1/*! 2 * jQuery JavaScript Library v1.3.2 3 * http://jquery.com/ 4 * 5 * Copyright (c) 2009 John Resig 6 * Dual licensed under the MIT and GPL licenses. 7 * http://docs.jquery.com/License 8 * 9 * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009) 10 * Revision: 6246 11 */ 12(function(){ 13 14var 15 // Will speed up references to window, and allows munging its name. 16 window = this, 17 // Will speed up references to undefined, and allows munging its name. 18 undefined, 19 // Map over jQuery in case of overwrite 20 _jQuery = window.jQuery, 21 // Map over the $ in case of overwrite 22 _$ = window.$, 23 24 jQuery = window.jQuery = window.$ = function( selector, context ) { 25 // The jQuery object is actually just the init constructor 'enhanced' 26 return new jQuery.fn.init( selector, context ); 27 }, 28 29 // A simple way to check for HTML strings or ID strings 30 // (both of which we optimize for) 31 quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/, 32 // Is it a simple selector 33 isSimple = /^.[^:#\[\.,]*$/; 34 35jQuery.fn = jQuery.prototype = { 36 init: function( selector, context ) { 37 // Make sure that a selection was provided 38 selector = selector || document; 39 40 // Handle $(DOMElement) 41 if ( selector.nodeType ) { 42 this[0] = selector; 43 this.length = 1; 44 this.context = selector; 45 return this; 46 } 47 // Handle HTML strings 48 if ( typeof selector === "string" ) { 49 // Are we dealing with HTML string or an ID? 50 var match = quickExpr.exec( selector ); 51 52 // Verify a match, and that no context was specified for #id 53 if ( match && (match[1] || !context) ) { 54 55 // HANDLE: $(html) -> $(array) 56 if ( match[1] ) 57 selector = jQuery.clean( [ match[1] ], context ); 58 59 // HANDLE: $("#id") 60 else { 61 var elem = document.getElementById( match[3] ); 62 63 // Handle the case where IE and Opera return items 64 // by name instead of ID 65 if ( elem && elem.id != match[3] ) 66 return jQuery().find( selector ); 67 68 // Otherwise, we inject the element directly into the jQuery object 69 var ret = jQuery( elem || [] ); 70 ret.context = document; 71 ret.selector = selector; 72 return ret; 73 } 74 75 // HANDLE: $(expr, [context]) 76 // (which is just equivalent to: $(content).find(expr) 77 } else 78 return jQuery( context ).find( selector ); 79 80 // HANDLE: $(function) 81 // Shortcut for document ready 82 } else if ( jQuery.isFunction( selector ) ) 83 return jQuery( document ).ready( selector ); 84 85 // Make sure that old selector state is passed along 86 if ( selector.selector && selector.context ) { 87 this.selector = selector.selector; 88 this.context = selector.context; 89 } 90 91 return this.setArray(jQuery.isArray( selector ) ? 92 selector : 93 jQuery.makeArray(selector)); 94 }, 95 96 // Start with an empty selector 97 selector: "", 98 99 // The current version of jQuery being used 100 jquery: "1.3.2", 101 102 // The number of elements contained in the matched element set 103 size: function() { 104 return this.length; 105 }, 106 107 // Get the Nth element in the matched element set OR 108 // Get the whole matched element set as a clean array 109 get: function( num ) { 110 return num === undefined ? 111 112 // Return a 'clean' array 113 Array.prototype.slice.call( this ) : 114 115 // Return just the object 116 this[ num ]; 117 }, 118 119 // Take an array of elements and push it onto the stack 120 // (returning the new matched element set) 121 pushStack: function( elems, name, selector ) { 122 // Build a new jQuery matched element set 123 var ret = jQuery( elems ); 124 125 // Add the old object onto the stack (as a reference) 126 ret.prevObject = this; 127 128 ret.context = this.context; 129 130 if ( name === "find" ) 131 ret.selector = this.selector + (this.selector ? " " : "") + selector; 132 else if ( name ) 133 ret.selector = this.selector + "." + name + "(" + selector + ")"; 134 135 // Return the newly-formed element set 136 return ret; 137 }, 138 139 // Force the current matched set of elements to become 140 // the specified array of elements (destroying the stack in the process) 141 // You should use pushStack() in order to do this, but maintain the stack 142 setArray: function( elems ) { 143 // Resetting the length to 0, then using the native Array push 144 // is a super-fast way to populate an object with array-like properties 145 this.length = 0; 146 Array.prototype.push.apply( this, elems ); 147 148 return this; 149 }, 150 151 // Execute a callback for every element in the matched set. 152 // (You can seed the arguments with an array of args, but this is 153 // only used internally.) 154 each: function( callback, args ) { 155 return jQuery.each( this, callback, args ); 156 }, 157 158 // Determine the position of an element within 159 // the matched set of elements 160 index: function( elem ) { 161 // Locate the position of the desired element 162 return jQuery.inArray( 163 // If it receives a jQuery object, the first element is used 164 elem && elem.jquery ? elem[0] : elem 165 , this ); 166 }, 167 168 attr: function( name, value, type ) { 169 var options = name; 170 171 // Look for the case where we're accessing a style value 172 if ( typeof name === "string" ) 173 if ( value === undefined ) 174 return this[0] && jQuery[ type || "attr" ]( this[0], name ); 175 176 else { 177 options = {}; 178 options[ name ] = value; 179 } 180 181 // Check to see if we're setting style values 182 return this.each(function(i){ 183 // Set all the styles 184 for ( name in options ) 185 jQuery.attr( 186 type ? 187 this.style : 188 this, 189 name, jQuery.prop( this, options[ name ], type, i, name ) 190 ); 191 }); 192 }, 193 194 css: function( key, value ) { 195 // ignore negative width and height values 196 if ( (key == 'width' || key == 'height') && parseFloat(value) < 0 ) 197 value = undefined; 198 return this.attr( key, value, "curCSS" ); 199 }, 200 201 text: function( text ) { 202 if ( typeof text !== "object" && text != null ) 203 return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) ); 204 205 var ret = ""; 206 207 jQuery.each( text || this, function(){ 208 jQuery.each( this.childNodes, function(){ 209 if ( this.nodeType != 8 ) 210 ret += this.nodeType != 1 ? 211 this.nodeValue : 212 jQuery.fn.text( [ this ] ); 213 }); 214 }); 215 216 return ret; 217 }, 218 219 wrapAll: function( html ) { 220 if ( this[0] ) { 221 // The elements to wrap the target around 222 var wrap = jQuery( html, this[0].ownerDocument ).clone(); 223 224 if ( this[0].parentNode ) 225 wrap.insertBefore( this[0] ); 226 227 wrap.map(function(){ 228 var elem = this; 229 230 while ( elem.firstChild ) 231 elem = elem.firstChild; 232 233 return elem; 234 }).append(this); 235 } 236 237 return this; 238 }, 239 240 wrapInner: function( html ) { 241 return this.each(function(){ 242 jQuery( this ).contents().wrapAll( html ); 243 }); 244 }, 245 246 wrap: function( html ) { 247 return this.each(function(){ 248 jQuery( this ).wrapAll( html ); 249 }); 250 }, 251 252 append: function() { 253 return this.domManip(arguments, true, function(elem){ 254 if (this.nodeType == 1) 255 this.appendChild( elem ); 256 }); 257 }, 258 259 prepend: function() { 260 return this.domManip(arguments, true, function(elem){ 261 if (this.nodeType == 1) 262 this.insertBefore( elem, this.firstChild ); 263 }); 264 }, 265 266 before: function() { 267 return this.domManip(arguments, false, function(elem){ 268 this.parentNode.insertBefore( elem, this ); 269 }); 270 }, 271 272 after: function() { 273 return this.domManip(arguments, false, function(elem){ 274 this.parentNode.insertBefore( elem, this.nextSibling ); 275 }); 276 }, 277 278 end: function() { 279 return this.prevObject || jQuery( [] ); 280 }, 281 282 // For internal use only. 283 // Behaves like an Array's method, not like a jQuery method. 284 push: [].push, 285 sort: [].sort, 286 splice: [].splice, 287 288 find: function( selector ) { 289 if ( this.length === 1 ) { 290 var ret = this.pushStack( [], "find", selector ); 291 ret.length = 0; 292 jQuery.find( selector, this[0], ret ); 293 return ret; 294 } else { 295 return this.pushStack( jQuery.unique(jQuery.map(this, function(elem){ 296 return jQuery.find( selector, elem ); 297 })), "find", selector ); 298 } 299 }, 300 301 clone: function( events ) { 302 // Do the clone 303 var ret = this.map(function(){ 304 if ( !jQuery.support.noCloneEvent && !jQuery.isXMLDoc(this) ) { 305 // IE copies events bound via attachEvent when 306 // using cloneNode. Calling detachEvent on the 307 // clone will also remove the events from the orignal 308 // In order to get around this, we use innerHTML. 309 // Unfortunately, this means some modifications to 310 // attributes in IE that are actually only stored 311 // as properties will not be copied (such as the 312 // the name attribute on an input). 313 var html = this.outerHTML; 314 if ( !html ) { 315 var div = this.ownerDocument.createElement("div"); 316 div.appendChild( this.cloneNode(true) ); 317 html = div.innerHTML; 318 } 319 320 return jQuery.clean([html.replace(/ jQuery\d+="(?:\d+|null)"/g, "").replace(/^\s*/, "")])[0]; 321 } else 322 return this.cloneNode(true); 323 }); 324 325 // Copy the events from the original to the clone 326 if ( events === true ) { 327 var orig = this.find("*").andSelf(), i = 0; 328 329 ret.find("*").andSelf().each(function(){ 330 if ( this.nodeName !== orig[i].nodeName ) 331 return; 332 333 var events = jQuery.data( orig[i], "events" ); 334 335 for ( var type in events ) { 336 for ( var handler in events[ type ] ) { 337 jQuery.event.add( this, type, events[ type ][ handler ], events[ type ][ handler ].data ); 338 } 339 } 340 341 i++; 342 }); 343 } 344 345 // Return the cloned set 346 return ret; 347 }, 348 349 filter: function( selector ) { 350 return this.pushStack( 351 jQuery.isFunction( selector ) && 352 jQuery.grep(this, function(elem, i){ 353 return selector.call( elem, i ); 354 }) || 355 356 jQuery.multiFilter( selector, jQuery.grep(this, function(elem){ 357 return elem.nodeType === 1; 358 }) ), "filter", selector ); 359 }, 360 361 closest: function( selector ) { 362 var pos = jQuery.expr.match.POS.test( selector ) ? jQuery(selector) : null, 363 closer = 0; 364 365 return this.map(function(){ 366 var cur = this; 367 while ( cur && cur.ownerDocument ) { 368 if ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selector) ) { 369 jQuery.data(cur, "closest", closer); 370 return cur; 371 } 372 cur = cur.parentNode; 373 closer++; 374 } 375 }); 376 }, 377 378 not: function( selector ) { 379 if ( typeof selector === "string" ) 380 // test special case where just one selector is passed in 381 if ( isSimple.test( selector ) ) 382 return this.pushStack( jQuery.multiFilter( selector, this, true ), "not", selector ); 383 else 384 selector = jQuery.multiFilter( selector, this ); 385 386 var isArrayLike = selector.length && selector[selector.length - 1] !== undefined && !selector.nodeType; 387 return this.filter(function() { 388 return isArrayLike ? jQuery.inArray( this, selector ) < 0 : this != selector; 389 }); 390 }, 391 392 add: function( selector ) { 393 return this.pushStack( jQuery.unique( jQuery.merge( 394 this.get(), 395 typeof selector === "string" ? 396 jQuery( selector ) : 397 jQuery.makeArray( selector ) 398 ))); 399 }, 400 401 is: function( selector ) { 402 return !!selector && jQuery.multiFilter( selector, this ).length > 0; 403 }, 404 405 hasClass: function( selector ) { 406 return !!selector && this.is( "." + selector ); 407 }, 408 409 val: function( value ) { 410 if ( value === undefined ) { 411 var elem = this[0]; 412 413 if ( elem ) { 414 if( jQuery.nodeName( elem, 'option' ) ) 415 return (elem.attributes.value || {}).specified ? elem.value : elem.text; 416 417 // We need to handle select boxes special 418 if ( jQuery.nodeName( elem, "select" ) ) { 419 var index = elem.selectedIndex, 420 values = [], 421 options = elem.options, 422 one = elem.type == "select-one"; 423 424 // Nothing was selected 425 if ( index < 0 ) 426 return null; 427 428 // Loop through all the selected options 429 for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) { 430 var option = options[ i ]; 431 432 if ( option.selected ) { 433 // Get the specifc value for the option 434 value = jQuery(option).val(); 435 436 // We don't need an array for one selects 437 if ( one ) 438 return value; 439 440 // Multi-Selects return an array 441 values.push( value ); 442 } 443 } 444 445 return values; 446 } 447 448 // Everything else, we just grab the value 449 return (elem.value || "").replace(/\r/g, ""); 450 451 } 452 453 return undefined; 454 } 455 456 if ( typeof value === "number" ) 457 value += ''; 458 459 return this.each(function(){ 460 if ( this.nodeType != 1 ) 461 return; 462 463 if ( jQuery.isArray(value) && /radio|checkbox/.test( this.type ) ) 464 this.checked = (jQuery.inArray(this.value, value) >= 0 || 465 jQuery.inArray(this.name, value) >= 0); 466 467 else if ( jQuery.nodeName( this, "select" ) ) { 468 var values = jQuery.makeArray(value); 469 470 jQuery( "option", this ).each(function(){ 471 this.selected = (jQuery.inArray( this.value, values ) >= 0 || 472 jQuery.inArray( this.text, values ) >= 0); 473 }); 474 475 if ( !values.length ) 476 this.selectedIndex = -1; 477 478 } else 479 this.value = value; 480 }); 481 }, 482 483 html: function( value ) { 484 return value === undefined ? 485 (this[0] ? 486 this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g, "") : 487 null) : 488 this.empty().append( value ); 489 }, 490 491 replaceWith: function( value ) { 492 return this.after( value ).remove(); 493 }, 494 495 eq: function( i ) { 496 return this.slice( i, +i + 1 ); 497 }, 498 499 slice: function() { 500 return this.pushStack( Array.prototype.slice.apply( this, arguments ), 501 "slice", Array.prototype.slice.call(arguments).join(",") ); 502 }, 503 504 map: function( callback ) { 505 return this.pushStack( jQuery.map(this, function(elem, i){ 506 return callback.call( elem, i, elem ); 507 })); 508 }, 509 510 andSelf: function() { 511 return this.add( this.prevObject ); 512 }, 513 514 domManip: function( args, table, callback ) { 515 if ( this[0] ) { 516 var fragment = (this[0].ownerDocument || this[0]).createDocumentFragment(), 517 scripts = jQuery.clean( args, (this[0].ownerDocument || this[0]), fragment ), 518 first = fragment.firstChild; 519 520 if ( first ) 521 for ( var i = 0, l = this.length; i < l; i++ ) 522 callback.call( root(this[i], first), this.length > 1 || i > 0 ? 523 fragment.cloneNode(true) : fragment ); 524 525 if ( scripts ) 526 jQuery.each( scripts, evalScript ); 527 } 528 529 return this; 530 531 function root( elem, cur ) { 532 return table && jQuery.nodeName(elem, "table") && jQuery.nodeName(cur, "tr") ? 533 (elem.getElementsByTagName("tbody")[0] || 534 elem.appendChild(elem.ownerDocument.createElement("tbody"))) : 535 elem; 536 } 537 } 538}; 539 540// Give the init function the jQuery prototype for later instantiation 541jQuery.fn.init.prototype = jQuery.fn; 542 543function evalScript( i, elem ) { 544 if ( elem.src ) 545 jQuery.ajax({ 546 url: elem.src, 547 async: false, 548 dataType: "script" 549 }); 550 551 else 552 jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" ); 553 554 if ( elem.parentNode ) 555 elem.parentNode.removeChild( elem ); 556} 557 558function now(){ 559 return +new Date; 560} 561 562jQuery.extend = jQuery.fn.extend = function() { 563 // copy reference to target object 564 var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options; 565 566 // Handle a deep copy situation 567 if ( typeof target === "boolean" ) { 568 deep = target; 569 target = arguments[1] || {}; 570 // skip the boolean and the target 571 i = 2; 572 } 573 574 // Handle case when target is a string or something (possible in deep copy) 575 if ( typeof target !== "object" && !jQuery.isFunction(target) ) 576 target = {}; 577 578 // extend jQuery itself if only one argument is passed 579 if ( length == i ) { 580 target = this; 581 --i; 582 } 583 584 for ( ; i < length; i++ ) 585 // Only deal with non-null/undefined values 586 if ( (options = arguments[ i ]) != null ) 587 // Extend the base object 588 for ( var name in options ) { 589 var src = target[ name ], copy = options[ name ]; 590 591 // Prevent never-ending loop 592 if ( target === copy ) 593 continue; 594 595 // Recurse if we're merging object values 596 if ( deep && copy && typeof copy === "object" && !copy.nodeType ) 597 target[ name ] = jQuery.extend( deep, 598 // Never move original objects, clone them 599 src || ( copy.length != null ? [ ] : { } ) 600 , copy ); 601 602 // Don't bring in undefined values 603 else if ( copy !== undefined ) 604 target[ name ] = copy; 605 606 } 607 608 // Return the modified object 609 return target; 610}; 611 612// exclude the following css properties to add px 613var exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i, 614 // cache defaultView 615 defaultView = document.defaultView || {}, 616 toString = Object.prototype.toString; 617 618jQuery.extend({ 619 noConflict: function( deep ) { 620 window.$ = _$; 621 622 if ( deep ) 623 window.jQuery = _jQuery; 624 625 return jQuery; 626 }, 627 628 // See test/unit/core.js for details concerning isFunction. 629 // Since version 1.3, DOM methods and functions like alert 630 // aren't supported. They return false on IE (#2968). 631 isFunction: function( obj ) { 632 return toString.call(obj) === "[object Function]"; 633 }, 634 635 isArray: function( obj ) { 636 return toString.call(obj) === "[object Array]"; 637 }, 638 639 // check if an element is in a (or is an) XML document 640 isXMLDoc: function( elem ) { 641 return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" || 642 !!elem.ownerDocument && jQuery.isXMLDoc( elem.ownerDocument ); 643 }, 644 645 // Evalulates a script in a global context 646 globalEval: function( data ) { 647 if ( data && /\S/.test(data) ) { 648 // Inspired by code by Andrea Giammarchi 649 // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html 650 var head = document.getElementsByTagName("head")[0] || document.documentElement, 651 script = document.createElement("script"); 652 653 script.type = "text/javascript"; 654 if ( jQuery.support.scriptEval ) 655 script.appendChild( document.createTextNode( data ) ); 656 else 657 script.text = data; 658 659 // Use insertBefore instead of appendChild to circumvent an IE6 bug. 660 // This arises when a base node is used (#2709). 661 head.insertBefore( script, head.firstChild ); 662 head.removeChild( script ); 663 } 664 }, 665 666 nodeName: function( elem, name ) { 667 return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase(); 668 }, 669 670 // args is for internal usage only 671 each: function( object, callback, args ) { 672 var name, i = 0, length = object.length; 673 674 if ( args ) { 675 if ( length === undefined ) { 676 for ( name in object ) 677 if ( callback.apply( object[ name ], args ) === false ) 678 break; 679 } else 680 for ( ; i < length; ) 681 if ( callback.apply( object[ i++ ], args ) === false ) 682 break; 683 684 // A special, fast, case for the most common use of each 685 } else { 686 if ( length === undefined ) { 687 for ( name in object ) 688 if ( callback.call( object[ name ], name, object[ name ] ) === false ) 689 break; 690 } else 691 for ( var value = object[0]; 692 i < length && callback.call( value, i, value ) !== false; value = object[++i] ){} 693 } 694 695 return object; 696 }, 697 698 prop: function( elem, value, type, i, name ) { 699 // Handle executable functions 700 if ( jQuery.isFunction( value ) ) 701 value = value.call( elem, i ); 702 703 // Handle passing in a number to a CSS property 704 return typeof value === "number" && type == "curCSS" && !exclude.test( name ) ? 705 value + "px" : 706 value; 707 }, 708 709 className: { 710 // internal only, use addClass("class") 711 add: function( elem, classNames ) { 712 jQuery.each((classNames || "").split(/\s+/), function(i, className){ 713 if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) ) 714 elem.className += (elem.className ? " " : "") + className; 715 }); 716 }, 717 718 // internal only, use removeClass("class") 719 remove: function( elem, classNames ) { 720 if (elem.nodeType == 1) 721 elem.className = classNames !== undefined ? 722 jQuery.grep(elem.className.split(/\s+/), function(className){ 723 return !jQuery.className.has( classNames, className ); 724 }).join(" ") : 725 ""; 726 }, 727 728 // internal only, use hasClass("class") 729 has: function( elem, className ) { 730 return elem && jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1; 731 } 732 }, 733 734 // A method for quickly swapping in/out CSS properties to get correct calculations 735 swap: function( elem, options, callback ) { 736 var old = {}; 737 // Remember the old values, and insert the new ones 738 for ( var name in options ) { 739 old[ name ] = elem.style[ name ]; 740 elem.style[ name ] = options[ name ]; 741 } 742 743 callback.call( elem ); 744 745 // Revert the old values 746 for ( var name in options ) 747 elem.style[ name ] = old[ name ]; 748 }, 749 750 css: function( elem, name, force, extra ) { 751 if ( name == "width" || name == "height" ) { 752 var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ]; 753 754 function getWH() { 755 val = name == "width" ? elem.offsetWidth : elem.offsetHeight; 756 757 if ( extra === "border" ) 758 return; 759 760 jQuery.each( which, function() { 761 if ( !extra ) 762 val -= parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0; 763 if ( extra === "margin" ) 764 val += parseFloat(jQuery.curCSS( elem, "margin" + this, true)) || 0; 765 else 766 val -= parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0; 767 }); 768 } 769 770 if ( elem.offsetWidth !== 0 ) 771 getWH(); 772 else 773 jQuery.swap( elem, props, getWH ); 774 775 return Math.max(0, Math.round(val)); 776 } 777 778 return jQuery.curCSS( elem, name, force ); 779 }, 780 781 curCSS: function( elem, name, force ) { 782 var ret, style = elem.style; 783 784 // We need to handle opacity special in IE 785 if ( name == "opacity" && !jQuery.support.opacity ) { 786 ret = jQuery.attr( style, "opacity" ); 787 788 return ret == "" ? 789 "1" : 790 ret; 791 } 792 793 // Make sure we're using the right name for getting the float value 794 if ( name.match( /float/i ) ) 795 name = styleFloat; 796 797 if ( !force && style && style[ name ] ) 798 ret = style[ name ]; 799 800 else if ( defaultView.getComputedStyle ) { 801 802 // Only "float" is needed here 803 if ( name.match( /float/i ) ) 804 name = "float"; 805 806 name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase(); 807 808 var computedStyle = defaultView.getComputedStyle( elem, null ); 809 810 if ( computedStyle ) 811 ret = computedStyle.getPropertyValue( name ); 812 813 // We should always get a number back from opacity 814 if ( name == "opacity" && ret == "" ) 815 ret = "1"; 816 817 } else if ( elem.currentStyle ) { 818 var camelCase = name.replace(/\-(\w)/g, function(all, letter){ 819 return letter.toUpperCase(); 820 }); 821 822 ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ]; 823 824 // From the awesome hack by Dean Edwards 825 // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 826 827 // If we're not dealing with a regular pixel number 828 // but a number that has a weird ending, we need to convert it to pixels 829 if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) { 830 // Remember the original values 831 var left = style.left, rsLeft = elem.runtimeStyle.left; 832 833 // Put in the new values to get a computed value out 834 elem.runtimeStyle.left = elem.currentStyle.left; 835 style.left = ret || 0; 836 ret = style.pixelLeft + "px"; 837 838 // Revert the changed values 839 style.left = left; 840 elem.runtimeStyle.left = rsLeft; 841 } 842 } 843 844 return ret; 845 }, 846 847 clean: function( elems, context, fragment ) { 848 context = context || document; 849 850 // !context.createElement fails in IE with an error but returns typeof 'object' 851 if ( typeof context.createElement === "undefined" ) 852 context = context.ownerDocument || context[0] && context[0].ownerDocument || document; 853 854 // If a single string is passed in and it's a single tag 855 // just do a createElement and skip the rest 856 if ( !fragment && elems.length === 1 && typeof elems[0] === "string" ) { 857 var match = /^<(\w+)\s*\/?>$/.exec(elems[0]); 858 if ( match ) 859 return [ context.createElement( match[1] ) ]; 860 } 861 862 var ret = [], scripts = [], div = context.createElement("div"); 863 864 jQuery.each(elems, function(i, elem){ 865 if ( typeof elem === "number" ) 866 elem += ''; 867 868 if ( !elem ) 869 return; 870 871 // Convert html string into DOM nodes 872 if ( typeof elem === "string" ) { 873 // Fix "XHTML"-style tags in all browsers 874 elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){ 875 return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ? 876 all : 877 front + "></" + tag + ">"; 878 }); 879 880 // Trim whitespace, otherwise indexOf won't work as expected 881 var tags = elem.replace(/^\s+/, "").substring(0, 10).toLowerCase(); 882 883 var wrap = 884 // option or optgroup 885 !tags.indexOf("<opt") && 886 [ 1, "<select multiple='multiple'>", "</select>" ] || 887 888 !tags.indexOf("<leg") && 889 [ 1, "<fieldset>", "</fieldset>" ] || 890 891 tags.match(/^<(thead|tbody|tfoot|colg|cap)/) && 892 [ 1, "<table>", "</table>" ] || 893 894 !tags.indexOf("<tr") && 895 [ 2, "<table><tbody>", "</tbody></table>" ] || 896 897 // <thead> matched above 898 (!tags.indexOf("<td") || !tags.indexOf("<th")) && 899 [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ] || 900 901 !tags.indexOf("<col") && 902 [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ] || 903 904 // IE can't serialize <link> and <script> tags normally 905 !jQuery.support.htmlSerialize && 906 [ 1, "div<div>", "</div>" ] || 907 908 [ 0, "", "" ]; 909 910 // Go to html and back, then peel off extra wrappers 911 div.innerHTML = wrap[1] + elem + wrap[2]; 912 913 // Move to the right depth 914 while ( wrap[0]-- ) 915 div = div.lastChild; 916 917 // Remove IE's autoinserted <tbody> from table fragments 918 if ( !jQuery.support.tbody ) { 919 920 // String was a <table>, *may* have spurious <tbody> 921 var hasBody = /<tbody/i.test(elem), 922 tbody = !tags.indexOf("<table") && !hasBody ? 923 div.firstChild && div.firstChild.childNodes : 924 925 // String was a bare <thead> or <tfoot> 926 wrap[1] == "<table>" && !hasBody ? 927 div.childNodes : 928 []; 929 930 for ( var j = tbody.length - 1; j >= 0 ; --j ) 931 if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) 932 tbody[ j ].parentNode.removeChild( tbody[ j ] ); 933 934 } 935 936 // IE completely kills leading whitespace when innerHTML is used 937 if ( !jQuery.support.leadingWhitespace && /^\s/.test( elem ) ) 938 div.insertBefore( context.createTextNode( elem.match(/^\s*/)[0] ), div.firstChild ); 939 940 elem = jQuery.makeArray( div.childNodes ); 941 } 942 943 if ( elem.nodeType ) 944 ret.push( elem ); 945 else 946 ret = jQuery.merge( ret, elem ); 947 948 }); 949 950 if ( fragment ) { 951 for ( var i = 0; ret[i]; i++ ) { 952 if ( jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) { 953 scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] ); 954 } else { 955 if ( ret[i].nodeType === 1 ) 956 ret.splice.apply( ret, [i + 1, 0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))) ); 957 fragment.appendChild( ret[i] ); 958 } 959 } 960 961 return scripts; 962 } 963 964 return ret; 965 }, 966 967 attr: function( elem, name, value ) { 968 // don't set attributes on text and comment nodes 969 if (!elem || elem.nodeType == 3 || elem.nodeType == 8) 970 return undefined; 971 972 var notxml = !jQuery.isXMLDoc( elem ), 973 // Whether we are setting (or getting) 974 set = value !== undefined; 975 976 // Try to normalize/fix the name 977 name = notxml && jQuery.props[ name ] || name; 978 979 // Only do all the following if this is a node (faster for style) 980 // IE elem.getAttribute passes even for style 981 if ( elem.tagName ) { 982 983 // These attributes require special treatment 984 var special = /href|src|style/.test( name ); 985 986 // Safari mis-reports the default selected property of a hidden option 987 // Accessing the parent's selectedIndex property fixes it 988 if ( name == "selected" && elem.parentNode ) 989 elem.parentNode.selectedIndex; 990 991 // If applicable, access the attribute via the DOM 0 way 992 if ( name in elem && notxml && !special ) { 993 if ( set ){ 994 // We can't allow the type property to be changed (since it causes problems in IE) 995 if ( name == "type" && jQuery.nodeName( elem, "input" ) && elem.parentNode ) 996 throw "type property can't be changed"; 997 998 elem[ name ] = value; 999 } 1000 1001 // browsers index elements by id/name on forms, give priority to attributes. 1002 if( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) ) 1003 return elem.getAttributeNode( name ).nodeValue; 1004 1005 // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set 1006 // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ 1007 if ( name == "tabIndex" ) { 1008 var attributeNode = elem.getAttributeNode( "tabIndex" ); 1009 return attributeNode && attributeNode.specified 1010 ? attributeNode.value 1011 : elem.nodeName.match(/(button|input|object|select|textarea)/i) 1012 ? 0 1013 : elem.nodeName.match(/^(a|area)$/i) && elem.href 1014 ? 0 1015 : undefined; 1016 } 1017 1018 return elem[ name ]; 1019 } 1020 1021 if ( !jQuery.support.style && notxml && name == "style" ) 1022 return jQuery.attr( elem.style, "cssText", value ); 1023 1024 if ( set ) 1025 // convert the value to a string (all browsers do this but IE) see #1070 1026 elem.setAttribute( name, "" + value ); 1027 1028 var attr = !jQuery.support.hrefNormalized && notxml && special 1029 // Some attributes require a special call on IE 1030 ? elem.getAttribute( name, 2 ) 1031 : elem.getAttribute( name ); 1032 1033 // Non-existent attributes return null, we normalize to undefined 1034 return attr === null ? undefined : attr; 1035 } 1036 1037 // elem is actually elem.style ... set the style 1038 1039 // IE uses filters for opacity 1040 if ( !jQuery.support.opacity && name == "opacity" ) { 1041 if ( set ) { 1042 // IE has trouble with opacity if it does not have layout 1043 // Force it by setting the zoom level 1044 elem.zoom = 1; 1045 1046 // Set the alpha filter to set the opacity 1047 elem.filter = (elem.filter || "").replace( /alpha\([^)]*\)/, "" ) + 1048 (parseInt( value ) + '' == "NaN" ? "" : "alpha(opacity=" + value * 100 + ")"); 1049 } 1050 1051 return elem.filter && elem.filter.indexOf("opacity=") >= 0 ? 1052 (parseFloat( elem.filter.match(/opacity=([^)]*)/)[1] ) / 100) + '': 1053 ""; 1054 } 1055 1056 name = name.replace(/-([a-z])/ig, function(all, letter){ 1057 return letter.toUpperCase(); 1058 }); 1059 1060 if ( set ) 1061 elem[ name ] = value; 1062 1063 return elem[ name ]; 1064 }, 1065 1066 trim: function( text ) { 1067 return (text || "").replace( /^\s+|\s+$/g, "" ); 1068 }, 1069 1070 makeArray: function( array ) { 1071 var ret = []; 1072 1073 if( array != null ){ 1074 var i = array.length; 1075 // The window, strings (and functions) also have 'length' 1076 if( i == null || typeof array === "string" || jQuery.isFunction(array) || array.setInterval ) 1077 ret[0] = array; 1078 else 1079 while( i ) 1080 ret[--i] = array[i]; 1081 } 1082 1083 return ret; 1084 }, 1085 1086 inArray: function( elem, array ) { 1087 for ( var i = 0, length = array.length; i < length; i++ ) 1088 // Use === because on IE, window == document 1089 if ( array[ i ] === elem ) 1090 return i; 1091 1092 return -1; 1093 }, 1094 1095 merge: function( first, second ) { 1096 // We have to loop this way because IE & Opera overwrite the length 1097 // expando of getElementsByTagName 1098 var i = 0, elem, pos = first.length; 1099 // Also, we need to make sure that the correct elements are being returned 1100 // (IE returns comment nodes in a '*' query) 1101 if ( !jQuery.support.getAll ) { 1102 while ( (elem = second[ i++ ]) != null ) 1103 if ( elem.nodeType != 8 ) 1104 first[ pos++ ] = elem; 1105 1106 } else 1107 while ( (elem = second[ i++ ]) != null ) 1108 first[ pos++ ] = elem; 1109 1110 return first; 1111 }, 1112 1113 unique: function( array ) { 1114 var ret = [], done = {}; 1115 1116 try { 1117 1118 for ( var i = 0, length = array.length; i < length; i++ ) { 1119 var id = jQuery.data( array[ i ] ); 1120 1121 if ( !done[ id ] ) { 1122 done[ id ] = true; 1123 ret.push( array[ i ] ); 1124 } 1125 } 1126 1127 } catch( e ) { 1128 ret = array; 1129 } 1130 1131 return ret; 1132 }, 1133 1134 grep: function( elems, callback, inv ) { 1135 var ret = []; 1136 1137 // Go through the array, only saving the items 1138 // that pass the validator function 1139 for ( var i = 0, length = elems.length; i < length; i++ ) 1140 if ( !inv != !callback( elems[ i ], i ) ) 1141 ret.push( elems[ i ] ); 1142 1143 return ret; 1144 }, 1145 1146 map: function( elems, callback ) { 1147 var ret = []; 1148 1149 // Go through the array, translating each of the items to their 1150 // new value (or values). 1151 for ( var i = 0, length = elems.length; i < length; i++ ) { 1152 var value = callback( elems[ i ], i ); 1153 1154 if ( value != null ) 1155 ret[ ret.length ] = value; 1156 } 1157 1158 return ret.concat.apply( [], ret ); 1159 } 1160}); 1161 1162// Use of jQuery.browser is deprecated. 1163// It's included for backwards compatibility and plugins, 1164// although they should work to migrate away. 1165 1166var userAgent = navigator.userAgent.toLowerCase(); 1167 1168// Figure out what browser is being used 1169jQuery.browser = { 1170 version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [0,'0'])[1], 1171 safari: /webkit/.test( userAgent ), 1172 opera: /opera/.test( userAgent ), 1173 msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ), 1174 mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent ) 1175}; 1176 1177jQuery.each({ 1178 parent: function(elem){return elem.parentNode;}, 1179 parents: function(elem){return jQuery.dir(elem,"parentNode");}, 1180 next: function(elem){return jQuery.nth(elem,2,"nextSibling");}, 1181 prev: function(elem){return jQuery.nth(elem,2,"previousSibling");}, 1182 nextAll: function(elem){return jQuery.dir(elem,"nextSibling");}, 1183 prevAll: function(elem){return jQuery.dir(elem,"previousSibling");}, 1184 siblings: function(elem){return jQuery.sibling(elem.parentNode.firstChild,elem);}, 1185 children: function(elem){return jQuery.sibling(elem.firstChild);}, 1186 contents: function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes);} 1187}, function(name, fn){ 1188 jQuery.fn[ name ] = function( selector ) { 1189 var ret = jQuery.map( this, fn ); 1190 1191 if ( selector && typeof selector == "string" ) 1192 ret = jQuery.multiFilter( selector, ret ); 1193 1194 return this.pushStack( jQuery.unique( ret ), name, selector ); 1195 }; 1196}); 1197 1198jQuery.each({ 1199 appendTo: "append", 1200 prependTo: "prepend", 1201 insertBefore: "before", 1202 insertAfter: "after", 1203 replaceAll: "replaceWith" 1204}, function(name, original){ 1205 jQuery.fn[ name ] = function( selector ) { 1206 var ret = [], insert = jQuery( selector ); 1207 1208 for ( var i = 0, l = insert.length; i < l; i++ ) { 1209 var elems = (i > 0 ? this.clone(true) : this).get(); 1210 jQuery.fn[ original ].apply( jQuery(insert[i]), elems ); 1211 ret = ret.concat( elems ); 1212 } 1213 1214 return this.pushStack( ret, name, selector ); 1215 }; 1216}); 1217 1218jQuery.each({ 1219 removeAttr: function( name ) { 1220 jQuery.attr( this, name, "" ); 1221 if (this.nodeType == 1) 1222 this.removeAttribute( name ); 1223 }, 1224 1225 addClass: function( classNames ) { 1226 jQuery.className.add( this, classNames ); 1227 }, 1228 1229 removeClass: function( classNames ) { 1230 jQuery.className.remove( this, classNames ); 1231 }, 1232 1233 toggleClass: function( classNames, state ) { 1234 if( typeof state !== "boolean" ) 1235 state = !jQuery.className.has( this, classNames ); 1236 jQuery.className[ state ? "add" : "remove" ]( this, classNames ); 1237 }, 1238 1239 remove: function( selector ) { 1240 if ( !selector || jQuery.filter( selector, [ this ] ).length ) { 1241 // Prevent memory leaks 1242 jQuery( "*", this ).add([this]).each(function(){ 1243 jQuery.event.remove(this); 1244 jQuery.removeData(this); 1245 }); 1246 if (this.parentNode) 1247 this.parentNode.removeChild( this ); 1248 } 1249 }, 1250 1251 empty: function() { 1252 // Remove element nodes and prevent memory leaks 1253 jQuery(this).children().remove(); 1254 1255 // Remove any remaining nodes 1256 while ( this.firstChild ) 1257 this.removeChild( this.firstChild ); 1258 } 1259}, function(name, fn){ 1260 jQuery.fn[ name ] = function(){ 1261 return this.each( fn, arguments ); 1262 }; 1263}); 1264 1265// Helper function used by the dimensions and offset modules 1266function num(elem, prop) { 1267 return elem[0] && parseInt( jQuery.curCSS(elem[0], prop, true), 10 ) || 0; 1268} 1269var expando = "jQuery" + now(), uuid = 0, windowData = {}; 1270 1271jQuery.extend({ 1272 cache: {}, 1273 1274 data: function( elem, name, data ) { 1275 elem = elem == window ? 1276 windowData : 1277 elem; 1278 1279 var id = elem[ expando ]; 1280 1281 // Compute a unique ID for the element 1282 if ( !id ) 1283 id = elem[ expando ] = ++uuid; 1284 1285 // Only generate the data cache if we're 1286 // trying to access or manipulate it 1287 if ( name && !jQuery.cache[ id ] ) 1288 jQuery.cache[ id ] = {}; 1289 1290 // Prevent overriding the named cache with undefined values 1291 if ( data !== undefined ) 1292 jQuery.cache[ id ][ name ] = data; 1293 1294 // Return the named cache data, or the ID for the element 1295 return name ? 1296 jQuery.cache[ id ][ name ] : 1297 id; 1298 }, 1299 1300 removeData: function( elem, name ) { 1301 elem = elem == window ? 1302 windowData : 1303 elem; 1304 1305 var id = elem[ expando ]; 1306 1307 // If we want to remove a specific section of the element's data 1308 if ( name ) { 1309 if ( jQuery.cache[ id ] ) { 1310 // Remove the section of cache data 1311 delete jQuery.cache[ id ][ name ]; 1312 1313 // If we've removed all the data, remove the element's cache 1314 name = ""; 1315 1316 for ( name in jQuery.cache[ id ] ) 1317 break; 1318 1319 if ( !name ) 1320 jQuery.removeData( elem ); 1321 } 1322 1323 // Otherwise, we want to remove all of the element's data 1324 } else { 1325 // Clean up the element expando 1326 try { 1327 delete elem[ expando ]; 1328 } catch(e){ 1329 // IE has trouble directly removing the expando 1330 // but it's ok with using removeAttribute 1331 if ( elem.removeAttribute ) 1332 elem.removeAttribute( expando ); 1333 } 1334 1335 // Completely remove the data cache 1336 delete jQuery.cache[ id ]; 1337 } 1338 }, 1339 queue: function( elem, type, data ) { 1340 if ( elem ){ 1341 1342 type = (type || "fx") + "queue"; 1343 1344 var q = jQuery.data( elem, type ); 1345 1346 if ( !q || jQuery.isArray(data) ) 1347 q = jQuery.data( elem, type, jQuery.makeArray(data) ); 1348 else if( data ) 1349 q.push( data ); 1350 1351 } 1352 return q; 1353 }, 1354 1355 dequeue: function( elem, type ){ 1356 var queue = jQuery.queue( elem, type ), 1357 fn = queue.shift(); 1358 1359 if( !type || type === "fx" ) 1360 fn = queue[0]; 1361 1362 if( fn !== undefined ) 1363 fn.call(elem); 1364 } 1365}); 1366 1367jQuery.fn.extend({ 1368 data: function( key, value ){ 1369 var parts = key.split("."); 1370 parts[1] = parts[1] ? "." + parts[1] : ""; 1371 1372 if ( value === undefined ) { 1373 var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); 1374 1375 if ( data === undefined && this.length ) 1376 data = jQuery.data( this[0], key ); 1377 1378 return data === undefined && parts[1] ? 1379 this.data( parts[0] ) : 1380 data; 1381 } else 1382 return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function(){ 1383 jQuery.data( this, key, value ); 1384 }); 1385 }, 1386 1387 removeData: function( key ){ 1388 return this.each(function(){ 1389 jQuery.removeData( this, key ); 1390 }); 1391 }, 1392 queue: function(type, data){ 1393 if ( typeof type !== "string" ) { 1394 data = type; 1395 type = "fx"; 1396 } 1397 1398 if ( data === undefined ) 1399 return jQuery.queue( this[0], type ); 1400 1401 return this.each(function(){ 1402 var queue = jQuery.queue( this, type, data ); 1403 1404 if( type == "fx" && queue.length == 1 ) 1405 queue[0].call(this); 1406 }); 1407 }, 1408 dequeue: function(type){ 1409 return this.each(function(){ 1410 jQuery.dequeue( this, type ); 1411 }); 1412 } 1413});/*! 1414 * Sizzle CSS Selector Engine - v0.9.3 1415 * Copyright 2009, The Dojo Foundation 1416 * Released under the MIT, BSD, and GPL Licenses. 1417 * More information: http://sizzlejs.com/ 1418 */ 1419(function(){ 1420 1421var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g, 1422 done = 0, 1423 toString = Object.prototype.toString; 1424 1425var Sizzle = function(selector, context, results, seed) { 1426 results = results || []; 1427 context = context || document; 1428 1429 if ( context.nodeType !== 1 && context.nodeType !== 9 ) 1430 return []; 1431 1432 if ( !selector || typeof selector !== "string" ) { 1433 return results; 1434 } 1435 1436 var parts = [], m, set, checkSet, check, mode, extra, prune = true; 1437 1438 // Reset the position of the chunker regexp (start from head) 1439 chunker.lastIndex = 0; 1440 1441 while ( (m = chunker.exec(selector)) !== null ) { 1442 parts.push( m[1] ); 1443 1444 if ( m[2] ) { 1445 extra = RegExp.rightContext; 1446 break; 1447 } 1448 } 1449 1450 if ( parts.length > 1 && origPOS.exec( selector ) ) { 1451 if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { 1452 set = posProcess( parts[0] + parts[1], context ); 1453 } else { 1454 set = Expr.relative[ parts[0] ] ? 1455 [ context ] : 1456 Sizzle( parts.shift(), context ); 1457 1458 while ( parts.length ) { 1459 selector = parts.shift(); 1460 1461 if ( Expr.relative[ selector ] ) 1462 selector += parts.shift(); 1463 1464 set = posProcess( selector, set ); 1465 } 1466 } 1467 } else { 1468 var ret = seed ? 1469 { expr: parts.pop(), set: makeArray(seed) } : 1470 Sizzle.find( parts.pop(), parts.length === 1 && context.parentNode ? context.parentNode : context, isXML(context) ); 1471 set = Sizzle.filter( ret.expr, ret.set ); 1472 1473 if ( parts.length > 0 ) { 1474 checkSet = makeArray(set); 1475 } else { 1476 prune = false; 1477 } 1478 1479 while ( parts.length ) { 1480 var cur = parts.pop(), pop = cur; 1481 1482 if ( !Expr.relative[ cur ] ) { 1483 cur = ""; 1484 } else { 1485 pop = parts.pop(); 1486 } 1487 1488 if ( pop == null ) { 1489 pop = context; 1490 } 1491 1492 Expr.relative[ cur ]( checkSet, pop, isXML(context) ); 1493 } 1494 } 1495 1496 if ( !checkSet ) { 1497 checkSet = set; 1498 } 1499 1500 if ( !checkSet ) { 1501 throw "Syntax error, unrecognized expression: " + (cur || selector); 1502 } 1503 1504 if ( toString.call(checkSet) === "[object Array]" ) { 1505 if ( !prune ) { 1506 results.push.apply( results, checkSet ); 1507 } else if ( context.nodeType === 1 ) { 1508 for ( var i = 0; checkSet[i] != null; i++ ) { 1509 if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) { 1510 results.push( set[i] ); 1511 } 1512 } 1513 } else { 1514 for ( var i = 0; checkSet[i] != null; i++ ) { 1515 if ( checkSet[i] && checkSet[i].nodeType === 1 ) { 1516 results.push( set[i] ); 1517 } 1518 } 1519 } 1520 } else { 1521 makeArray( checkSet, results ); 1522 } 1523 1524 if ( extra ) { 1525 Sizzle( extra, context, results, seed ); 1526 1527 if ( sortOrder ) { 1528 hasDuplicate = false; 1529 results.sort(sortOrder); 1530 1531 if ( hasDuplicate ) { 1532 for ( var i = 1; i < results.length; i++ ) { 1533 if ( results[i] === results[i-1] ) { 1534 results.splice(i--, 1); 1535 } 1536 } 1537 } 1538 } 1539 } 1540 1541 return results; 1542}; 1543 1544Sizzle.matches = function(expr, set){ 1545 return Sizzle(expr, null, null, set); 1546}; 1547 1548Sizzle.find = function(expr, context, isXML){ 1549 var set, match; 1550 1551 if ( !expr ) { 1552 return []; 1553 } 1554 1555 for ( var i = 0, l = Expr.order.length; i < l; i++ ) { 1556 var type = Expr.order[i], match; 1557 1558 if ( (match = Expr.match[ type ].exec( expr )) ) { 1559 var left = RegExp.leftContext; 1560 1561 if ( left.substr( left.length - 1 ) !== "\\" ) { 1562 match[1] = (match[1] || "").replace(/\\/g, ""); 1563 set = Expr.find[ type ]( match, context, isXML ); 1564 if ( set != null ) { 1565 expr = expr.replace( Expr.match[ type ], "" ); 1566 break; 1567 } 1568 } 1569 } 1570 } 1571 1572 if ( !set ) { 1573 set = context.getElementsByTagName("*"); 1574 } 1575 1576 return {set: set, expr: expr}; 1577}; 1578 1579Sizzle.filter = function(expr, set, inplace, not){ 1580 var old = expr, result = [], curLoop = set, match, anyFound, 1581 isXMLFilter = set && set[0] && isXML(set[0]); 1582 1583 while ( expr && set.length ) { 1584 for ( var type in Expr.filter ) { 1585 if ( (match = Expr.match[ type ].exec( expr )) != null ) { 1586 var filter = Expr.filter[ type ], found, item; 1587 anyFound = false; 1588 1589 if ( curLoop == result ) { 1590 result = []; 1591 } 1592 1593 if ( Expr.preFilter[ type ] ) { 1594 match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); 1595 1596 if ( !match ) { 1597 anyFound = found = true; 1598 } else if ( match === true ) { 1599 continue; 1600 } 1601 } 1602 1603 if ( match ) { 1604 for ( var i = 0; (item = curLoop[i]) != null; i++ ) { 1605 if ( item ) { 1606 found = filter( item, match, i, curLoop ); 1607 var pass = not ^ !!found; 1608 1609 if ( inplace && found != null ) { 1610 if ( pass ) { 1611 anyFound = true; 1612 } else { 1613 curLoop[i] = false; 1614 } 1615 } else if ( pass ) { 1616 result.push( item ); 1617 anyFound = true; 1618 } 1619 } 1620 } 1621 } 1622 1623 if ( found !== undefined ) { 1624 if ( !inplace ) { 1625 curLoop = result; 1626 } 1627 1628 expr = expr.replace( Expr.match[ type ], "" ); 1629 1630 if ( !anyFound ) { 1631 return []; 1632 } 1633 1634 break; 1635 } 1636 } 1637 } 1638 1639 // Improper expression 1640 if ( expr == old ) { 1641 if ( anyFound == null ) { 1642 throw "Syntax error, unrecognized expression: " + expr; 1643 } else { 1644 break; 1645 } 1646 } 1647 1648 old = expr; 1649 } 1650 1651 return curLoop; 1652}; 1653 1654var Expr = Sizzle.selectors = { 1655 order: [ "ID", "NAME", "TAG" ], 1656 match: { 1657 ID: /#((?:[\w\u00c0-\uFFFF_-]|\\.)+)/, 1658 CLASS: /\.((?:[\w\u00c0-\uFFFF_-]|\\.)+)/, 1659 NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF_-]|\\.)+)['"]*\]/, 1660 ATTR: /\[\s*((?:[\w\u00c0-\uFFFF_-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/, 1661 TAG: /^((?:[\w\u00c0-\uFFFF\*_-]|\\.)+)/, 1662 CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/, 1663 POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/, 1664 PSEUDO: /:((?:[\w\u00c0-\uFFFF_-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/ 1665 }, 1666 attrMap: { 1667 "class": "className", 1668 "for": "htmlFor" 1669 }, 1670 attrHandle: { 1671 href: function(elem){ 1672 return elem.getAttribute("href"); 1673 } 1674 }, 1675 relative: { 1676 "+": function(checkSet, part, isXML){ 1677 var isPartStr = typeof part === "string", 1678 isTag = isPartStr && !/\W/.test(part), 1679 isPartStrNotTag = isPartStr && !isTag; 1680 1681 if ( isTag && !isXML ) { 1682 part = part.toUpperCase(); 1683 } 1684 1685 for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { 1686 if ( (elem = checkSet[i]) ) { 1687 while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} 1688 1689 checkSet[i] = isPartStrNotTag || elem && elem.nodeName === part ? 1690 elem || false : 1691 elem === part; 1692 } 1693 } 1694 1695 if ( isPartStrNotTag ) { 1696 Sizzle.filter( part, checkSet, true ); 1697 } 1698 }, 1699 ">": function(checkSet, part, isXML){ 1700 var isPartStr = typeof part === "string"; 1701 1702 if ( isPartStr && !/\W/.test(part) ) { 1703 part = isXML ? part : part.toUpperCase(); 1704 1705 for ( var i = 0, l = checkSet.length; i < l; i++ ) { 1706 var elem = checkSet[i]; 1707 if ( elem ) { 1708 var parent = elem.parentNode; 1709 checkSet[i] = parent.nodeName === part ? parent : false; 1710 } 1711 } 1712 } else { 1713 for ( var i = 0, l = checkSet.length; i < l; i++ ) { 1714 var elem = checkSet[i]; 1715 if ( elem ) { 1716 checkSet[i] = isPartStr ? 1717 elem.parentNode : 1718 elem.parentNode === part; 1719 } 1720 } 1721 1722 if ( isPartStr ) { 1723 Sizzle.filter( part, checkSet, true ); 1724 } 1725 } 1726 }, 1727 "": function(checkSet, part, isXML){ 1728 var doneName = done++, checkFn = dirCheck; 1729 1730 if ( !part.match(/\W/) ) { 1731 var nodeCheck = part = isXML ? part : part.toUpperCase(); 1732 checkFn = dirNodeCheck; 1733 } 1734 1735 checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML); 1736 }, 1737 "~": function(checkSet, part, isXML){ 1738 var doneName = done++, checkFn = dirCheck; 1739 1740 if ( typeof part === "string" && !part.match(/\W/) ) { 1741 var nodeCheck = part = isXML ? part : part.toUpperCase(); 1742 checkFn = dirNodeCheck; 1743 } 1744 1745 checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML); 1746 } 1747 }, 1748 find: { 1749 ID: function(match, context, isXML){ 1750 if ( typeof context.getElementById !== "undefined" && !isXML ) { 1751 var m = context.getElementById(match[1]); 1752 return m ? [m] : []; 1753 } 1754 }, 1755 NAME: function(match, context, isXML){ 1756 if ( typeof context.getElementsByName !== "undefined" ) { 1757 var ret = [], results = context.getElementsByName(match[1]); 1758 1759 for ( var i = 0, l = results.length; i < l; i++ ) { 1760 if ( results[i].getAttribute("name") === match[1] ) { 1761 ret.push( results[i] ); 1762 } 1763 } 1764 1765 return ret.length === 0 ? null : ret; 1766 } 1767 }, 1768 TAG: function(match, context){ 1769 return context.getElementsByTagName(match[1]); 1770 } 1771 }, 1772 preFilter: { 1773 CLASS: function(match, curLoop, inplace, result, not, isXML){ 1774 match = " " + match[1].replace(/\\/g, "") + " "; 1775 1776 if ( isXML ) { 1777 return match; 1778 } 1779 1780 for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { 1781 if ( elem ) { 1782 if ( not ^ (elem.className && (" " + elem.className + " ").indexOf(match) >= 0) ) { 1783 if ( !inplace ) 1784 result.push( elem ); 1785 } else if ( inplace ) { 1786 curLoop[i] = false; 1787 } 1788 } 1789 } 1790 1791 return false; 1792 }, 1793 ID: function(match){ 1794 return match[1].replace(/\\/g, ""); 1795 }, 1796 TAG: function(match, curLoop){ 1797 for ( var i = 0; curLoop[i] === false; i++ ){} 1798 return curLoop[i] && isXML(curLoop[i]) ? match[1] : match[1].toUpperCase(); 1799 }, 1800 CHILD: function(match){ 1801 if ( match[1] == "nth" ) { 1802 // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' 1803 var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec( 1804 match[2] == "even" && "2n" || match[2] == "odd" && "2n+1" || 1805 !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); 1806 1807 // calculate the numbers (first)n+(last) including if they are negative 1808 match[2] = (test[1] + (test[2] || 1)) - 0; 1809 match[3] = test[3] - 0; 1810 } 1811 1812 // TODO: Move to normal caching system 1813 match[0] = done++; 1814 1815 return match; 1816 }, 1817 ATTR: function(match, curLoop, inplace, result, not, isXML){ 1818 var name = match[1].replace(/\\/g, ""); 1819 1820 if ( !isXML && Expr.attrMap[name] ) { 1821 match[1] = Expr.attrMap[name]; 1822 } 1823 1824 if ( match[2] === "~=" ) { 1825 match[4] = " " + match[4] + " "; 1826 } 1827 1828 return match; 1829 }, 1830 PSEUDO: function(match, curLoop, inplace, result, not){ 1831 if ( match[1] === "not" ) { 1832 // If we're dealing with a complex expression, or a simple one 1833 if ( match[3].match(chunker).length > 1 || /^\w/.test(match[3]) ) { 1834 match[3] = Sizzle(match[3], null, null, curLoop); 1835 } else { 1836 var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); 1837 if ( !inplace ) { 1838 result.push.apply( result, ret ); 1839 } 1840 return false; 1841 } 1842 } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { 1843 return true; 1844 } 1845 1846 return match; 1847 }, 1848 POS: function(match){ 1849 match.unshift( true ); 1850 return match; 1851 } 1852 }, 1853 filters: { 1854 enabled: function(elem){ 1855 return elem.disabled === false && elem.type !== "hidden"; 1856 }, 1857 disabled: function(elem){ 1858 return elem.disabled === true; 1859 }, 1860 checked: function(elem){ 1861 return elem.checked === true; 1862 }, 1863 selected: function(elem){ 1864 // Accessing this property makes selected-by-default 1865 // options in Safari work properly 1866 elem.parentNode.selectedIndex; 1867 return elem.selected === true; 1868 }, 1869 parent: function(elem){ 1870 return !!elem.firstChild; 1871 }, 1872 empty: function(elem){ 1873 return !elem.firstChild; 1874 }, 1875 has: function(elem, i, match){ 1876 return !!Sizzle( match[3], elem ).length; 1877 }, 1878 header: function(elem){ 1879 return /h\d/i.test( elem.nodeName ); 1880 }, 1881 text: function(elem){ 1882 return "text" === elem.type; 1883 }, 1884 radio: function(elem){ 1885 return "radio" === elem.type; 1886 }, 1887 checkbox: function(elem){ 1888 return "checkbox" === elem.type; 1889 }, 1890 file: function(elem){ 1891 return "file" === elem.type; 1892 }, 1893 password: function(elem){ 1894 return "password" === elem.type; 1895 }, 1896 submit: function(elem){ 1897 return "submit" === elem.type; 1898 }, 1899 image: function(elem){ 1900 return "image" === elem.type; 1901 }, 1902 reset: function(elem){ 1903 return "reset" === elem.type; 1904 }, 1905 button: function(elem){ 1906 return "button" === elem.type || elem.nodeName.toUpperCase() === "BUTTON"; 1907 }, 1908 input: function(elem){ 1909 return /input|select|textarea|button/i.test(elem.nodeName); 1910 } 1911 }, 1912 setFilters: { 1913 first: function(elem, i){ 1914 return i === 0; 1915 }, 1916 last: function(elem, i, match, array){ 1917 return i === array.length - 1; 1918 }, 1919 even: function(elem, i){ 1920 return i % 2 === 0; 1921 }, 1922 odd: function(elem, i){ 1923 return i % 2 === 1; 1924 }, 1925 lt: function(elem, i, match){ 1926 return i < match[3] - 0; 1927 }, 1928 gt: function(elem, i, match){ 1929 return i > match[3] - 0; 1930 }, 1931 nth: function(elem, i, match){ 1932 return match[3] - 0 == i; 1933 }, 1934 eq: function(elem, i, match){ 1935 return match[3] - 0 == i; 1936 } 1937 }, 1938 filter: { 1939 PSEUDO: function(elem, match, i, array){ 1940 var name = match[1], filter = Expr.filters[ name ]; 1941 1942 if ( filter ) { 1943 return filter( elem, i, match, array ); 1944 } else if ( name === "contains" ) { 1945 return (elem.textContent || elem.innerText || "").indexOf(match[3]) >= 0; 1946 } else if ( name === "not" ) { 1947 var not = match[3]; 1948 1949 for ( var i = 0, l = not.length; i < l; i++ ) { 1950 if ( not[i] === elem ) { 1951 return false; 1952 } 1953 } 1954 1955 return true; 1956 } 1957 }, 1958 CHILD: function(elem, match){ 1959 var type = match[1], node = elem; 1960 switch (type) { 1961 case 'only': 1962 case 'first': 1963 while (node = node.previousSibling) { 1964 if ( node.nodeType === 1 ) return false; 1965 } 1966 if ( type == 'first') return true; 1967 node = elem; 1968 case 'last': 1969 while (node = node.nextSibling) { 1970 if ( node.nodeType === 1 ) return false; 1971 } 1972 return true; 1973 case 'nth': 1974 var first = match[2], last = match[3]; 1975 1976 if ( first == 1 && last == 0 ) { 1977 return true; 1978 } 1979 1980 var doneName = match[0], 1981 parent = elem.parentNode; 1982 1983 if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) { 1984 var count = 0; 1985 for ( node = parent.firstChild; node; node = node.nextSibling ) { 1986 if ( node.nodeType === 1 ) { 1987 node.nodeIndex = ++count; 1988 } 1989 } 1990 parent.sizcache = doneName; 1991 } 1992 1993 var diff = elem.nodeIndex - last; 1994 if ( first == 0 ) { 1995 return diff == 0; 1996 } else { 1997 return ( diff % first == 0 && diff / first >= 0 ); 1998 } 1999 } 2000 }, 2001 ID: function(elem, match){ 2002 return elem.nodeType === 1 && elem.getAttribute("id") === match; 2003 }, 2004 TAG: function(elem, match){ 2005 return (match === "*" && elem.nodeType === 1) || elem.nodeName === match; 2006 }, 2007 CLASS: function(elem, match){ 2008 return (" " + (elem.className || elem.getAttribute("class")) + " ") 2009 .indexOf( match ) > -1; 2010 }, 2011 ATTR: function(elem, match){ 2012 var name = match[1], 2013 result = Expr.attrHandle[ name ] ? 2014 Expr.attrHandle[ name ]( elem ) : 2015 elem[ name ] != null ? 2016 elem[ name ] : 2017 elem.getAttribute( name ), 2018 value = result + "", 2019 type = match[2], 2020 check = match[4]; 2021 2022 return result == null ? 2023 type === "!=" : 2024 type === "=" ? 2025 value === check : 2026 type === "*=" ? 2027 value.indexOf(check) >= 0 : 2028 type === "~=" ? 2029 (" " + value + " ").indexOf(check) >= 0 : 2030 !check ? 2031 value && result !== false : 2032 type === "!=" ? 2033 value != check : 2034 type === "^=" ? 2035 value.indexOf(check) === 0 : 2036 type === "$=" ? 2037 value.substr(value.length - check.length) === check : 2038 type === "|=" ? 2039 value === check || value.substr(0, check.length + 1) === check + "-" : 2040 false; 2041 }, 2042 POS: function(elem, match, i, array){ 2043 var name = match[2], filter = Expr.setFilters[ name ]; 2044 2045 if ( filter ) { 2046 return filter( elem, i, match, array ); 2047 } 2048 } 2049 } 2050}; 2051 2052var origPOS = Expr.match.POS; 2053 2054for ( var type in Expr.match ) { 2055 Expr.match[ type ] = RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source ); 2056} 2057 2058var makeArray = function(array, results) { 2059 array = Array.prototype.slice.call( array ); 2060 2061 if ( results ) { 2062 results.push.apply( results, array ); 2063 return results; 2064 } 2065 2066 return array; 2067}; 2068 2069// Perform a simple check to determine if the browser is capable of 2070// converting a NodeList to an array using builtin methods. 2071try { 2072 Array.prototype.slice.call( document.documentElement.childNodes ); 2073 2074// Provide a fallback method if it does not work 2075} catch(e){ 2076 makeArray = function(array, results) { 2077 var ret = results || []; 2078 2079 if ( toString.call(array) === "[object Array]" ) { 2080 Array.prototype.push.apply( ret, array ); 2081 } else { 2082 if ( typeof array.length === "number" ) { 2083 for ( var i = 0, l = array.length; i < l; i++ ) { 2084 ret.push( array[i] ); 2085 } 2086 } else { 2087 for ( var i = 0; array[i]; i++ ) { 2088 ret.push( array[i] ); 2089 } 2090 } 2091 } 2092 2093 return ret; 2094 }; 2095} 2096 2097var sortOrder; 2098 2099if ( document.documentElement.compareDocumentPosition ) { 2100 sortOrder = function( a, b ) { 2101 var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1; 2102 if ( ret === 0 ) { 2103 hasDuplicate = true; 2104 } 2105 return ret; 2106 }; 2107} else if ( "sourceIndex" in document.documentElement ) { 2108 sortOrder = function( a, b ) { 2109 var ret = a.sourceIndex - b.sourceIndex; 2110 if ( ret === 0 ) { 2111 hasDuplicate = true; 2112 } 2113 return ret; 2114 }; 2115} else if ( document.createRange ) { 2116 sortOrder = function( a, b ) { 2117 var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange(); 2118 aRange.selectNode(a); 2119 aRange.collapse(true); 2120 bRange.selectNode(b); 2121 bRange.collapse(true); 2122 var ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange); 2123 if ( ret === 0 ) { 2124 hasDuplicate = true; 2125 } 2126 return ret; 2127 }; 2128} 2129 2130// Check to see if the browser returns elements by name when 2131// querying by getElementById (and provide a workaround) 2132(function(){ 2133 // We're going to inject a fake input element with a specified name 2134 var form = document.createElement("form"), 2135 id = "script" + (new Date).getTime(); 2136 form.innerHTML = "<input name='" + id + "'/>"; 2137 2138 // Inject it into the root element, check its status, and remove it quickly 2139 var root = document.documentElement; 2140 root.insertBefore( form, root.firstChild ); 2141 2142 // The workaround has to do additional checks after a getElementById 2143 // Which slows things down for other browsers (hence the branching) 2144 if ( !!document.getElementById( id ) ) { 2145 Expr.find.ID = function(match, context, isXML){ 2146 if ( typeof context.getElementById !== "undefined" && !isXML ) { 2147 var m = context.getElementById(match[1]); 2148 return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : []; 2149 } 2150 }; 2151 2152 Expr.filter.ID = function(elem, match){ 2153 var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); 2154 return elem.nodeType === 1 && node && node.nodeValue === match; 2155 }; 2156 } 2157 2158 root.removeChild( form ); 2159})(); 2160 2161(function(){ 2162 // Check to see if the browser returns only elements 2163 // when doing getElementsByTagName("*") 2164 2165 // Create a fake element 2166 var div = document.createElement("div"); 2167 div.appendChild( document.createComment("") ); 2168 2169 // Make sure no comments are found 2170 if ( div.getElementsByTagName("*").length > 0 ) { 2171 Expr.find.TAG = function(match, context){ 2172 var results = context.getElementsByTagName(match[1]); 2173 2174 // Filter out possible comments 2175 if ( match[1] === "*" ) { 2176 var tmp = []; 2177 2178 for ( var i = 0; results[i]; i++ ) { 2179 if ( results[i].nodeType === 1 ) { 2180 tmp.push( results[i] ); 2181 } 2182 } 2183 2184 results = tmp; 2185 } 2186 2187 return results; 2188 }; 2189 } 2190 2191 // Check to see if an attribute returns normalized href attributes 2192 div.innerHTML = "<a href='#'></a>"; 2193 if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && 2194 div.firstChild.getAttribute("href") !== "#" ) { 2195 Expr.attrHandle.href = function(elem){ 2196 return elem.getAttribute("href", 2); 2197 }; 2198 } 2199})(); 2200 2201if ( document.querySelectorAll ) (function(){ 2202 var oldSizzle = Sizzle, div = document.createElement("div"); 2203 div.innerHTML = "<p class='TEST'></p>"; 2204 2205 // Safari can't handle uppercase or unicode characters when 2206 // in quirks mode. 2207 if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { 2208 return; 2209 } 2210 2211 Sizzle = function(query, context, extra, seed){ 2212 context = context || document; 2213 2214 // Only use querySelectorAll on non-XML documents 2215 // (ID selectors don't work in non-HTML documents) 2216 if ( !seed && context.nodeType === 9 && !isXML(context) ) { 2217 try { 2218 return makeArray( context.querySelectorAll(query), extra ); 2219 } catch(e){} 2220 } 2221 2222 return oldSizzle(query, context, extra, seed); 2223 }; 2224 2225 Sizzle.find = oldSizzle.find; 2226 Sizzle.filter = oldSizzle.filter; 2227 Sizzle.selectors = oldSizzle.selectors; 2228 Sizzle.matches = oldSizzle.matches; 2229})(); 2230 2231if ( document.getElementsByClassName && document.documentElement.getElementsByClassName ) (function(){ 2232 var div = document.createElement("div"); 2233 div.innerHTML = "<div class='test e'></div><div class='test'></div>"; 2234 2235 // Opera can't find a second classname (in 9.6) 2236 if ( div.getElementsByClassName("e").length === 0 ) 2237 return; 2238 2239 // Safari caches class attributes, doesn't catch changes (in 3.2) 2240 div.lastChild.className = "e"; 2241 2242 if ( div.getElementsByClassName("e").length === 1 ) 2243 return; 2244 2245 Expr.order.splice(1, 0, "CLASS"); 2246 Expr.find.CLASS = function(match, context, isXML) { 2247 if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { 2248 return context.getElementsByClassName(match[1]); 2249 } 2250 }; 2251})(); 2252 2253function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { 2254 var sibDir = dir == "previousSibling" && !isXML; 2255 for ( var i = 0, l = checkSet.length; i < l; i++ ) { 2256 var elem = checkSet[i]; 2257 if ( elem ) { 2258 if ( sibDir && elem.nodeType === 1 ){ 2259 elem.sizcache = doneName; 2260 elem.sizset = i; 2261 } 2262 elem = elem[dir]; 2263 var match = false; 2264 2265 while ( elem ) { 2266 if ( elem.sizcache === doneName ) { 2267 match = checkSet[elem.sizset]; 2268 break; 2269 } 2270 2271 if ( elem.nodeType === 1 && !isXML ){ 2272 elem.sizcache = doneName; 2273 elem.sizset = i; 2274 } 2275 2276 if ( elem.nodeName === cur ) { 2277 match = elem; 2278 break; 2279 } 2280 2281 elem = elem[dir]; 2282 } 2283 2284 checkSet[i] = match; 2285 } 2286 } 2287} 2288 2289function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { 2290 var sibDir = dir == "previousSibling" && !isXML; 2291 for ( var i = 0, l = checkSet.length; i < l; i++ ) { 2292 var elem = checkSet[i]; 2293 if ( elem ) { 2294 if ( sibDir && elem.nodeType === 1 ) { 2295 elem.sizcache = doneName; 2296 elem.sizset = i; 2297 } 2298 elem = elem[dir]; 2299 var match = false; 2300 2301 while ( elem ) { 2302 if ( elem.sizcache === doneName ) { 2303 match = checkSet[elem.sizset]; 2304 break; 2305 } 2306 2307 if ( elem.nodeType === 1 ) { 2308 if ( !isXML ) { 2309 elem.sizcache = doneName; 2310 elem.sizset = i; 2311 } 2312 if ( typeof cur !== "string" ) { 2313 if ( elem === cur ) { 2314 match = true; 2315 break; 2316 } 2317 2318 } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { 2319 match = elem; 2320 break; 2321 } 2322 } 2323 2324 elem = elem[dir]; 2325 } 2326 2327 checkSet[i] = match; 2328 } 2329 } 2330} 2331 2332var contains = document.compareDocumentPosition ? function(a, b){ 2333 return a.compareDocumentPosition(b) & 16; 2334} : function(a, b){ 2335 return a !== b && (a.contains ? a.contains(b) : true); 2336}; 2337 2338var isXML = function(elem){ 2339 return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" || 2340 !!elem.ownerDocument && isXML( elem.ownerDocument ); 2341}; 2342 2343var posProcess = function(selector, context){ 2344 var tmpSet = [], later = "", match, 2345 root = context.nodeType ? [context] : context; 2346 2347 // Position selectors must be done after the filter 2348 // And so must :not(positional) so we move all PSEUDOs to the end 2349 while ( (match = Expr.match.PSEUDO.exec( selector )) ) { 2350 later += match[0]; 2351 selector = selector.replace( Expr.match.PSEUDO, "" ); 2352 } 2353 2354 selector = Expr.relative[selector] ? selector + "*" : selector; 2355 2356 for ( var i = 0, l = root.length; i < l; i++ ) { 2357 Sizzle( selector, root[i], tmpSet ); 2358 } 2359 2360 return Sizzle.filter( later, tmpSet ); 2361}; 2362 2363// EXPOSE 2364jQuery.find = Sizzle; 2365jQuery.filter = Sizzle.filter; 2366jQuery.expr = Sizzle.selectors; 2367jQuery.expr[":"] = jQuery.expr.filters; 2368 2369Sizzle.selectors.filters.hidden = function(elem){ 2370 return elem.offsetWidth === 0 || elem.offsetHeight === 0; 2371}; 2372 2373Sizzle.selectors.filters.visible = function(elem){ 2374 return elem.offsetWidth > 0 || elem.offsetHeight > 0; 2375}; 2376 2377Sizzle.selectors.filters.animated = function(elem){ 2378 return jQuery.grep(jQuery.timers, function(fn){ 2379 return elem === fn.elem; 2380 }).length; 2381}; 2382 2383jQuery.multiFilter = function( expr, elems, not ) { 2384 if ( not ) { 2385 expr = ":not(" + expr + ")"; 2386 } 2387 2388 return Sizzle.matches(expr, elems); 2389}; 2390 2391jQuery.dir = function( elem, dir ){ 2392 var matched = [], cur = elem[dir]; 2393 while ( cur && cur != document ) { 2394 if ( cur.nodeType == 1 ) 2395 matched.push( cur ); 2396 cur = cur[dir]; 2397 } 2398 return matched; 2399}; 2400 2401jQuery.nth = function(cur, result, dir, elem){ 2402 result = result || 1; 2403 var num = 0; 2404 2405 for ( ; cur; cur = cur[dir] ) 2406 if ( cur.nodeType == 1 && ++num == result ) 2407 break; 2408 2409 return cur; 2410}; 2411 2412jQuery.sibling = function(n, elem){ 2413 var r = []; 2414 2415 for ( ; n; n = n.nextSibling ) { 2416 if ( n.nodeType == 1 && n != elem ) 2417 r.push( n ); 2418 } 2419 2420 return r; 2421}; 2422 2423return; 2424 2425window.Sizzle = Sizzle; 2426 2427})(); 2428/* 2429 * A number of helper functions used for managing events. 2430 * Many of the ideas behind this code originated from 2431 * Dean Edwards' addEvent library. 2432 */ 2433jQuery.event = { 2434 2435 // Bind an event to an element 2436 // Original by Dean Edwards 2437 add: function(elem, types, handler, data) { 2438 if ( elem.nodeType == 3 || elem.nodeType == 8 ) 2439 return; 2440 2441 // For whatever reason, IE has trouble passing the window object 2442 // around, causing it to be cloned in the process 2443 if ( elem.setInterval && elem != window ) 2444 elem = window; 2445 2446 // Make sure that the function being executed has a unique ID 2447 if ( !handler.guid ) 2448 handler.guid = this.guid++; 2449 2450 // if data is passed, bind to handler 2451 if ( data !== undefined ) { 2452 // Create temporary function pointer to original handler 2453 var fn = handler; 2454 2455 // Create unique handler function, wrapped around original handler 2456 handler = this.proxy( fn ); 2457 2458 // Store data in unique handler 2459 handler.data = data; 2460 } 2461 2462 // Init the element's event structure 2463 var events = jQuery.data(elem, "events") || jQuery.data(elem, "events", {}), 2464 handle = jQuery.data(elem, "handle") || jQuery.data(elem, "handle", function(){ 2465 // Handle the second event of a trigger and when 2466 // an event is called after a page has unloaded 2467 return typeof jQuery !== "undefined" && !jQuery.event.triggered ? 2468 jQuery.event.handle.apply(arguments.callee.elem, arguments) : 2469 undefined; 2470 }); 2471 // Add elem as a property of the handle function 2472 // This is to prevent a memory leak with non-native 2473 // event in IE. 2474 handle.elem = elem; 2475 2476 // Handle multiple events separated by a space 2477 // jQuery(...).bind("mouseover mouseout", fn); 2478 jQuery.each(types.split(/\s+/), function(index, type) { 2479 // Namespaced event handlers 2480 var namespaces = type.split("."); 2481 type = namespaces.shift(); 2482 handler.type = namespaces.slice().sort().join("."); 2483 2484 // Get the current list of functions bound to this event 2485 var handlers = events[type]; 2486 2487 if ( jQuery.event.specialAll[type] ) 2488 jQuery.event.specialAll[type].setup.call(elem, data, namespaces); 2489 2490 // Init the event handler queue 2491 if (!handlers) { 2492 handlers = events[type] = {}; 2493 2494 // Check for a special event handler 2495 // Only use addEventListener/attachEvent if the special 2496 // events handler returns false 2497 if ( !jQuery.event.special[type] || jQuery.event.special[type].setup.call(elem, data, namespaces) === false ) { 2498 // Bind the global event handler to the element 2499 if (elem.addEventListener) 2500 elem.addEventListener(type, handle, false); 2501 else if (elem.attachEvent) 2502 elem.attachEvent("on" + type, handle); 2503 } 2504 } 2505 2506 // Add the function to the element's handler list 2507 handlers[handler.guid] = handler; 2508 2509 // Keep track of which events have been used, for global triggering 2510 jQuery.event.global[type] = true; 2511 }); 2512 2513 // Nullify elem to prevent memory leaks in IE 2514 elem = null; 2515 }, 2516 2517 guid: 1, 2518 global: {}, 2519 2520 // Detach an event or set of events from an element 2521 remove: function(elem, types, handler) { 2522 // don't do events on text and comment nodes 2523 if ( elem.nodeType == 3 || elem.nodeType == 8 ) 2524 return; 2525 2526 var events = jQuery.data(elem, "events"), ret, index; 2527 2528 if ( events ) { 2529 // Unbind all events for the element 2530 if ( types === undefined || (typeof types === "string" && types.charAt(0) == ".") ) 2531 for ( var type in events ) 2532 this.remove( elem, type + (types || "") ); 2533 else { 2534 // types is actually an event object here 2535 if ( types.type ) { 2536 handler = types.handler; 2537 types = types.type; 2538 } 2539 2540 // Handle multiple events seperated by a space 2541 // jQuery(...).unbind("mouseover mouseout", fn); 2542 jQuery.each(types.split(/\s+/), function(index, type){ 2543 // Namespaced event handlers 2544 var namespaces = type.split("."); 2545 type = namespaces.shift(); 2546 var namespace = RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)"); 2547 2548 if ( events[type] ) { 2549 // remove the given handler for the given type 2550 if ( handler ) 2551 delete events[type][handler.guid]; 2552 2553 // remove all handlers for the given type 2554 else 2555 for ( var handle in events[type] ) 2556 // Handle the removal of namespaced events 2557 if ( namespace.test(events[type][handle].type) ) 2558 delete events[type][handle]; 2559 2560 if ( jQuery.event.specialAll[type] ) 2561 jQuery.event.specialAll[type].teardown.call(elem, namespaces); 2562 2563 // remove generic event handler if no more handlers exist 2564 for ( ret in events[type] ) break; 2565 if ( !ret ) { 2566 if ( !jQuery.event.special[type] || jQuery.event.special[type].teardown.call(elem, namespaces) === false ) { 2567 if (elem.removeEventListener) 2568 elem.removeEventListener(type, jQuery.data(elem, "handle"), false); 2569 else if (elem.detachEvent) 2570 elem.detachEvent("on" + type, jQuery.data(elem, "handle")); 2571 } 2572 ret = null; 2573 delete events[type]; 2574 } 2575 } 2576 }); 2577 } 2578 2579 // Remove the expando if it's no longer used 2580 for ( ret in events ) break; 2581 if ( !ret ) { 2582 var handle = jQuery.data( elem, "handle" ); 2583 if ( handle ) handle.elem = null; 2584 jQuery.removeData( elem, "events" ); 2585 jQuery.removeData( elem, "handle" ); 2586 } 2587 } 2588 }, 2589 2590 // bubbling is internal 2591 trigger: function( event, data, elem, bubbling ) { 2592 // Event object or event type 2593 var type = event.type || event; 2594 2595 if( !bubbling ){ 2596 event = typeof event === "object" ? 2597 // jQuery.Event object 2598 event[expando] ? event : 2599 // Object literal 2600 jQuery.extend( jQuery.Event(type), event ) : 2601 // Just the event type (string) 2602 jQuery.Event(type); 2603 2604 if ( type.indexOf("!") >= 0 ) { 2605 event.type = type = type.slice(0, -1); 2606 event.exclusive = true; 2607 } 2608 2609 // Handle a global trigger 2610 if ( !elem ) { 2611 // Don't bubble custom events when global (to avoid too much overhead) 2612 event.stopPropagation(); 2613 // Only trigger if we've ever bound an event for it 2614 if ( this.global[type] ) 2615 jQuery.each( jQuery.cache, function(){ 2616 if ( this.events && this.events[type] ) 2617 jQuery.event.trigger( event, data, this.handle.elem ); 2618 }); 2619 } 2620 2621 // Handle triggering a single element 2622 2623 // don't do events on text and comment nodes 2624 if ( !elem || elem.nodeType == 3 || elem.nodeType == 8 ) 2625 return undefined; 2626 2627 // Clean up in case it is reused 2628 event.result = undefined; 2629 event.target = elem; 2630 2631 // Clone the incoming data, if any 2632 data = jQuery.makeArray(data); 2633 data.unshift( event ); 2634 } 2635 2636 event.currentTarget = elem; 2637 2638 // Trigger the event, it is assumed that "handle" is a function 2639 var handle = jQuery.data(elem, "handle"); 2640 if ( handle ) 2641 handle.apply( elem, data ); 2642 2643 // Handle triggering native .onfoo handlers (and on links since we don't call .click() for links) 2644 if ( (!elem[type] || (jQuery.nodeName(elem, 'a') && type == "click")) && elem["on"+type] && elem["on"+type].apply( elem, data ) === false ) 2645 event.result = false; 2646 2647 // Trigger the native events (except for clicks on links) 2648 if ( !bubbling && elem[type] && !event.isDefaultPrevented() && !(jQuery.nodeName(elem, 'a') && type == "click") ) { 2649 this.triggered = true; 2650 try { 2651 elem[ type ](); 2652 // prevent IE from throwing an error for some hidden elements 2653 } catch (e) {} 2654 } 2655 2656 this.triggered = false; 2657 2658 if ( !event.isPropagationStopped() ) { 2659 var parent = elem.parentNode || elem.ownerDocument; 2660 if ( parent ) 2661 jQuery.event.trigger(event, data, parent, true); 2662 } 2663 }, 2664 2665 handle: function(event) { 2666 // returned undefined or false 2667 var all, handlers; 2668 2669 event = arguments[0] = jQuery.event.fix( event || window.event ); 2670 event.currentTarget = this; 2671 2672 // Namespaced event handlers 2673 var namespaces = event.type.split("."); 2674 event.type = namespaces.shift(); 2675 2676 // Cache this now, all = true means, any handler 2677 all = !namespaces.length && !event.exclusive; 2678 2679 var namespace = RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)"); 2680 2681 handlers = ( jQuery.data(this, "events") || {} )[event.type]; 2682 2683 for ( var j in handlers ) { 2684 var handler = handlers[j]; 2685 2686 // Filter the functions by class 2687 if ( all || namespace.test(handler.type) ) { 2688 // Pass in a reference to the handler function itself 2689 // So that we can later remove it 2690 event.handler = handler; 2691 event.data = handler.data; 2692 2693 var ret = handler.apply(this, arguments); 2694 2695 if( ret !== undefined ){ 2696 event.result = ret; 2697 if ( ret === false ) { 2698 event.preventDefault(); 2699 event.stopPropagation(); 2700 } 2701 } 2702 2703 if( event.isImmediatePropagationStopped() ) 2704 break; 2705 2706 } 2707 } 2708 }, 2709 2710 props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "), 2711 2712 fix: function(event) { 2713 if ( event[expando] ) 2714 return event; 2715 2716 // store a copy of the original event object 2717 // and "clone" to set read-only properties 2718 var originalEvent = event; 2719 event = jQuery.Event( originalEvent ); 2720 2721 for ( var i = this.props.length, prop; i; ){ 2722 prop = this.props[ --i ]; 2723 event[ prop ] = originalEvent[ prop ]; 2724 } 2725 2726 // Fix target property, if necessary 2727 if ( !event.target ) 2728 event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either 2729 2730 // check if target is a textnode (safari) 2731 if ( event.target.nodeType == 3 ) 2732 event.target = event.target.parentNode; 2733 2734 // Add relatedTarget, if necessary 2735 if ( !event.relatedTarget && event.fromElement ) 2736 event.relatedTarget = event.fromElement == event.target ? event.toElement : event.fromElement; 2737 2738 // Calculate pageX/Y if missing and clientX/Y available 2739 if ( event.pageX == null && event.clientX != null ) { 2740 var doc = document.documentElement, body = document.body; 2741 event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc.clientLeft || 0); 2742 event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc.clientTop || 0); 2743 } 2744 2745 // Add which for key events 2746 if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) ) 2747 event.which = event.charCode || event.keyCode; 2748 2749 // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs) 2750 if ( !event.metaKey && event.ctrlKey ) 2751 event.metaKey = event.ctrlKey; 2752 2753 // Add which for click: 1 == left; 2 == middle; 3 == right 2754 // Note: button is not normalized, so don't use it 2755 if ( !event.which && event.button ) 2756 event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) )); 2757 2758 return event; 2759 }, 2760 2761 proxy: function( fn, proxy ){ 2762 proxy = proxy || function(){ return fn.apply(this, arguments); }; 2763 // Set the guid of unique handler to the same of original handler, so it can be removed 2764 proxy.guid = fn.guid = fn.guid || proxy.guid || this.guid++; 2765 // So proxy can be declared as an argument 2766 return proxy; 2767 }, 2768 2769 special: { 2770 ready: { 2771 // Make sure the ready event is setup 2772 setup: bindReady, 2773 teardown: function() {} 2774 } 2775 }, 2776 2777 specialAll: { 2778 live: { 2779 setup: function( selector, namespaces ){ 2780 jQuery.event.add( this, namespaces[0], liveHandler ); 2781 }, 2782 teardown: function( namespaces ){ 2783 if ( namespaces.length ) { 2784 var remove = 0, name = RegExp("(^|\\.)" + namespaces[0] + "(\\.|$)"); 2785 2786 jQuery.each( (jQuery.data(this, "events").live || {}), function(){ 2787 if ( name.test(this.type) ) 2788 remove++; 2789 }); 2790 2791 if ( remove < 1 ) 2792 jQuery.event.remove( this, namespaces[0], liveHandler ); 2793 } 2794 } 2795 } 2796 } 2797}; 2798 2799jQuery.Event = function( src ){ 2800 // Allow instantiation without the 'new' keyword 2801 if( !this.preventDefault ) 2802 return new jQuery.Event(src); 2803 2804 // Event object 2805 if( src && src.type ){ 2806 this.originalEvent = src; 2807 this.type = src.type; 2808 // Event type 2809 }else 2810 this.type = src; 2811 2812 // timeStamp is buggy for some events on Firefox(#3843) 2813 // So we won't rely on the native value 2814 this.timeStamp = now(); 2815 2816 // Mark it as fixed 2817 this[expando] = true; 2818}; 2819 2820function returnFalse(){ 2821 return false; 2822} 2823function returnTrue(){ 2824 return true; 2825} 2826 2827// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding 2828// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html 2829jQuery.Event.prototype = { 2830 preventDefault: function() { 2831 this.isDefaultPrevented = returnTrue; 2832 2833 var e = this.originalEvent; 2834 if( !e ) 2835 return; 2836 // if preventDefault exists run it on the original event 2837 if (e.preventDefault) 2838 e.preventDefault(); 2839 // otherwise set the returnValue property of the original event to false (IE) 2840 e.returnValue = false; 2841 }, 2842 stopPropagation: function() { 2843 this.isPropagationStopped = returnTrue; 2844 2845 var e = this.originalEvent; 2846 if( !e ) 2847 return; 2848 // if stopPropagation exists run it on the original event 2849 if (e.stopPropagation) 2850 e.stopPropagation(); 2851 // otherwise set the cancelBubble property of the original event to true (IE) 2852 e.cancelBubble = true; 2853 }, 2854 stopImmediatePropagation:function(){ 2855 this.isImmediatePropagationStopped = returnTrue; 2856 this.stopPropagation(); 2857 }, 2858 isDefaultPrevented: returnFalse, 2859 isPropagationStopped: returnFalse, 2860 isImmediatePropagationStopped: returnFalse 2861}; 2862// Checks if an event happened on an element within another element 2863// Used in jQuery.event.special.mouseenter and mouseleave handlers 2864var withinElement = function(event) { 2865 // Check if mouse(over|out) are still within the same parent element 2866 var parent = event.relatedTarget; 2867 // Traverse up the tree 2868 while ( parent && parent != this ) 2869 try { parent = parent.parentNode; } 2870 catch(e) { parent = this; } 2871 2872 if( parent != this ){ 2873 // set the correct event type 2874 event.type = event.data; 2875 // handle event if we actually just moused on to a non sub-element 2876 jQuery.event.handle.apply( this, arguments ); 2877 } 2878}; 2879 2880jQuery.each({ 2881 mouseover: 'mouseenter', 2882 mouseout: 'mouseleave' 2883}, function( orig, fix ){ 2884 jQuery.event.special[ fix ] = { 2885 setup: function(){ 2886 jQuery.event.add( this, orig, withinElement, fix ); 2887 }, 2888 teardown: function(){ 2889 jQuery.event.remove( this, orig, withinElement ); 2890 } 2891 }; 2892}); 2893 2894jQuery.fn.extend({ 2895 bind: function( type, data, fn ) { 2896 return type == "unload" ? this.one(type, data, fn) : this.each(function(){ 2897 jQuery.event.add( this, type, fn || data, fn && data ); 2898 }); 2899 }, 2900 2901 one: function( type, data, fn ) { 2902 var one = jQuery.event.proxy( fn || data, function(event) { 2903 jQuery(this).unbind(event, one); 2904 return (fn || data).apply( this, arguments ); 2905 }); 2906 return this.each(function(){ 2907 jQuery.event.add( this, type, one, fn && data); 2908 }); 2909 }, 2910 2911 unbind: function( type, fn ) { 2912 return this.each(function(){ 2913 jQuery.event.remove( this, type, fn ); 2914 }); 2915 }, 2916 2917 trigger: function( type, data ) { 2918 return this.each(function(){ 2919 jQuery.event.trigger( type, data, this ); 2920 }); 2921 }, 2922 2923 triggerHandler: function( type, data ) { 2924 if( this[0] ){ 2925 var event = jQuery.Event(type); 2926 event.preventDefault(); 2927 event.stopPropagation(); 2928 jQuery.event.trigger( event, data, this[0] ); 2929 return event.result; 2930 } 2931 }, 2932 2933 toggle: function( fn ) { 2934 // Save reference to arguments for access in closure 2935 var args = arguments, i = 1; 2936 2937 // link all the functions, so any of them can unbind this click handler 2938 while( i < args.length ) 2939 jQuery.event.proxy( fn, args[i++] ); 2940 2941 return this.click( jQuery.event.proxy( fn, function(event) { 2942 // Figure out which function to execute 2943 this.lastToggle = ( this.lastToggle || 0 ) % i; 2944 2945 // Make sure that clicks stop 2946 event.preventDefault(); 2947 2948 // and execute the function 2949 return args[ this.lastToggle++ ].apply( this, arguments ) || false; 2950 })); 2951 }, 2952 2953 hover: function(fnOver, fnOut) { 2954 return this.mouseenter(fnOver).mouseleave(fnOut); 2955 }, 2956 2957 ready: function(fn) { 2958 // Attach the listeners 2959 bindReady(); 2960 2961 // If the DOM is already ready 2962 if ( jQuery.isReady ) 2963 // Execute the function immediately 2964 fn.call( document, jQuery ); 2965 2966 // Otherwise, remember the function for later 2967 else 2968 // Add the function to the wait list 2969 jQuery.readyList.push( fn ); 2970 2971 return this; 2972 }, 2973 2974 live: function( type, fn ){ 2975 var proxy = jQuery.event.proxy( fn ); 2976 proxy.guid += this.selector + type; 2977 2978 jQuery(document).bind( liveConvert(type, this.selector), this.selector, proxy ); 2979 2980 return this; 2981 }, 2982 2983 die: function( type, fn ){ 2984 jQuery(document).unbind( liveConvert(type, this.selector), fn ? { guid: fn.guid + this.selector + type } : null ); 2985 return this; 2986 } 2987}); 2988 2989function liveHandler( event ){ 2990 var check = RegExp("(^|\\.)" + event.type + "(\\.|$)"), 2991 stop = true, 2992 elems = []; 2993 2994 jQuery.each(jQuery.data(this, "events").live || [], function(i, fn){ 2995 if ( check.test(fn.type) ) { 2996 var elem = jQuery(event.target).closest(fn.data)[0]; 2997 if ( elem ) 2998 elems.push({ elem: elem, fn: fn }); 2999 } 3000 }); 3001 3002 elems.sort(function(a,b) { 3003 return jQuery.data(a.elem, "closest") - jQuery.data(b.elem, "closest"); 3004 }); 3005 3006 jQuery.each(elems, function(){ 3007 if ( this.fn.call(this.elem, event, this.fn.data) === false ) 3008 return (stop = false); 3009 }); 3010 3011 return stop; 3012} 3013 3014function liveConvert(type, selector){ 3015 return ["live", type, selector.replace(/\./g, "`").replace(/ /g, "|")].join("."); 3016} 3017 3018jQuery.extend({ 3019 isReady: false, 3020 readyList: [], 3021 // Handle when the DOM is ready 3022 ready: function() { 3023 // Make sure that the DOM is not already loaded 3024 if ( !jQuery.isReady ) { 3025 // Remember that the DOM is ready 3026 jQuery.isReady = true; 3027 3028 // If there are functions bound, to execute 3029 if ( jQuery.readyList ) { 3030 // Execute all of them 3031 jQuery.each( jQuery.readyList, function(){ 3032 this.call( document, jQuery ); 3033 }); 3034 3035 // Reset the list of functions 3036 jQuery.readyList = null; 3037 } 3038 3039 // Trigger any bound ready events 3040 jQuery(document).triggerHandler("ready"); 3041 } 3042 } 3043}); 3044 3045var readyBound = false; 3046 3047function bindReady(){ 3048 if ( readyBound ) return; 3049 readyBound = true; 3050 3051 // Mozilla, Opera and webkit nightlies currently support this event 3052 if ( document.addEventListener ) { 3053 // Use the handy event callback 3054 document.addEventListener( "DOMContentLoaded", function(){ 3055 document.removeEventListener( "DOMContentLoaded", arguments.callee, false ); 3056 jQuery.ready(); 3057 }, false ); 3058 3059 // If IE event model is used 3060 } else if ( document.attachEvent ) { 3061 // ensure firing before onload, 3062 // maybe late but safe also for iframes 3063 document.attachEvent("onreadystatechange", function(){ 3064 if ( document.readyState === "complete" ) { 3065 document.detachEvent( "onreadystatechange", arguments.callee ); 3066 jQuery.ready(); 3067 } 3068 }); 3069 3070 // If IE and not an iframe 3071 // continually check to see if the document is ready 3072 if ( document.documentElement.doScroll && window == window.top ) (function(){ 3073 if ( jQuery.isReady ) return; 3074 3075 try { 3076 // If IE is used, use the trick by Diego Perini 3077 // http://javascript.nwbox.com/IEContentLoaded/ 3078 document.documentElement.doScroll("left"); 3079 } catch( error ) { 3080 setTimeout( arguments.callee, 0 ); 3081 return; 3082 } 3083 3084 // and execute any waiting functions 3085 jQuery.ready(); 3086 })(); 3087 } 3088 3089 // A fallback to window.onload, that will always work 3090 jQuery.event.add( window, "load", jQuery.ready ); 3091} 3092 3093jQuery.each( ("blur,focus,load,resize,scroll,unload,click,dblclick," + 3094 "mousedown,mouseup,mousemove,mouseover,mouseout,mouseenter,mouseleave," + 3095 "change,select,submit,keydown,keypress,keyup,error").split(","), function(i, name){ 3096 3097 // Handle event binding 3098 jQuery.fn[name] = function(fn){ 3099 return fn ? this.bind(name, fn) : this.trigger(name); 3100 }; 3101}); 3102 3103// Prevent memory leaks in IE 3104// And prevent errors on refresh with events like mouseover in other browsers 3105// Window isn't included so as not to unbind existing unload events 3106jQuery( window ).bind( 'unload', function(){ 3107 for ( var id in jQuery.cache ) 3108 // Skip the window 3109 if ( id != 1 && jQuery.cache[ id ].handle ) 3110 jQuery.event.remove( jQuery.cache[ id ].handle.elem ); 3111}); 3112(function(){ 3113 3114 jQuery.support = {}; 3115 3116 var root = document.documentElement, 3117 script = document.createElement("script"), 3118 div = document.createElement("div"), 3119 id = "script" + (new Date).getTime(); 3120 3121 div.style.display = "none"; 3122 div.innerHTML = ' <link/><table></table><a href="/a" style="color:red;float:left;opacity:.5;">a</a><select><option>text</option></select><object><param/></object>'; 3123 3124 var all = div.getElementsByTagName("*"), 3125 a = div.getElementsByTagName("a")[0]; 3126 3127 // Can't get basic test support 3128 if ( !all || !all.length || !a ) { 3129 return; 3130 } 3131 3132 jQuery.support = { 3133 // IE strips leading whitespace when .innerHTML is used 3134 leadingWhitespace: div.firstChild.nodeType == 3, 3135 3136 // Make sure that tbody elements aren't automatically inserted 3137 // IE will insert them into empty tables 3138 tbody: !div.getElementsByTagName("tbody").length, 3139 3140 // Make sure that you can get all elements in an <object> element 3141 // IE 7 always returns no results 3142 objectAll: !!div.getElementsByTagName("object")[0] 3143 .getElementsByTagName("*").length, 3144 3145 // Make sure that link elements get serialized correctly by innerHTML 3146 // This requires a wrapper element in IE 3147 htmlSerialize: !!div.getElementsByTagName("link").length, 3148 3149 // Get the style information from getAttribute 3150 // (IE uses .cssText insted) 3151 style: /red/.test( a.getAttribute("style") ), 3152 3153 // Make sure that URLs aren't manipulated 3154 // (IE normalizes it by default) 3155 hrefNormalized: a.getAttribute("href") === "/a", 3156 3157 // Make sure that element opacity exists 3158 // (IE uses filter instead) 3159 opacity: a.style.opacity === "0.5", 3160 3161 // Verify style float existence 3162 // (IE uses styleFloat instead of cssFloat) 3163 cssFloat: !!a.style.cssFloat, 3164 3165 // Will be defined later 3166 scriptEval: false, 3167 noCloneEvent: true, 3168 boxModel: null 3169 }; 3170 3171 script.type = "text/javascript"; 3172 try { 3173 script.appendChild( document.createTextNode( "window." + id + "=1;" ) ); 3174 } catch(e){} 3175 3176 root.insertBefore( script, root.firstChild ); 3177 3178 // Make sure that the execution of code works by injecting a script 3179 // tag with appendChild/createTextNode 3180 // (IE doesn't support this, fails, and uses .text instead) 3181 if ( window[ id ] ) { 3182 jQuery.support.scriptEval = true; 3183 delete window[ id ]; 3184 } 3185 3186 root.removeChild( script ); 3187 3188 if ( div.attachEvent && div.fireEvent ) { 3189 div.attachEvent("onclick", function(){ 3190 // Cloning a node shouldn't copy over any 3191 // bound event handlers (IE does this) 3192 jQuery.support.noCloneEvent = false; 3193 div.detachEvent("onclick", arguments.callee); 3194 }); 3195 div.cloneNode(true).fireEvent("onclick"); 3196 } 3197 3198 // Figure out if the W3C box model works as expected 3199 // document.body must exist before we can do this 3200 jQuery(function(){ 3201 var div = document.createElement("div"); 3202 div.style.width = div.style.paddingLeft = "1px"; 3203 3204 document.body.appendChild( div ); 3205 jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2; 3206 document.body.removeChild( div ).style.display = 'none'; 3207 }); 3208})(); 3209 3210var styleFloat = jQuery.support.cssFloat ? "cssFloat" : "styleFloat"; 3211 3212jQuery.props = { 3213 "for": "htmlFor", 3214 "class": "className", 3215 "float": styleFloat, 3216 cssFloat: styleFloat, 3217 styleFloat: styleFloat, 3218 readonly: "readOnly", 3219 maxlength: "maxLength", 3220 cellspacing: "cellSpacing", 3221 rowspan: "rowSpan", 3222 tabindex: "tabIndex" 3223}; 3224jQuery.fn.extend({ 3225 // Keep a copy of the old load 3226 _load: jQuery.fn.load, 3227 3228 load: function( url, params, callback ) { 3229 if ( typeof url !== "string" ) 3230 return this._load( url ); 3231 3232 var off = url.indexOf(" "); 3233 if ( off >= 0 ) { 3234 var selector = url.slice(off, url.length); 3235 url = url.slice(0, off); 3236 } 3237 3238 // Default to a GET request 3239 var type = "GET"; 3240 3241 // If the second parameter was provided 3242 if ( params ) 3243 // If it's a function 3244 if ( jQuery.isFunction( params ) ) { 3245 // We assume that it's the callback 3246 callback = params; 3247 params = null; 3248 3249 // Otherwise, build a param string 3250 } else if( typeof params === "object" ) { 3251 params = jQuery.param( params ); 3252 type = "POST"; 3253 } 3254 3255 var self = this; 3256 3257 // Request the remote document 3258 jQuery.ajax({ 3259 url: url, 3260 type: type, 3261 dataType: "html", 3262 data: params, 3263 complete: function(res, status){ 3264 // If successful, inject the HTML into all the matched elements 3265 if ( status == "success" || status == "notmodified" ) 3266 // See if a selector was specified 3267 self.html( selector ? 3268 // Create a dummy div to hold the results 3269 jQuery("<div/>") 3270 // inject the contents of the document in, removing the scripts 3271 // to avoid any 'Permission Denied' errors in IE 3272 .append(res.responseText.replace(/<script(.|\s)*?\/script>/g, "")) 3273 3274 // Locate the specified elements 3275 .find(selector) : 3276 3277 // If not, just inject the full result 3278 res.responseText ); 3279 3280 if( callback ) 3281 self.each( callback, [res.responseText, status, res] ); 3282 } 3283 }); 3284 return this; 3285 }, 3286 3287 serialize: function() { 3288 return jQuery.param(this.serializeArray()); 3289 }, 3290 serializeArray: function() { 3291 return this.map(function(){ 3292 return this.elements ? jQuery.makeArray(this.elements) : this; 3293 }) 3294 .filter(function(){ 3295 return this.name && !this.disabled && 3296 (this.checked || /select|textarea/i.test(this.nodeName) || 3297 /text|hidden|password|search/i.test(this.type)); 3298 }) 3299 .map(function(i, elem){ 3300 var val = jQuery(this).val(); 3301 return val == null ? null : 3302 jQuery.isArray(val) ? 3303 jQuery.map( val, function(val, i){ 3304 return {name: elem.name, value: val}; 3305 }) : 3306 {name: elem.name, value: val}; 3307 }).get(); 3308 } 3309}); 3310 3311// Attach a bunch of functions for handling common AJAX events 3312jQuery.each( "ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","), function(i,o){ 3313 jQuery.fn[o] = function(f){ 3314 return this.bind(o, f); 3315 }; 3316}); 3317 3318var jsc = now(); 3319 3320jQuery.extend({ 3321 3322 get: function( url, data, callback, type ) { 3323 // shift arguments if data argument was ommited 3324 if ( jQuery.isFunction( data ) ) { 3325 callback = data; 3326 data = null; 3327 } 3328 3329 return jQuery.ajax({ 3330 type: "GET", 3331 url: url, 3332 data: data, 3333 success: callback, 3334 dataType: type 3335 }); 3336 }, 3337 3338 getScript: function( url, callback ) { 3339 return jQuery.get(url, null, callback, "script"); 3340 }, 3341 3342 getJSON: function( url, data, callback ) { 3343 return jQuery.get(url, data, callback, "json"); 3344 }, 3345 3346 post: function( url, data, callback, type ) { 3347 if ( jQuery.isFunction( data ) ) { 3348 callback = data; 3349 data = {}; 3350 } 3351 3352 return jQuery.ajax({ 3353 type: "POST", 3354 url: url, 3355 data: data, 3356 success: callback, 3357 dataType: type 3358 }); 3359 }, 3360 3361 ajaxSetup: function( settings ) { 3362 jQuery.extend( jQuery.ajaxSettings, settings ); 3363 }, 3364 3365 ajaxSettings: { 3366 url: location.href, 3367 global: true, 3368 type: "GET", 3369 contentType: "application/x-www-form-urlencoded", 3370 processData: true, 3371 async: true, 3372 /* 3373 timeout: 0, 3374 data: null, 3375 username: null, 3376 password: null, 3377 */ 3378 // Create the request object; Microsoft failed to properly 3379 // implement the XMLHttpRequest in IE7, so we use the ActiveXObject when it is available 3380 // This function can be overriden by calling jQuery.ajaxSetup 3381 xhr:function(){ 3382 return window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest(); 3383 }, 3384 accepts: { 3385 xml: "application/xml, text/xml", 3386 html: "text/html", 3387 script: "text/javascript, application/javascript", 3388 json: "application/json, text/javascript", 3389 text: "text/plain", 3390 _default: "*/*" 3391 } 3392 }, 3393 3394 // Last-Modified header cache for next request 3395 lastModified: {}, 3396 3397 ajax: function( s ) { 3398 // Extend the settings, but re-extend 's' so that it can be 3399 // checked again later (in the test suite, specifically) 3400 s = jQuery.extend(true, s, jQuery.extend(true, {}, jQuery.ajaxSettings, s)); 3401 3402 var jsonp, jsre = /=\?(&|$)/g, status, data, 3403 type = s.type.toUpperCase(); 3404 3405 // convert data if not already a string 3406 if ( s.data && s.processData && typeof s.data !== "string" ) 3407 s.data = jQuery.param(s.data); 3408 3409 // Handle JSONP Parameter Callbacks 3410 if ( s.dataType == "jsonp" ) { 3411 if ( type == "GET" ) { 3412 if ( !s.url.match(jsre) ) 3413 s.url += (s.url.match(/\?/) ? "&" : "?") + (s.jsonp || "callback") + "=?"; 3414 } else if ( !s.data || !s.data.match(jsre) ) 3415 s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?"; 3416 s.dataType = "json"; 3417 } 3418 3419 // Build temporary JSONP function 3420 if ( s.dataType == "json" && (s.data && s.data.match(jsre) || s.url.match(jsre)) ) { 3421 jsonp = "jsonp" + jsc++; 3422 3423 // Replace the =? sequence both in the query string and the data 3424 if ( s.data ) 3425 s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1"); 3426 s.url = s.url.replace(jsre, "=" + jsonp + "$1"); 3427 3428 // We need to make sure 3429 // that a JSONP style response is executed properly 3430 s.dataType = "script"; 3431 3432 // Handle JSONP-style loading 3433 window[ jsonp ] = function(tmp){ 3434 data = tmp; 3435 success(); 3436 complete(); 3437 // Garbage collect 3438 window[ jsonp ] = undefined; 3439 try{ delete window[ jsonp ]; } catch(e){} 3440 if ( head ) 3441 head.removeChild( script ); 3442 }; 3443 } 3444 3445 if ( s.dataType == "script" && s.cache == null ) 3446 s.cache = false; 3447 3448 if ( s.cache === false && type == "GET" ) { 3449 var ts = now(); 3450 // try replacing _= if it is there 3451 var ret = s.url.replace(/(\?|&)_=.*?(&|$)/, "$1_=" + ts + "$2"); 3452 // if nothing was replaced, add timestamp to the end 3453 s.url = ret + ((ret == s.url) ? (s.url.match(/\?/) ? "&" : "?") + "_=" + ts : ""); 3454 } 3455 3456 // If data is available, append data to url for get requests 3457 if ( s.data && type == "GET" ) { 3458 s.url += (s.url.match(/\?/) ? "&" : "?") + s.data; 3459 3460 // IE likes to send both get and post data, prevent this 3461 s.data = null; 3462 } 3463 3464 // Watch for a new set of requests 3465 if ( s.global && ! jQuery.active++ ) 3466 jQuery.event.trigger( "ajaxStart" ); 3467 3468 // Matches an absolute URL, and saves the domain 3469 var parts = /^(\w+:)?\/\/([^\/?#]+)/.exec( s.url ); 3470 3471 // If we're requesting a remote document 3472 // and trying to load JSON or Script with a GET 3473 if ( s.dataType == "script" && type == "GET" && parts 3474 && ( parts[1] && parts[1] != location.protocol || parts[2] != location.host )){ 3475 3476 var head = document.getElementsByTagName("head")[0]; 3477 var script = document.createElement("script"); 3478 script.src = s.url; 3479 if (s.scriptCharset) 3480 script.charset = s.scriptCharset; 3481 3482 // Handle Script loading 3483 if ( !jsonp ) { 3484 var done = false; 3485 3486 // Attach handlers for all browsers 3487 script.onload = script.onreadystatechange = function(){ 3488 if ( !done && (!this.readyState || 3489 this.readyState == "loaded" || this.readyState == "complete") ) { 3490 done = true; 3491 success(); 3492 complete(); 3493 3494 // Handle memory leak in IE 3495 script.onload = script.onreadystatechange = null; 3496 head.removeChild( script ); 3497 } 3498 }; 3499 } 3500 3501 head.appendChild(script); 3502 3503 // We handle everything using the script element injection 3504 return undefined; 3505 } 3506 3507 var requestDone = false; 3508 3509 // Create the request object 3510 var xhr = s.xhr(); 3511 3512 // Open the socket 3513 // Passing null username, generates a login popup on Opera (#2865) 3514 if( s.username ) 3515 xhr.open(type, s.url, s.async, s.username, s.password); 3516 else 3517 xhr.open(type, s.url, s.async); 3518 3519 // Need an extra try/catch for cross domain requests in Firefox 3 3520 try { 3521 // Set the correct header, if data is being sent 3522 if ( s.data ) 3523 xhr.setRequestHeader("Content-Type", s.contentType); 3524 3525 // Set the If-Modified-Since header, if ifModified mode. 3526 if ( s.ifModified ) 3527 xhr.setRequestHeader("If-Modified-Since", 3528 jQuery.lastModified[s.url] || "Thu, 01 Jan 1970 00:00:00 GMT" ); 3529 3530 // Set header so the called script knows that it's an XMLHttpRequest 3531 xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest"); 3532 3533 // Set the Accepts header for the server, depending on the dataType 3534 xhr.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ? 3535 s.accepts[ s.dataType ] + ", */*" : 3536 s.accepts._default ); 3537 } catch(e){} 3538 3539 // Allow custom headers/mimetypes and early abort 3540 if ( s.beforeSend && s.beforeSend(xhr, s) === false ) { 3541 // Handle the global AJAX counter 3542 if ( s.global && ! --jQuery.active ) 3543 jQuery.event.trigger( "ajaxStop" ); 3544 // close opended socket 3545 xhr.abort(); 3546 return false; 3547 } 3548 3549 if ( s.global ) 3550 jQuery.event.trigger("ajaxSend", [xhr, s]); 3551 3552 // Wait for a response to come back 3553 var onreadystatechange = function(isTimeout){ 3554 // The request was aborted, clear the interval and decrement jQuery.active 3555 if (xhr.readyState == 0) { 3556 if (ival) { 3557 // clear poll interval 3558 clearInterval(ival); 3559 ival = null; 3560 // Handle the global AJAX counter 3561 if ( s.global && ! --jQuery.active ) 3562 jQuery.event.trigger( "ajaxStop" ); 3563 } 3564 // The transfer is complete and the data is available, or the request timed out 3565 } else if ( !requestDone && xhr && (xhr.readyState == 4 || isTimeout == "timeout") ) { 3566 requestDone = true; 3567 3568 // clear poll interval 3569 if (ival) { 3570 clearInterval(ival); 3571 ival = null; 3572 } 3573 3574 status = isTimeout == "timeout" ? "timeout" : 3575 !jQuery.httpSuccess( xhr ) ? "error" : 3576 s.ifModified && jQuery.httpNotModified( xhr, s.url ) ? "notmodified" : 3577 "success"; 3578 3579 if ( status == "success" ) { 3580 // Watch for, and catch, XML document parse errors 3581 try { 3582 // process the data (runs the xml through httpData regardless of callback) 3583 data = jQuery.httpData( xhr, s.dataType, s ); 3584 } catch(e) { 3585 status = "parsererror"; 3586 } 3587 } 3588 3589 // Make sure that the request was successful or notmodified 3590 if ( status == "success" ) { 3591 // Cache Last-Modified header, if ifModified mode. 3592 var modRes; 3593 try { 3594 modRes = xhr.getResponseHeader("Last-Modified"); 3595 } catch(e) {} // swallow exception thrown by FF if header is not available 3596 3597 if ( s.ifModified && modRes ) 3598 jQuery.lastModified[s.url] = modRes; 3599 3600 // JSONP handles its own success callback 3601 if ( !jsonp ) 3602 success(); 3603 } else 3604 jQuery.handleError(s, xhr, status); 3605 3606 // Fire the complete handlers 3607 complete(); 3608 3609 if ( isTimeout ) 3610 xhr.abort(); 3611 3612 // Stop memory leaks 3613 if ( s.async ) 3614 xhr = null; 3615 } 3616 }; 3617 3618 if ( s.async ) { 3619 // don't attach the handler to the request, just poll it instead 3620 var ival = setInterval(onreadystatechange, 13); 3621 3622 // Timeout checker 3623 if ( s.timeout > 0 ) 3624 setTimeout(function(){ 3625 // Check to see if the request is still happening 3626 if ( xhr && !requestDone ) 3627 onreadystatechange( "timeout" ); 3628 }, s.timeout); 3629 } 3630 3631 // Send the data 3632 try { 3633 xhr.send(s.data); 3634 } catch(e) { 3635 jQuery.handleError(s, xhr, null, e); 3636 } 3637 3638 // firefox 1.5 doesn't fire statechange for sync requests 3639 if ( !s.async ) 3640 onreadystatechange(); 3641 3642 function success(){ 3643 // If a local callback was specified, fire it and pass it the data 3644 if ( s.success ) 3645 s.success( data, status ); 3646 3647 // Fire the global callback 3648 if ( s.global ) 3649 jQuery.event.trigger( "ajaxSuccess", [xhr, s] ); 3650 } 3651 3652 function complete(){ 3653 // Process result 3654 if ( s.complete ) 3655 s.complete(xhr, status); 3656 3657 // The request was completed 3658 if ( s.global ) 3659 jQuery.event.trigger( "ajaxComplete", [xhr, s] ); 3660 3661 // Handle the global AJAX counter 3662 if ( s.global && ! --jQuery.active ) 3663 jQuery.event.trigger( "ajaxStop" ); 3664 } 3665 3666 // return XMLHttpRequest to allow aborting the request etc. 3667 return xhr; 3668 }, 3669 3670 handleError: function( s, xhr, status, e ) { 3671 // If a local callback was specified, fire it 3672 if ( s.error ) s.error( xhr, status, e ); 3673 3674 // Fire the global callback 3675 if ( s.global ) 3676 jQuery.event.trigger( "ajaxError", [xhr, s, e] ); 3677 }, 3678 3679 // Counter for holding the number of active queries 3680 active: 0, 3681 3682 // Determines if an XMLHttpRequest was successful or not 3683 httpSuccess: function( xhr ) { 3684 try { 3685 // IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450 3686 return !xhr.status && location.protocol == "file:" || 3687 ( xhr.status >= 200 && xhr.status < 300 ) || xhr.status == 304 || xhr.status == 1223; 3688 } catch(e){} 3689 return false; 3690 }, 3691 3692 // Determines if an XMLHttpRequest returns NotModified 3693 httpNotModified: function( xhr, url ) { 3694 try { 3695 var xhrRes = xhr.getResponseHeader("Last-Modified"); 3696 3697 // Firefox always returns 200. check Last-Modified date 3698 return xhr.status == 304 || xhrRes == jQuery.lastModified[url]; 3699 } catch(e){} 3700 return false; 3701 }, 3702 3703 httpData: function( xhr, type, s ) { 3704 var ct = xhr.getResponseHeader("content-type"), 3705 xml = type == "xml" || !type && ct && ct.indexOf("xml") >= 0, 3706 data = xml ? xhr.responseXML : xhr.responseText; 3707 3708 if ( xml && data.documentElement.tagName == "parsererror" ) 3709 throw "parsererror"; 3710 3711 // Allow a pre-filtering function to sanitize the response 3712 // s != null is checked to keep backwards compatibility 3713 if( s && s.dataFilter ) 3714 data = s.dataFilter( data, type ); 3715 3716 // The filter can actually parse the response 3717 if( typeof data === "string" ){ 3718 3719 // If the type is "script", eval it in global context 3720 if ( type == "script" ) 3721 jQuery.globalEval( data ); 3722 3723 // Get the JavaScript object, if JSON is used. 3724 if ( type == "json" ) 3725 data = window["eval"]("(" + data + ")"); 3726 } 3727 3728 return data; 3729 }, 3730 3731 // Serialize an array of form elements or a set of 3732 // key/values into a query string 3733 param: function( a ) { 3734 var s = [ ]; 3735 3736 function add( key, value ){ 3737 s[ s.length ] = encodeURIComponent(key) + '=' + encodeURIComponent(value); 3738 }; 3739 3740 // If an array was passed in, assume that it is an array 3741 // of form elements 3742 if ( jQuery.isArray(a) || a.jquery ) 3743 // Serialize the form elements 3744 jQuery.each( a, function(){ 3745 add( this.name, this.value ); 3746 }); 3747 3748 // Otherwise, assume that it's an object of key/value pairs 3749 else 3750 // Serialize the key/values 3751 for ( var j in a ) 3752 // If the value is an array then the key names need to be repeated 3753 if ( jQuery.isArray(a[j]) ) 3754 jQuery.each( a[j], function(){ 3755 add( j, this ); 3756 }); 3757 else 3758 add( j, jQuery.isFunction(a[j]) ? a[j]() : a[j] ); 3759 3760 // Return the resulting serialization 3761 return s.join("&").replace(/%20/g, "+"); 3762 } 3763 3764}); 3765var elemdisplay = {}, 3766 timerId, 3767 fxAttrs = [ 3768 // height animations 3769 [ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ], 3770 // width animations 3771 [ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ], 3772 // opacity animations 3773 [ "opacity" ] 3774 ]; 3775 3776function genFx( type, num ){ 3777 var obj = {}; 3778 jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function(){ 3779 obj[ this ] = type; 3780 }); 3781 return obj; 3782} 3783 3784jQuery.fn.extend({ 3785 show: function(speed,callback){ 3786 if ( speed ) { 3787 return this.animate( genFx("show", 3), speed, callback); 3788 } else { 3789 for ( var i = 0, l = this.length; i < l; i++ ){ 3790 var old = jQuery.data(this[i], "olddisplay"); 3791 3792 this[i].style.display = old || ""; 3793 3794 if ( jQuery.css(this[i], "display") === "none" ) { 3795 var tagName = this[i].tagName, display; 3796 3797 if ( elemdisplay[ tagName ] ) { 3798 display = elemdisplay[ tagName ]; 3799 } else { 3800 var elem = jQuery("<" + tagName + " />").appendTo("body"); 3801 3802 display = elem.css("display"); 3803 if ( display === "none" ) 3804 display = "block"; 3805 3806 elem.remove(); 3807 3808 elemdisplay[ tagName ] = display; 3809 } 3810 3811 jQuery.data(this[i], "olddisplay", display); 3812 } 3813 } 3814 3815 // Set the display of the elements in a second loop 3816 // to avoid the constant reflow 3817 for ( var i = 0, l = this.length; i < l; i++ ){ 3818 this[i].style.display = jQuery.data(this[i], "olddisplay") || ""; 3819 } 3820 3821 return this; 3822 } 3823 }, 3824 3825 hide: function(speed,callback){ 3826 if ( speed ) { 3827 return this.animate( genFx("hide", 3), speed, callback); 3828 } else { 3829 for ( var i = 0, l = this.length; i < l; i++ ){ 3830 var old = jQuery.data(this[i], "olddisplay"); 3831 if ( !old && old !== "none" ) 3832 jQuery.data(this[i], "olddisplay", jQuery.css(this[i], "display")); 3833 } 3834 3835 // Set the display of the elements in a second loop 3836 // to avoid the constant reflow 3837 for ( var i = 0, l = this.length; i < l; i++ ){ 3838 this[i].style.display = "none"; 3839 } 3840 3841 return this; 3842 } 3843 }, 3844 3845 // Save the old toggle function 3846 _toggle: jQuery.fn.toggle, 3847 3848 toggle: function( fn, fn2 ){ 3849 var bool = typeof fn === "boolean"; 3850 3851 return jQuery.isFunction(fn) && jQuery.isFunction(fn2) ? 3852 this._toggle.apply( this, arguments ) : 3853 fn == null || bool ? 3854 this.each(function(){ 3855 var state = bool ? fn : jQuery(this).is(":hidden"); 3856 jQuery(this)[ state ? "show" : "hide" ](); 3857 }) : 3858 this.animate(genFx("toggle", 3), fn, fn2); 3859 }, 3860 3861 fadeTo: function(speed,to,callback){ 3862 return this.animate({opacity: to}, speed, callback); 3863 }, 3864 3865 animate: function( prop, speed, easing, callback ) { 3866 var optall = jQuery.speed(speed, easing, callback); 3867 3868 return this[ optall.queue === false ? "each" : "queue" ](function(){ 3869 3870 var opt = jQuery.extend({}, optall), p, 3871 hidden = this.nodeType == 1 && jQuery(this).is(":hidden"), 3872 self = this; 3873 3874 for ( p in prop ) { 3875 if ( prop[p] == "hide" && hidden || prop[p] == "show" && !hidden ) 3876 return opt.complete.call(this); 3877 3878 if ( ( p == "height" || p == "width" ) && this.style ) { 3879 // Store display property 3880 opt.display = jQuery.css(this, "display"); 3881 3882 // Make sure that nothing sneaks out 3883 opt.overflow = this.style.overflow; 3884 } 3885 } 3886 3887 if ( opt.overflow != null ) 3888 this.style.overflow = "hidden"; 3889 3890 opt.curAnim = jQuery.extend({}, prop); 3891 3892 jQuery.each( prop, function(name, val){ 3893 var e = new jQuery.fx( self, opt, name ); 3894 3895 if ( /toggle|show|hide/.test(val) ) 3896 e[ val == "toggle" ? hidden ? "show" : "hide" : val ]( prop ); 3897 else { 3898 var parts = val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/), 3899 start = e.cur(true) || 0; 3900 3901 if ( parts ) { 3902 var end = parseFloat(parts[2]), 3903 unit = parts[3] || "px"; 3904 3905 // We need to compute starting value 3906 if ( unit != "px" ) { 3907 self.style[ name ] = (end || 1) + unit; 3908 start = ((end || 1) / e.cur(true)) * start; 3909 self.style[ name ] = start + unit; 3910 } 3911 3912 // If a +=/-= token was provided, we're doing a relative animation 3913 if ( parts[1] ) 3914 end = ((parts[1] == "-=" ? -1 : 1) * end) + start; 3915 3916 e.custom( start, end, unit ); 3917 } else 3918 e.custom( start, val, "" ); 3919 } 3920 }); 3921 3922 // For JS strict compliance 3923 return true; 3924 }); 3925 }, 3926 3927 stop: function(clearQueue, gotoEnd){ 3928 var timers = jQuery.timers; 3929 3930 if (clearQueue) 3931 this.queue([]); 3932 3933 this.each(function(){ 3934 // go in reverse order so anything added to the queue during the loop is ignored 3935 for ( var i = timers.length - 1; i >= 0; i-- ) 3936 if ( timers[i].elem == this ) { 3937 if (gotoEnd) 3938 // force the next step to be the last 3939 timers[i](true); 3940 timers.splice(i, 1); 3941 } 3942 }); 3943 3944 // start the next in the queue if the last step wasn't forced 3945 if (!gotoEnd) 3946 this.dequeue(); 3947 3948 return this; 3949 } 3950 3951}); 3952 3953// Generate shortcuts for custom animations 3954jQuery.each({ 3955 slideDown: genFx("show", 1), 3956 slideUp: genFx("hide", 1), 3957 slideToggle: genFx("toggle", 1), 3958 fadeIn: { opacity: "show" }, 3959 fadeOut: { opacity: "hide" } 3960}, function( name, props ){ 3961 jQuery.fn[ name ] = function( speed, callback ){ 3962 return this.animate( props, speed, callback ); 3963 }; 3964}); 3965 3966jQuery.extend({ 3967 3968 speed: function(speed, easing, fn) { 3969 var opt = typeof speed === "object" ? speed : { 3970 complete: fn || !fn && easing || 3971 jQuery.isFunction( speed ) && speed, 3972 duration: speed, 3973 easing: fn && easing || easing && !jQuery.isFunction(easing) && easing 3974 }; 3975 3976 opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration : 3977 jQuery.fx.speeds[opt.duration] || jQuery.fx.speeds._default; 3978 3979 // Queueing 3980 opt.old = opt.complete; 3981 opt.complete = function(){ 3982 if ( opt.queue !== false ) 3983 jQuery(this).dequeue(); 3984 if ( jQuery.isFunction( opt.old ) ) 3985 opt.old.call( this ); 3986 }; 3987 3988 return opt; 3989 }, 3990 3991 easing: { 3992 linear: function( p, n, firstNum, diff ) { 3993 return firstNum + diff * p; 3994 }, 3995 swing: function( p, n, firstNum, diff ) { 3996 return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum; 3997 } 3998 }, 3999 4000 timers: [], 4001 4002 fx: function( elem, options, prop ){ 4003 this.options = options; 4004 this.elem = elem; 4005 this.prop = prop; 4006 4007 if ( !options.orig ) 4008 options.orig = {}; 4009 } 4010 4011}); 4012 4013jQuery.fx.prototype = { 4014 4015 // Simple function for setting a style value 4016 update: function(){ 4017 if ( this.options.step ) 4018 this.options.step.call( this.elem, this.now, this ); 4019 4020 (jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this ); 4021 4022 // Set display property to block for height/width animations 4023 if ( ( this.prop == "height" || this.prop == "width" ) && this.elem.style ) 4024 this.elem.style.display = "block"; 4025 }, 4026 4027 // Get the current size 4028 cur: function(force){ 4029 if ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) ) 4030 return this.elem[ this.prop ]; 4031 4032 var r = parseFloat(jQuery.css(this.elem, this.prop, force)); 4033 return r && r > -10000 ? r : parseFloat(jQuery.curCSS(this.elem, this.prop)) || 0; 4034 }, 4035 4036 // Start an animation from one number to another 4037 custom: function(from, to, unit){ 4038 this.startTime = now(); 4039 this.start = from; 4040 this.end = to; 4041 this.unit = unit || this.unit || "px"; 4042 this.now = this.start; 4043 this.pos = this.state = 0; 4044 4045 var self = this; 4046 function t(gotoEnd){ 4047 return self.step(gotoEnd); 4048 } 4049 4050 t.elem = this.elem; 4051 4052 if ( t() && jQuery.timers.push(t) && !timerId ) { 4053 timerId = setInterval(function(){ 4054 var timers = jQuery.timers; 4055 4056 for ( var i = 0; i < timers.length; i++ ) 4057 if ( !timers[i]() ) 4058 timers.splice(i--, 1); 4059 4060 if ( !timers.length ) { 4061 clearInterval( timerId ); 4062 timerId = undefined; 4063 } 4064 }, 13); 4065 } 4066 }, 4067 4068 // Simple 'show' function 4069 show: function(){ 4070 // Remember where we started, so that we can go back to it later 4071 this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop ); 4072 this.options.show = true; 4073 4074 // Begin the animation 4075 // Make sure that we start at a small width/height to avoid any 4076 // flash of content 4077 this.custom(this.prop == "width" || this.prop == "height" ? 1 : 0, this.cur()); 4078 4079 // Start by showing the element 4080 jQuery(this.elem).show(); 4081 }, 4082 4083 // Simple 'hide' function 4084 hide: function(){ 4085 // Remember where we started, so that we can go back to it later 4086 this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop ); 4087 this.options.hide = true; 4088 4089 // Begin the animation 4090 this.custom(this.cur(), 0); 4091 }, 4092 4093 // Each step of an animation 4094 step: function(gotoEnd){ 4095 var t = now(); 4096 4097 if ( gotoEnd || t >= this.options.duration + this.startTime ) { 4098 this.now = this.end; 4099 this.pos = this.state = 1; 4100 this.update(); 4101 4102 this.options.curAnim[ this.prop ] = true; 4103 4104 var done = true; 4105 for ( var i in this.options.curAnim ) 4106 if ( this.options.curAnim[i] !== true ) 4107 done = false; 4108 4109 if ( done ) { 4110 if ( this.options.display != null ) { 4111 // Reset the overflow 4112 this.elem.style.overflow = this.options.overflow; 4113 4114 // Reset the display 4115 this.elem.style.display = this.options.display; 4116 if ( jQuery.css(this.elem, "display") == "none" ) 4117 this.elem.style.display = "block"; 4118 } 4119 4120 // Hide the element if the "hide" operation was done 4121 if ( this.options.hide ) 4122 jQuery(this.elem).hide(); 4123 4124 // Reset the properties, if the item has been hidden or shown 4125 if ( this.options.hide || this.options.show ) 4126 for ( var p in this.options.curAnim ) 4127 jQuery.attr(this.elem.style, p, this.options.orig[p]); 4128 4129 // Execute the complete function 4130 this.options.complete.call( this.elem ); 4131 } 4132 4133 return false; 4134 } else { 4135 var n = t - this.startTime; 4136 this.state = n / this.options.duration; 4137 4138 // Perform the easing function, defaults to swing 4139 this.pos = jQuery.easing[this.options.easing || (jQuery.easing.swing ? "swing" : "linear")](this.state, n, 0, 1, this.options.duration); 4140 this.now = this.start + ((this.end - this.start) * this.pos); 4141 4142 // Perform the next step of the animation 4143 this.update(); 4144 } 4145 4146 return true; 4147 } 4148 4149}; 4150 4151jQuery.extend( jQuery.fx, { 4152 speeds:{ 4153 slow: 600, 4154 fast: 200, 4155 // Default speed 4156 _default: 400 4157 }, 4158 step: { 4159 4160 opacity: function(fx){ 4161 jQuery.attr(fx.elem.style, "opacity", fx.now); 4162 }, 4163 4164 _default: function(fx){ 4165 if ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) 4166 fx.elem.style[ fx.prop ] = fx.now + fx.unit; 4167 else 4168 fx.elem[ fx.prop ] = fx.now; 4169 } 4170 } 4171}); 4172if ( document.documentElement["getBoundingClientRect"] ) 4173 jQuery.fn.offset = function() { 4174 if ( !this[0] ) return { top: 0, left: 0 }; 4175 if ( this[0] === this[0].ownerDocument.body ) return jQuery.offset.bodyOffset( this[0] ); 4176 var box = this[0].getBoundingClientRect(), doc = this[0].ownerDocument, body = doc.body, docElem = doc.documentElement, 4177 clientTop = docElem.clientTop || body.clientTop || 0, clientLeft = docElem.clientLeft || body.clientLeft || 0, 4178 top = box.top + (self.pageYOffset || jQuery.boxModel && docElem.scrollTop || body.scrollTop ) - clientTop, 4179 left = box.left + (self.pageXOffset || jQuery.boxModel && docElem.scrollLeft || body.scrollLeft) - clientLeft; 4180 return { top: top, left: left }; 4181 }; 4182else 4183 jQuery.fn.offset = function() { 4184 if ( !this[0] ) return { top: 0, left: 0 }; 4185 if ( this[0] === this[0].ownerDocument.body ) return jQuery.offset.bodyOffset( this[0] ); 4186 jQuery.offset.initialized || jQuery.offset.initialize(); 4187 4188 var elem = this[0], offsetParent = elem.offsetParent, prevOffsetParent = elem, 4189 doc = elem.ownerDocument, computedStyle, docElem = doc.documentElement, 4190 body = doc.body, defaultView = doc.defaultView, 4191 prevComputedStyle = defaultView.getComputedStyle(elem, null), 4192 top = elem.offsetTop, left = elem.offsetLeft; 4193 4194 while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) { 4195 computedStyle = defaultView.getComputedStyle(elem, null); 4196 top -= elem.scrollTop, left -= elem.scrollLeft; 4197 if ( elem === offsetParent ) { 4198 top += elem.offsetTop, left += elem.offsetLeft; 4199 if ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && /^t(able|d|h)$/i.test(elem.tagName)) ) 4200 top += parseInt( computedStyle.borderTopWidth, 10) || 0, 4201 left += parseInt( computedStyle.borderLeftWidth, 10) || 0; 4202 prevOffsetParent = offsetParent, offsetParent = elem.offsetParent; 4203 } 4204 if ( jQuery.offset.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" ) 4205 top += parseInt( computedStyle.borderTopWidth, 10) || 0, 4206 left += parseInt( computedStyle.borderLeftWidth, 10) || 0; 4207 prevComputedStyle = computedStyle; 4208 } 4209 4210 if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" ) 4211 top += body.offsetTop, 4212 left += body.offsetLeft; 4213 4214 if ( prevComputedStyle.position === "fixed" ) 4215 top += Math.max(docElem.scrollTop, body.scrollTop), 4216 left += Math.max(docElem.scrollLeft, body.scrollLeft); 4217 4218 return { top: top, left: left }; 4219 }; 4220 4221jQuery.offset = { 4222 initialize: function() { 4223 if ( this.initialized ) return; 4224 var body = document.body, container = document.createElement('div'), innerDiv, checkDiv, table, td, rules, prop, bodyMarginTop = body.style.marginTop, 4225 html = '<div style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;"><div></div></div><table style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;" cellpadding="0" cellspacing="0"><tr><td></td></tr></table>'; 4226 4227 rules = { position: 'absolute', top: 0, left: 0, margin: 0, border: 0, width: '1px', height: '1px', visibility: 'hidden' }; 4228 for ( prop in rules ) container.style[prop] = rules[prop]; 4229 4230 container.innerHTML = html; 4231 body.insertBefore(container, body.firstChild); 4232 innerDiv = container.firstChild, checkDiv = innerDiv.firstChild, td = innerDiv.nextSibling.firstChild.firstChild; 4233 4234 this.doesNotAddBorder = (checkDiv.offsetTop !== 5); 4235 this.doesAddBorderForTableAndCells = (td.offsetTop === 5); 4236 4237 innerDiv.style.overflow = 'hidden', innerDiv.style.position = 'relative'; 4238 this.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5); 4239 4240 body.style.marginTop = '1px'; 4241 this.doesNotIncludeMarginInBodyOffset = (body.offsetTop === 0); 4242 body.style.marginTop = bodyMarginTop; 4243 4244 body.removeChild(container); 4245 this.initialized = true; 4246 }, 4247 4248 bodyOffset: function(body) { 4249 jQuery.offset.initialized || jQuery.offset.initialize(); 4250 var top = body.offsetTop, left = body.offsetLeft; 4251 if ( jQuery.offset.doesNotIncludeMarginInBodyOffset ) 4252 top += parseInt( jQuery.curCSS(body, 'marginTop', true), 10 ) || 0, 4253 left += parseInt( jQuery.curCSS(body, 'marginLeft', true), 10 ) || 0; 4254 return { top: top, left: left }; 4255 } 4256}; 4257 4258 4259jQuery.fn.extend({ 4260 position: function() { 4261 var left = 0, top = 0, results; 4262 4263 if ( this[0] ) { 4264 // Get *real* offsetParent 4265 var offsetParent = this.offsetParent(), 4266 4267 // Get correct offsets 4268 offset = this.offset(), 4269 parentOffset = /^body|html$/i.test(offsetParent[0].tagName) ? { top: 0, left: 0 } : offsetParent.offset(); 4270 4271 // Subtract element margins 4272 // note: when an element has margin: auto the offsetLeft and marginLeft 4273 // are the same in Safari causing offset.left to incorrectly be 0 4274 offset.top -= num( this, 'marginTop' ); 4275 offset.left -= num( this, 'marginLeft' ); 4276 4277 // Add offsetParent borders 4278 parentOffset.top += num( offsetParent, 'borderTopWidth' ); 4279 parentOffset.left += num( offsetParent, 'borderLeftWidth' ); 4280 4281 // Subtract the two offsets 4282 results = { 4283 top: offset.top - parentOffset.top, 4284 left: offset.left - parentOffset.left 4285 }; 4286 } 4287 4288 return results; 4289 }, 4290 4291 offsetParent: function() { 4292 var offsetParent = this[0].offsetParent || document.body; 4293 while ( offsetParent && (!/^body|html$/i.test(offsetParent.tagName) && jQuery.css(offsetParent, 'position') == 'static') ) 4294 offsetParent = offsetParent.offsetParent; 4295 return jQuery(offsetParent); 4296 } 4297}); 4298 4299 4300// Create scrollLeft and scrollTop methods 4301jQuery.each( ['Left', 'Top'], function(i, name) { 4302 var method = 'scroll' + name; 4303 4304 jQuery.fn[ method ] = function(val) { 4305 if (!this[0]) return null; 4306 4307 return val !== undefined ? 4308 4309 // Set the scroll offset 4310 this.each(function() { 4311 this == window || this == document ? 4312 window.scrollTo( 4313 !i ? val : jQuery(window).scrollLeft(), 4314 i ? val : jQuery(window).scrollTop() 4315 ) : 4316 this[ method ] = val; 4317 }) : 4318 4319 // Return the scroll offset 4320 this[0] == window || this[0] == document ? 4321 self[ i ? 'pageYOffset' : 'pageXOffset' ] || 4322 jQuery.boxModel && document.documentElement[ method ] || 4323 document.body[ method ] : 4324 this[0][ method ]; 4325 }; 4326}); 4327// Create innerHeight, innerWidth, outerHeight and outerWidth methods 4328jQuery.each([ "Height", "Width" ], function(i, name){ 4329 4330 var tl = i ? "Left" : "Top", // top or left 4331 br = i ? "Right" : "Bottom", // bottom or right 4332 lower = name.toLowerCase(); 4333 4334 // innerHeight and innerWidth 4335 jQuery.fn["inner" + name] = function(){ 4336 return this[0] ? 4337 jQuery.css( this[0], lower, false, "padding" ) : 4338 null; 4339 }; 4340 4341 // outerHeight and outerWidth 4342 jQuery.fn["outer" + name] = function(margin) { 4343 return this[0] ? 4344 jQuery.css( this[0], lower, false, margin ? "margin" : "border" ) : 4345 null; 4346 }; 4347 4348 var type = name.toLowerCase(); 4349 4350 jQuery.fn[ type ] = function( size ) { 4351 // Get window width or height 4352 return this[0] == window ? 4353 // Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode 4354 document.compatMode == "CSS1Compat" && document.documentElement[ "client" + name ] || 4355 document.body[ "client" + name ] : 4356 4357 // Get document width or height 4358 this[0] == document ? 4359 // Either scroll[Width/Height] or offset[Width/Height], whichever is greater 4360 Math.max( 4361 document.documentElement["client" + name], 4362 document.body["scroll" + name], document.documentElement["scroll" + name], 4363 document.body["offset" + name], document.documentElement["offset" + name] 4364 ) : 4365 4366 // Get or set width or height on the element 4367 size === undefined ? 4368 // Get width or height on the element 4369 (this.length ? jQuery.css( this[0], type ) : null) : 4370 4371 // Set the width or height on the element (default to pixels if value is unitless) 4372 this.css( type, typeof size === "string" ? size : size + "px" ); 4373 }; 4374 4375}); 4376})(); 4377/* 4378Script: Core.js 4379 MooTools - My Object Oriented JavaScript Tools. 4380 4381License: 4382 MIT-style license. 4383 4384Copyright: 4385 Copyright (c) 2006-2008 [Valerio Proietti](http://mad4milk.net/). 4386 4387Code & Documentation: 4388 [The MooTools production team](http://mootools.net/developers/). 4389 4390Inspiration: 4391 - 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) 4392 - Some functionality inspired by [Prototype.js](http://prototypejs.org) Copyright (c) 2005-2007 Sam Stephenson, [MIT License](http://opensource.org/licenses/mit-license.php) 4393*/ 4394 4395var MooTools = { 4396 'version': '1.2.2', 4397 'build': 'f0491d62fbb7e906789aa3733d6a67d43e5af7c9' 4398}; 4399 4400var Native = function(options){ 4401 options = options || {}; 4402 var name = options.name; 4403 var legacy = options.legacy; 4404 var protect = options.protect; 4405 var methods = options.implement; 4406 var generics = options.generics; 4407 var initialize = options.initialize; 4408 var afterImplement = options.afterImplement || function(){}; 4409 var object = initialize || legacy; 4410 generics = generics !== false; 4411 4412 object.constructor = Native; 4413 object.$family = {name: 'native'}; 4414 if (legacy && initialize) object.prototype = legacy.prototype; 4415 object.prototype.constructor = object; 4416 4417 if (name){ 4418 var family = name.toLowerCase(); 4419 object.prototype.$family = {name: family}; 4420 Native.typize(object, family); 4421 } 4422 4423 var add = function(obj, name, method, force){ 4424 if (!protect || force || !obj.prototype[name]) obj.prototype[name] = method; 4425 if (generics) Native.genericize(obj, name, protect); 4426 afterImplement.call(obj, name, method); 4427 return obj; 4428 }; 4429 4430 object.alias = function(a1, a2, a3){ 4431 if (typeof a1 == 'string'){ 4432 if ((a1 = this.prototype[a1])) return add(this, a2, a1, a3); 4433 } 4434 for (var a in a1) this.alias(a, a1[a], a2); 4435 return this; 4436 }; 4437 4438 object.implement = function(a1, a2, a3){ 4439 if (typeof a1 == 'string') return add(this, a1, a2, a3); 4440 for (var p in a1) add(this, p, a1[p], a2); 4441 return this; 4442 }; 4443 4444 if (methods) object.implement(methods); 4445 4446 return object; 4447}; 4448 4449Native.genericize = function(object, property, check){ 4450 if ((!check || !object[property]) && typeof object.prototype[property] == 'function') object[property] = function(){ 4451 var args = Array.prototype.slice.call(arguments); 4452 return object.prototype[property].apply(args.shift(), args); 4453 }; 4454}; 4455 4456Native.implement = function(objects, properties){ 4457 for (var i = 0, l = objects.length; i < l; i++) objects[i].implement(properties); 4458}; 4459 4460Native.typize = function(object, family){ 4461 if (!object.type) object.type = function(item){ 4462 return ($type(item) === family); 4463 }; 4464}; 4465 4466(function(){ 4467 var natives = {'Array': Array, 'Date': Date, 'Function': Function, 'Number': Number, 'RegExp': RegExp, 'String': String}; 4468 for (var n in natives) new Native({name: n, initialize: natives[n], protect: true}); 4469 4470 var types = {'boolean': Boolean, 'native': Native, 'object': Object}; 4471 for (var t in types) Native.typize(types[t], t); 4472 4473 var generics = { 4474 'Array': ["concat", "indexOf", "join", "lastIndexOf", "pop", "push", "reverse", "shift", "slice", "sort", "splice", "toString", "unshift", "valueOf"], 4475 'String': ["charAt", "charCodeAt", "concat", "indexOf", "lastIndexOf", "match", "replace", "search", "slice", "split", "substr", "substring", "toLowerCase", "toUpperCase", "valueOf"] 4476 }; 4477 for (var g in generics){ 4478 for (var i = generics[g].length; i--;) Native.genericize(window[g], generics[g][i], true); 4479 } 4480})(); 4481 4482var Hash = new Native({ 4483 4484 name: 'Hash', 4485 4486 initialize: function(object){ 4487 if ($type(object) == 'hash') object = $unlink(object.getClean()); 4488 for (var key in object) this[key] = object[key]; 4489 return this; 4490 } 4491 4492}); 4493 4494Hash.implement({ 4495 4496 forEach: function(fn, bind){ 4497 for (var key in this){ 4498 if (this.hasOwnProperty(key)) fn.call(bind, this[key], key, this); 4499 } 4500 }, 4501 4502 getClean: function(){ 4503 var clean = {}; 4504 for (var key in this){ 4505 if (this.hasOwnProperty(key)) clean[key] = this[key]; 4506 } 4507 return clean; 4508 }, 4509 4510 getLength: function(){ 4511 var length = 0; 4512 for (var key in this){ 4513 if (this.hasOwnProperty(key)) length++; 4514 } 4515 return length; 4516 } 4517 4518}); 4519 4520Hash.alias('forEach', 'each'); 4521 4522Array.implement({ 4523 4524 forEach: function(fn, bind){ 4525 for (var i = 0, l = this.length; i < l; i++) fn.call(bind, this[i], i, this); 4526 } 4527 4528}); 4529 4530Array.alias('forEach', 'each'); 4531 4532function $A(iterable){ 4533 if (iterable.item){ 4534 var l = iterable.length, array = new Array(l); 4535 while (l--) array[l] = iterable[l]; 4536 return array; 4537 } 4538 return Array.prototype.slice.call(iterable); 4539}; 4540 4541function $arguments(i){ 4542 return function(){ 4543 return arguments[i]; 4544 }; 4545}; 4546 4547function $chk(obj){ 4548 return !!(obj || obj === 0); 4549}; 4550 4551function $clear(timer){ 4552 clearTimeout(timer); 4553 clearInterval(timer); 4554 return null; 4555}; 4556 4557function $defined(obj){ 4558 return (obj != undefined); 4559}; 4560 4561function $each(iterable, fn, bind){ 4562 var type = $type(iterable); 4563 ((type == 'arguments' || type == 'collection' || type == 'array') ? Array : Hash).each(iterable, fn, bind); 4564}; 4565 4566function $empty(){}; 4567 4568function $extend(original, extended){ 4569 for (var key in (extended || {})) original[key] = extended[key]; 4570 return original; 4571}; 4572 4573function $H(object){ 4574 return new Hash(object); 4575}; 4576 4577function $lambda(value){ 4578 return (typeof value == 'function') ? value : function(){ 4579 return value; 4580 }; 4581}; 4582 4583function $merge(){ 4584 var args = Array.slice(arguments); 4585 args.unshift({}); 4586 return $mixin.apply(null, args); 4587}; 4588 4589function $mixin(mix){ 4590 for (var i = 1, l = arguments.length; i < l; i++){ 4591 var object = arguments[i]; 4592 if ($type(object) != 'object') continue; 4593 for (var key in object){ 4594 var op = object[key], mp = mix[key]; 4595 mix[key] = (mp && $type(op) == 'object' && $type(mp) == 'object') ? $mixin(mp, op) : $unlink(op); 4596 } 4597 } 4598 return mix; 4599}; 4600 4601function $pick(){ 4602 for (var i = 0, l = arguments.length; i < l; i++){ 4603 if (arguments[i] != undefined) return arguments[i]; 4604 } 4605 return null; 4606}; 4607 4608function $random(min, max){ 4609 return Math.floor(Math.random() * (max - min + 1) + min); 4610}; 4611 4612function $splat(obj){ 4613 var type = $type(obj); 4614 return (type) ? ((type != 'array' && type != 'arguments') ? [obj] : obj) : []; 4615}; 4616 4617var $time = Date.now || function(){ 4618 return +new Date; 4619}; 4620 4621function $try(){ 4622 for (var i = 0, l = arguments.length; i < l; i++){ 4623 try { 4624 return arguments[i](); 4625 } catch(e){} 4626 } 4627 return null; 4628}; 4629 4630function $type(obj){ 4631 if (obj == undefined) return false; 4632 if (obj.$family) return (obj.$family.name == 'number' && !isFinite(obj)) ? false : obj.$family.name; 4633 if (obj.nodeName){ 4634 switch (obj.nodeType){ 4635 case 1: return 'element'; 4636 case 3: return (/\S/).test(obj.nodeValue) ? 'textnode' : 'whitespace'; 4637 } 4638 } else if (typeof obj.length == 'number'){ 4639 if (obj.callee) return 'arguments'; 4640 else if (obj.item) return 'collection'; 4641 } 4642 return typeof obj; 4643}; 4644 4645function $unlink(object){ 4646 var unlinked; 4647 switch ($type(object)){ 4648 case 'object': 4649 unlinked = {}; 4650 for (var p in object) unlinked[p] = $unlink(object[p]); 4651 break; 4652 case 'hash': 4653 unlinked = new Hash(object); 4654 break; 4655 case 'array': 4656 unlinked = []; 4657 for (var i = 0, l = object.length; i < l; i++) unlinked[i] = $unlink(object[i]); 4658 break; 4659 default: return object; 4660 } 4661 return unlinked; 4662}; 4663 4664 4665/* 4666Script: Browser.js 4667 The Browser Core. Contains Browser initialization, Window and Document, and the Browser Hash. 4668 4669License: 4670 MIT-style license. 4671*/ 4672 4673var Browser = $merge({ 4674 4675 Engine: {name: 'unknown', version: 0}, 4676 4677 Platform: {name: (window.orientation != undefined) ? 'ipod' : (navigator.platform.match(/mac|win|linux/i) || ['other'])[0].toLowerCase()}, 4678 4679 Features: {xpath: !!(document.evaluate), air: !!(window.runtime), query: !!(document.querySelector)}, 4680 4681 Plugins: {}, 4682 4683 Engines: { 4684 4685 presto: function(){ 4686 return (!window.opera) ? false : ((arguments.callee.caller) ? 960 : ((document.getElementsByClassName) ? 950 : 925)); 4687 }, 4688 4689 trident: function(){ 4690 return (!window.ActiveXObject) ? false : ((window.XMLHttpRequest) ? 5 : 4); 4691 }, 4692 4693 webkit: function(){ 4694 return (navigator.taintEnabled) ? false : ((Browser.Features.xpath) ? ((Browser.Features.query) ? 525 : 420) : 419); 4695 }, 4696 4697 gecko: function(){ 4698 return (document.getBoxObjectFor == undefined) ? false : ((document.getElementsByClassName) ? 19 : 18); 4699 } 4700 4701 } 4702 4703}, Browser || {}); 4704 4705Browser.Platform[Browser.Platform.name] = true; 4706 4707Browser.detect = function(){ 4708 4709 for (var engine in this.Engines){ 4710 var version = this.Engines[engine](); 4711 if (version){ 4712 this.Engine = {name: engine, version: version}; 4713 this.Engine[engine] = this.Engine[engine + version] = true; 4714 break; 4715 } 4716 } 4717 4718 return {name: engine, version: version}; 4719 4720}; 4721 4722Browser.detect(); 4723 4724Browser.Request = function(){ 4725 return $try(function(){ 4726 return new XMLHttpRequest(); 4727 }, function(){ 4728 return new ActiveXObject('MSXML2.XMLHTTP'); 4729 }); 4730}; 4731 4732Browser.Features.xhr = !!(Browser.Request()); 4733 4734Browser.Plugins.Flash = (function(){ 4735 var version = ($try(function(){ 4736 return navigator.plugins['Shockwave Flash'].description; 4737 }, function(){ 4738 return new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version'); 4739 }) || '0 r0').match(/\d+/g); 4740 return {version: parseInt(version[0] || 0 + '.' + version[1], 10) || 0, build: parseInt(version[2], 10) || 0}; 4741})(); 4742 4743function $exec(text){ 4744 if (!text) return text; 4745 if (window.execScript){ 4746 window.execScript(text); 4747 } else { 4748 var script = document.createElement('script'); 4749 script.setAttribute('type', 'text/javascript'); 4750 script[(Browser.Engine.webkit && Browser.Engine.version < 420) ? 'innerText' : 'text'] = text; 4751 document.head.appendChild(script); 4752 document.head.removeChild(script); 4753 } 4754 return text; 4755}; 4756 4757Native.UID = 1; 4758 4759var $uid = (Browser.Engine.trident) ? function(item){ 4760 return (item.uid || (item.uid = [Native.UID++]))[0]; 4761} : function(item){ 4762 return item.uid || (item.uid = Native.UID++); 4763}; 4764 4765var Window = new Native({ 4766 4767 name: 'Window', 4768 4769 legacy: (Browser.Engine.trident) ? null: window.Window, 4770 4771 initialize: function(win){ 4772 $uid(win); 4773 if (!win.Element){ 4774 win.Element = $empty; 4775 if (Browser.Engine.webkit) win.document.createElement("iframe"); //fixes safari 2 4776 win.Element.prototype = (Browser.Engine.webkit) ? window["[[DOMElement.prototype]]"] : {}; 4777 } 4778 win.document.window = win; 4779 return $extend(win, Window.Prototype); 4780 }, 4781 4782 afterImplement: function(property, value){ 4783 window[property] = Window.Prototype[property] = value; 4784 } 4785 4786}); 4787 4788Window.Prototype = {$family: {name: 'window'}}; 4789 4790new Window(window); 4791 4792var Document = new Native({ 4793 4794 name: 'Document', 4795 4796 legacy: (Browser.Engine.trident) ? null: window.Document, 4797 4798 initialize: function(doc){ 4799 $uid(doc); 4800 doc.head = doc.getElementsByTagName('head')[0]; 4801 doc.html = doc.getElementsByTagName('html')[0]; 4802 if (Browser.Engine.trident && Browser.Engine.version <= 4) $try(function(){ 4803 doc.execCommand("BackgroundImageCache", false, true); 4804 }); 4805 if (Browser.Engine.trident) doc.window.attachEvent('onunload', function() { 4806 doc.window.detachEvent('onunload', arguments.callee); 4807 doc.head = doc.html = doc.window = null; 4808 }); 4809 return $extend(doc, Document.Prototype); 4810 }, 4811 4812 afterImplement: function(property, value){ 4813 document[property] = Document.Prototype[property] = value; 4814 } 4815 4816}); 4817 4818Document.Prototype = {$family: {name: 'document'}}; 4819 4820new Document(document); 4821 4822 4823/* 4824Script: Array.js 4825 Contains Array Prototypes like each, contains, and erase. 4826 4827License: 4828 MIT-style license. 4829*/ 4830 4831Array.implement({ 4832 4833 every: function(fn, bind){ 4834 for (var i = 0, l = this.length; i < l; i++){ 4835 if (!fn.call(bind, this[i], i, this)) return false; 4836 } 4837 return true; 4838 }, 4839 4840 filter: function(fn, bind){ 4841 var results = []; 4842 for (var i = 0, l = this.length; i < l; i++){ 4843 if (fn.call(bind, this[i], i, this)) results.push(this[i]); 4844 } 4845 return results; 4846 }, 4847 4848 clean: function() { 4849 return this.filter($defined); 4850 }, 4851 4852 indexOf: function(item, from){ 4853 var len = this.length; 4854 for (var i = (from < 0) ? Math.max(0, len + from) : from || 0; i < len; i++){ 4855 if (this[i] === item) return i; 4856 } 4857 return -1; 4858 }, 4859 4860 map: function(fn, bind){ 4861 var results = []; 4862 for (var i = 0, l = this.length; i < l; i++) results[i] = fn.call(bind, this[i], i, this); 4863 return results; 4864 }, 4865 4866 some: function(fn, bind){ 4867 for (var i = 0, l = this.length; i < l; i++){ 4868 if (fn.call(bind, this[i], i, this)) return true; 4869 } 4870 return false; 4871 }, 4872 4873 associate: function(keys){ 4874 var obj = {}, length = Math.min(this.length, keys.length); 4875 for (var i = 0; i < length; i++) obj[keys[i]] = this[i]; 4876 return obj; 4877 }, 4878 4879 link: function(object){ 4880 var result = {}; 4881 for (var i = 0, l = this.length; i < l; i++){ 4882 for (var key in object){ 4883 if (object[key](this[i])){ 4884 result[key] = this[i]; 4885 delete object[key]; 4886 break; 4887 } 4888 } 4889 } 4890 return result; 4891 }, 4892 4893 contains: function(item, from){ 4894 return this.indexOf(item, from) != -1; 4895 }, 4896 4897 extend: function(array){ 4898 for (var i = 0, j = array.length; i < j; i++) this.push(array[i]); 4899 return this; 4900 }, 4901 4902 getLast: function(){ 4903 return (this.length) ? this[this.length - 1] : null; 4904 }, 4905 4906 getRandom: function(){ 4907 return (this.length) ? this[$random(0, this.length - 1)] : null; 4908 }, 4909 4910 include: function(item){ 4911 if (!this.contains(item)) this.push(item); 4912 return this; 4913 }, 4914 4915 combine: function(array){ 4916 for (var i = 0, l = array.length; i < l; i++) this.include(array[i]); 4917 return this; 4918 }, 4919 4920 erase: function(item){ 4921 for (var i = this.length; i--; i){ 4922 if (this[i] === item) this.splice(i, 1); 4923 } 4924 return this; 4925 }, 4926 4927 empty: function(){ 4928 this.length = 0; 4929 return this; 4930 }, 4931 4932 flatten: function(){ 4933 var array = []; 4934 for (var i = 0, l = this.length; i < l; i++){ 4935 var type = $type(this[i]); 4936 if (!type) continue; 4937 array = array.concat((type == 'array' || type == 'collection' || type == 'arguments') ? Array.flatten(this[i]) : this[i]); 4938 } 4939 return array; 4940 }, 4941 4942 hexToRgb: function(array){ 4943 if (this.length != 3) return null; 4944 var rgb = this.map(function(value){ 4945 if (value.length == 1) value += value; 4946 return value.toInt(16); 4947 }); 4948 return (array) ? rgb : 'rgb(' + rgb + ')'; 4949 }, 4950 4951 rgbToHex: function(array){ 4952 if (this.length < 3) return null; 4953 if (this.length == 4 && this[3] == 0 && !array) return 'transparent'; 4954 var hex = []; 4955 for (var i = 0; i < 3; i++){ 4956 var bit = (this[i] - 0).toString(16); 4957 hex.push((bit.length == 1) ? '0' + bit : bit); 4958 } 4959 return (array) ? hex : '#' + hex.join(''); 4960 } 4961 4962}); 4963 4964 4965/* 4966Script: Function.js 4967 Contains Function Prototypes like create, bind, pass, and delay. 4968 4969License: 4970 MIT-style license. 4971*/ 4972 4973Function.implement({ 4974 4975 extend: function(properties){ 4976 for (var property in properties) this[property] = properties[property]; 4977 return this; 4978 }, 4979 4980 create: function(options){ 4981 var self = this; 4982 options = options || {}; 4983 return function(event){ 4984 var args = options.arguments; 4985 args = (args != undefined) ? $splat(args) : Array.slice(arguments, (options.event) ? 1 : 0); 4986 if (options.event) args = [event || window.event].extend(args); 4987 var returns = function(){ 4988 return self.apply(options.bind || null, args); 4989 }; 4990 if (options.delay) return setTimeout(returns, options.delay); 4991 if (options.periodical) return setInterval(returns, options.periodical); 4992 if (options.attempt) return $try(returns); 4993 return returns(); 4994 }; 4995 }, 4996 4997 run: function(args, bind){ 4998 return this.apply(bind, $splat(args)); 4999 }, 5000 5001 pass: function(args, bind){ 5002 return this.create({bind: bind, arguments: args}); 5003 }, 5004 5005 bind: function(bind, args){ 5006 return this.create({bind: bind, arguments: args}); 5007 }, 5008 5009 bindWithEvent: function(bind, args){ 5010 return this.create({bind: bind, arguments: args, event: true}); 5011 }, 5012 5013 attempt: function(args, bind){ 5014 return this.create({bind: bind, arguments: args, attempt: true})(); 5015 }, 5016 5017 delay: function(delay, bind, args){ 5018 return this.create({bind: bind, arguments: args, delay: delay})(); 5019 }, 5020 5021 periodical: function(periodical, bind, args){ 5022 return this.create({bind: bind, arguments: args, periodical: periodical})(); 5023 } 5024 5025}); 5026 5027 5028/* 5029Script: Number.js 5030 Contains Number Prototypes like limit, round, times, and ceil. 5031 5032License: 5033 MIT-style license. 5034*/ 5035 5036Number.implement({ 5037 5038 limit: function(min, max){ 5039 return Math.min(max, Math.max(min, this)); 5040 }, 5041 5042 round: function(precision){ 5043 precision = Math.pow(10, precision || 0); 5044 return Math.round(this * precision) / precision; 5045 }, 5046 5047 times: function(fn, bind){ 5048 for (var i = 0; i < this; i++) fn.call(bind, i, this); 5049 }, 5050 5051 toFloat: function(){ 5052 return parseFloat(this); 5053 }, 5054 5055 toInt: function(base){ 5056 return parseInt(this, base || 10); 5057 } 5058 5059}); 5060 5061Number.alias('times', 'each'); 5062 5063(function(math){ 5064 var methods = {}; 5065 math.each(function(name){ 5066 if (!Number[name]) methods[name] = function(){ 5067 return Math[name].apply(null, [this].concat($A(arguments))); 5068 }; 5069 }); 5070 Number.implement(methods); 5071})(['abs', 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'exp', 'floor', 'log', 'max', 'min', 'pow', 'sin', 'sqrt', 'tan']); 5072 5073 5074/* 5075Script: String.js 5076 Contains String Prototypes like camelCase, capitalize, test, and toInt. 5077 5078License: 5079 MIT-style license. 5080*/ 5081 5082String.implement({ 5083 5084 test: function(regex, params){ 5085 return ((typeof regex == 'string') ? new RegExp(regex, params) : regex).test(this); 5086 }, 5087 5088 contains: function(string, separator){ 5089 return (separator) ? (separator + this + separator).indexOf(separator + string + separator) > -1 : this.indexOf(string) > -1; 5090 }, 5091 5092 trim: function(){ 5093 return this.replace(/^\s+|\s+$/g, ''); 5094 }, 5095 5096 clean: function(){ 5097 return this.replace(/\s+/g, ' ').trim(); 5098 }, 5099 5100 camelCase: function(){ 5101 return this.replace(/-\D/g, function(match){ 5102 return match.charAt(1).toUpperCase(); 5103 }); 5104 }, 5105 5106 hyphenate: function(){ 5107 return this.replace(/[A-Z]/g, function(match){ 5108 return ('-' + match.charAt(0).toLowerCase()); 5109 }); 5110 }, 5111 5112 capitalize: function(){ 5113 return this.replace(/\b[a-z]/g, function(match){ 5114 return match.toUpperCase(); 5115 }); 5116 }, 5117 5118 escapeRegExp: function(){ 5119 return this.replace(/([-.*+?^${}()|[\]\/\\])/g, '\\$1'); 5120 }, 5121 5122 toInt: function(base){ 5123 return parseInt(this, base || 10); 5124 }, 5125 5126 toFloat: function(){ 5127 return parseFloat(this); 5128 }, 5129 5130 hexToRgb: function(array){ 5131 var hex = this.match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/); 5132 return (hex) ? hex.slice(1).hexToRgb(array) : null; 5133 }, 5134 5135 rgbToHex: function(array){ 5136 var rgb = this.match(/\d{1,3}/g); 5137 return (rgb) ? rgb.rgbToHex(array) : null; 5138 }, 5139 5140 stripScripts: function(option){ 5141 var scripts = ''; 5142 var text = this.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi, function(){ 5143 scripts += arguments[1] + '\n'; 5144 return ''; 5145 }); 5146 if (option === true) $exec(scripts); 5147 else if ($type(option) == 'function') option(scripts, text); 5148 return text; 5149 }, 5150 5151 substitute: function(object, regexp){ 5152 return this.replace(regexp || (/\\?\{([^{}]+)\}/g), function(match, name){ 5153 if (match.charAt(0) == '\\') return match.slice(1); 5154 return (object[name] != undefined) ? object[name] : ''; 5155 }); 5156 } 5157 5158}); 5159 5160 5161/* 5162Script: Hash.js 5163 Contains Hash Prototypes. Provides a means for overcoming the JavaScript practical impossibility of extending native Objects. 5164 5165License: 5166 MIT-style license. 5167*/ 5168 5169Hash.implement({ 5170 5171 has: Object.prototype.hasOwnProperty, 5172 5173 keyOf: function(value){ 5174 for (var key in this){ 5175 if (this.hasOwnProperty(key) && this[key] === value) return key; 5176 } 5177 return null; 5178 }, 5179 5180 hasValue: function(value){ 5181 return (Hash.keyOf(this, value) !== null); 5182 }, 5183 5184 extend: function(properties){ 5185 Hash.each(properties, function(value, key){ 5186 Hash.set(this, key, value); 5187 }, this); 5188 return this; 5189 }, 5190 5191 combine: function(properties){ 5192 Hash.each(properties, function(value, key){ 5193 Hash.include(this, key, value); 5194 }, this); 5195 return this; 5196 }, 5197 5198 erase: function(key){ 5199 if (this.hasOwnProperty(key)) delete this[key]; 5200 return this; 5201 }, 5202 5203 get: function(key){ 5204 return (this.hasOwnProperty(key)) ? this[key] : null; 5205 }, 5206 5207 set: function(key, value){ 5208 if (!this[key] || this.hasOwnProperty(key)) this[key] = value; 5209 return this; 5210 }, 5211 5212 empty: function(){ 5213 Hash.each(this, function(value, key){ 5214 delete this[key]; 5215 }, this); 5216 return this; 5217 }, 5218 5219 include: function(key, value){ 5220 if (this[key] == undefined) this[key] = value; 5221 return this; 5222 }, 5223 5224 map: function(fn, bind){ 5225 var results = new Hash; 5226 Hash.each(this, function(value, key){ 5227 results.set(key, fn.call(bind, value, key, this)); 5228 }, this); 5229 return results; 5230 }, 5231 5232 filter: function(fn, bind){ 5233 var results = new Hash; 5234 Hash.each(this, function(value, key){ 5235 if (fn.call(bind, value, key, this)) results.set(key, value); 5236 }, this); 5237 return results; 5238 }, 5239 5240 every: function(fn, bind){ 5241 for (var key in this){ 5242 if (this.hasOwnProperty(key) && !fn.call(bind, this[key], key)) return false; 5243 } 5244 return true; 5245 }, 5246 5247 some: function(fn, bind){ 5248 for (var key in this){ 5249 if (this.hasOwnProperty(key) && fn.call(bind, this[key], key)) return true; 5250 } 5251 return false; 5252 }, 5253 5254 getKeys: function(){ 5255 var keys = []; 5256 Hash.each(this, function(value, key){ 5257 keys.push(key); 5258 }); 5259 return keys; 5260 }, 5261 5262 getValues: function(){ 5263 var values = []; 5264 Hash.each(this, function(value){ 5265 values.push(value); 5266 }); 5267 return values; 5268 }, 5269 5270 toQueryString: function(base){ 5271 var queryString = []; 5272 Hash.each(this, function(value, key){ 5273 if (base) key = base + '[' + key + ']'; 5274 var result; 5275 switch ($type(value)){ 5276 case 'object': result = Hash.toQueryString(value, key); break; 5277 case 'array': 5278 var qs = {}; 5279 value.each(function(val, i){ 5280 qs[i] = val; 5281 }); 5282 result = Hash.toQueryString(qs, key); 5283 break; 5284 default: result = key + '=' + encodeURIComponent(value); 5285 } 5286 if (value != undefined) queryString.push(result); 5287 }); 5288 5289 return queryString.join('&'); 5290 } 5291 5292}); 5293 5294Hash.alias({keyOf: 'indexOf', hasValue: 'contains'}); 5295 5296 5297/* 5298Script: Event.js 5299 Contains the Event Native, to make the event object completely crossbrowser. 5300 5301License: 5302 MIT-style license. 5303*/ 5304 5305var Event = new Native({ 5306 5307 name: 'Event', 5308 5309 initialize: function(event, win){ 5310 win = win || window; 5311 var doc = win.document; 5312 event = event || win.event; 5313 if (event.$extended) return event; 5314 this.$extended = true; 5315 var type = event.type; 5316 var target = event.target || event.srcElement; 5317 while (target && target.nodeType == 3) target = target.parentNode; 5318 5319 if (type.test(/key/)){ 5320 var code = event.which || event.keyCode; 5321 var key = Event.Keys.keyOf(code); 5322 if (type == 'keydown'){ 5323 var fKey = code - 111; 5324 if (fKey > 0 && fKey < 13) key = 'f' + fKey; 5325 } 5326 key = key || String.fromCharCode(code).toLowerCase(); 5327 } else if (type.match(/(click|mouse|menu)/i)){ 5328 doc = (!doc.compatMode || doc.compatMode == 'CSS1Compat') ? doc.html : doc.body; 5329 var page = { 5330 x: event.pageX || event.clientX + doc.scrollLeft, 5331 y: event.pageY || event.clientY + doc.scrollTop 5332 }; 5333 var client = { 5334 x: (event.pageX) ? event.pageX - win.pageXOffset : event.clientX, 5335 y: (event.pageY) ? event.pageY - win.pageYOffset : event.clientY 5336 }; 5337 if (type.match(/DOMMouseScroll|mousewheel/)){ 5338 var wheel = (event.wheelDelta) ? event.wheelDelta / 120 : -(event.detail || 0) / 3; 5339 } 5340 var rightClick = (event.which == 3) || (event.button == 2); 5341 var related = null; 5342 if (type.match(/over|out/)){ 5343 switch (type){ 5344 case 'mouseover': related = event.relatedTarget || event.fromElement; break; 5345 case 'mouseout': related = event.relatedTarget || event.toElement; 5346 } 5347 if (!(function(){ 5348 while (related && related.nodeType == 3) related = related.parentNode; 5349 return true; 5350 }).create({attempt: Browser.Engine.gecko})()) related = false; 5351 } 5352 } 5353 5354 return $extend(this, { 5355 event: event, 5356 type: type, 5357 5358 page: page, 5359 client: client, 5360 rightClick: rightClick, 5361 5362 wheel: wheel, 5363 5364 relatedTarget: related, 5365 target: target, 5366 5367 code: code, 5368 key: key, 5369 5370 shift: event.shiftKey, 5371 control: event.ctrlKey, 5372 alt: event.altKey, 5373 meta: event.metaKey 5374 }); 5375 } 5376 5377}); 5378 5379Event.Keys = new Hash({ 5380 'enter': 13, 5381 'up': 38, 5382 'down': 40, 5383 'left': 37, 5384 'right': 39, 5385 'esc': 27, 5386 'space': 32, 5387 'backspace': 8, 5388 'tab': 9, 5389 'delete': 46 5390}); 5391 5392Event.implement({ 5393 5394 stop: function(){ 5395 return this.stopPropagation().preventDefault(); 5396 }, 5397 5398 stopPropagation: function(){ 5399 if (this.event.stopPropagation) this.event.stopPropagation(); 5400 else this.event.cancelBubble = true; 5401 return this; 5402 }, 5403 5404 preventDefault: function(){ 5405 if (this.event.preventDefault) this.event.preventDefault(); 5406 else this.event.returnValue = false; 5407 return this; 5408 } 5409 5410}); 5411 5412 5413/* 5414Script: Class.js 5415 Contains the Class Function for easily creating, extending, and implementing reusable Classes. 5416 5417License: 5418 MIT-style license. 5419*/ 5420 5421function Class(params){ 5422 5423 if (params instanceof Function) params = {initialize: params}; 5424 5425 var newClass = function(){ 5426 Object.reset(this); 5427 if (newClass._prototyping) return this; 5428 this._current = $empty; 5429 var value = (this.initialize) ? this.initialize.apply(this, arguments) : this; 5430 delete this._current; delete this.caller; 5431 return value; 5432 }.extend(this); 5433 5434 newClass.implement(params); 5435 5436 newClass.constructor = Class; 5437 newClass.prototype.constructor = newClass; 5438 5439 return newClass; 5440 5441}; 5442 5443Function.prototype.protect = function(){ 5444 this._protected = true; 5445 return this; 5446}; 5447 5448Object.reset = function(object, key){ 5449 5450 if (key == null){ 5451 for (var p in object) Object.reset(object, p); 5452 return object; 5453 } 5454 5455 delete object[key]; 5456 5457 switch ($type(object[key])){ 5458 case 'object': 5459 var F = function(){}; 5460 F.prototype = object[key]; 5461 var i = new F; 5462 object[key] = Object.reset(i); 5463 break; 5464 case 'array': object[key] = $unlink(object[key]); break; 5465 } 5466 5467 return object; 5468 5469}; 5470 5471new Native({name: 'Class', initialize: Class}).extend({ 5472 5473 instantiate: function(F){ 5474 F._prototyping = true; 5475 var proto = new F; 5476 delete F._prototyping; 5477 return proto; 5478 }, 5479 5480 wrap: function(self, key, method){ 5481 if (method._origin) method = method._origin; 5482 5483 return function(){ 5484 if (method._protected && this._current == null) throw new Error('The method "' + key + '" cannot be called.'); 5485 var caller = this.caller, current = this._current; 5486 this.caller = current; this._current = arguments.callee; 5487 var result = method.apply(this, arguments); 5488 this._current = current; this.caller = caller; 5489 return result; 5490 }.extend({_owner: self, _origin: method, _name: key}); 5491 5492 } 5493 5494}); 5495 5496Class.implement({ 5497 5498 implement: function(key, value){ 5499 5500 if ($type(key) == 'object'){ 5501 for (var p in key) this.implement(p, key[p]); 5502 return this; 5503 } 5504 5505 var mutator = Class.Mutators[key]; 5506 5507 if (mutator){ 5508 value = mutator.call(this, value); 5509 if (value == null) return this; 5510 } 5511 5512 var proto = this.prototype; 5513 5514 switch ($type(value)){ 5515 5516 case 'function': 5517 if (value._hidden) return this; 5518 proto[key] = Class.wrap(this, key, value); 5519 break; 5520 5521 case 'object': 5522 var previous = proto[key]; 5523 if ($type(previous) == 'object') $mixin(previous, value); 5524 else proto[key] = $unlink(value); 5525 break; 5526 5527 case 'array': 5528 proto[key] = $unlink(value); 5529 break; 5530 5531 default: proto[key] = value; 5532 5533 } 5534 5535 return this; 5536 5537 } 5538 5539}); 5540 5541Class.Mutators = { 5542 5543 Extends: function(parent){ 5544 5545 this.parent = parent; 5546 this.prototype = Class.instantiate(parent); 5547 5548 this.implement('parent', function(){ 5549 var name = this.caller._name, previous = this.caller._owner.parent.prototype[name]; 5550 if (!previous) throw new Error('The method "' + name + '" has no parent.'); 5551 return previous.apply(this, arguments); 5552 }.protect()); 5553 5554 }, 5555 5556 Implements: function(items){ 5557 $splat(items).each(function(item){ 5558 if (item instanceof Function) item = Class.instantiate(item); 5559 this.implement(item); 5560 }, this); 5561 5562 } 5563 5564}; 5565 5566 5567/* 5568Script: Class.Extras.js 5569 Contains Utility Classes that can be implemented into your own Classes to ease the execution of many common tasks. 5570 5571License: 5572 MIT-style license. 5573*/ 5574 5575var Chain = new Class({ 5576 5577 $chain: [], 5578 5579 chain: function(){ 5580 this.$chain.extend(Array.flatten(arguments)); 5581 return this; 5582 }, 5583 5584 callChain: function(){ 5585 return (this.$chain.length) ? this.$chain.shift().apply(this, arguments) : false; 5586 }, 5587 5588 clearChain: function(){ 5589 this.$chain.empty(); 5590 return this; 5591 } 5592 5593}); 5594 5595var Events = new Class({ 5596 5597 $events: {}, 5598 5599 addEvent: function(type, fn, internal){ 5600 type = Events.removeOn(type); 5601 if (fn != $empty){ 5602 this.$events[type] = this.$events[type] || []; 5603 this.$events[type].include(fn); 5604 if (internal) fn.internal = true; 5605 } 5606 return this; 5607 }, 5608 5609 addEvents: function(events){ 5610 for (var type in events) this.addEvent(type, events[type]); 5611 return this; 5612 }, 5613 5614 fireEvent: function(type, args, delay){ 5615 type = Events.removeOn(type); 5616 if (!this.$events || !this.$events[type]) return this; 5617 this.$events[type].each(function(fn){ 5618 fn.create({'bind': this, 'delay': delay, 'arguments': args})(); 5619 }, this); 5620 return this; 5621 }, 5622 5623 removeEvent: function(type, fn){ 5624 type = Events.removeOn(type); 5625 if (!this.$events[type]) return this; 5626 if (!fn.internal) this.$events[type].erase(fn); 5627 return this; 5628 }, 5629 5630 removeEvents: function(events){ 5631 var type; 5632 if ($type(events) == 'object'){ 5633 for (type in events) this.removeEvent(type, events[type]); 5634 return this; 5635 } 5636 if (events) events = Events.removeOn(events); 5637 for (type in this.$events){ 5638 if (events && events != type) continue; 5639 var fns = this.$events[type]; 5640 for (var i = fns.length; i--; i) this.removeEvent(type, fns[i]); 5641 } 5642 return this; 5643 } 5644 5645}); 5646 5647Events.removeOn = function(string){ 5648 return string.replace(/^on([A-Z])/, function(full, first) { 5649 return first.toLowerCase(); 5650 }); 5651}; 5652 5653var Options = new Class({ 5654 5655 setOptions: function(){ 5656 this.options = $merge.run([this.options].extend(arguments)); 5657 if (!this.addEvent) return this; 5658 for (var option in this.options){ 5659 if ($type(this.options[option]) != 'function' || !(/^on[A-Z]/).test(option)) continue; 5660 this.addEvent(option, this.options[option]); 5661 delete this.options[option]; 5662 } 5663 return this; 5664 } 5665 5666}); 5667 5668 5669/* 5670Script: Element.js 5671 One of the most important items in MooTools. Contains the dollar function, the dollars function, and an handful of cross-browser, 5672 time-saver methods to let you easily work with HTML Elements. 5673 5674License: 5675 MIT-style license. 5676*/ 5677 5678var Element = new Native({ 5679 5680 name: 'Element', 5681 5682 legacy: window.Element, 5683 5684 initialize: function(tag, props){ 5685 var konstructor = Element.Constructors.get(tag); 5686 if (konstructor) return konstructor(props); 5687 if (typeof tag == 'string') return document.newElement(tag, props); 5688 return $(tag).set(props); 5689 }, 5690 5691 afterImplement: function(key, value){ 5692 Element.Prototype[key] = value; 5693 if (Array[key]) return; 5694 Elements.implement(key, function(){ 5695 var items = [], elements = true; 5696 for (var i = 0, j = this.length; i < j; i++){ 5697 var returns = this[i][key].apply(this[i], arguments); 5698 items.push(returns); 5699 if (elements) elements = ($type(returns) == 'element'); 5700 } 5701 return (elements) ? new Elements(items) : items; 5702 }); 5703 } 5704 5705}); 5706 5707Element.Prototype = {$family: {name: 'element'}}; 5708 5709Element.Constructors = new Hash; 5710 5711var IFrame = new Native({ 5712 5713 name: 'IFrame', 5714 5715 generics: false, 5716 5717 initialize: function(){ 5718 var params = Array.link(arguments, {properties: Object.type, iframe: $defined}); 5719 var props = params.properties || {}; 5720 var iframe = $(params.iframe) || false; 5721 var onload = props.onload || $empty; 5722 delete props.onload; 5723 props.id = props.name = $pick(props.id, props.name, iframe.id, iframe.name, 'IFrame_' + $time()); 5724 iframe = new Element(iframe || 'iframe', props); 5725 var onFrameLoad = function(){ 5726 var host = $try(function(){ 5727 return iframe.contentWindow.location.host; 5728 }); 5729 if (host && host == window.location.host){ 5730 var win = new Window(iframe.contentWindow); 5731 new Document(iframe.contentWindow.document); 5732 $extend(win.Element.prototype, Element.Prototype); 5733 } 5734 onload.call(iframe.contentWindow, iframe.contentWindow.document); 5735 }; 5736 (window.frames[props.id]) ? onFrameLoad() : iframe.addListener('load', onFrameLoad); 5737 return iframe; 5738 } 5739 5740}); 5741 5742var Elements = new Native({ 5743 5744 initialize: function(elements, options){ 5745 options = $extend({ddup: true, cash: true}, options); 5746 elements = elements || []; 5747 if (options.ddup || options.cash){ 5748 var uniques = {}, returned = []; 5749 for (var i = 0, l = elements.length; i < l; i++){ 5750 var el = $.element(elements[i], !options.cash); 5751 if (options.ddup){ 5752 if (uniques[el.uid]) continue; 5753 uniques[el.uid] = true; 5754 } 5755 returned.push(el); 5756 } 5757 elements = returned; 5758 } 5759 return (options.cash) ? $extend(elements, this) : elements; 5760 } 5761 5762}); 5763 5764Elements.implement({ 5765 5766 filter: function(filter, bind){ 5767 if (!filter) return this; 5768 return new Elements(Array.filter(this, (typeof filter == 'string') ? function(item){ 5769 return item.match(filter); 5770 } : filter, bind)); 5771 } 5772 5773}); 5774 5775Document.implement({ 5776 5777 newElement: function(tag, props){ 5778 if (Browser.Engine.trident && props){ 5779 ['name', 'type', 'checked'].each(function(attribute){ 5780 if (!props[attribute]) return; 5781 tag += ' ' + attribute + '="' + props[attribute] + '"'; 5782 if (attribute != 'checked') delete props[attribute]; 5783 }); 5784 tag = '<' + tag + '>'; 5785 } 5786 return $.element(this.createElement(tag)).set(props); 5787 }, 5788 5789 newTextNode: function(text){ 5790 return this.createTextNode(text); 5791 }, 5792 5793 getDocument: function(){ 5794 return this; 5795 }, 5796 5797 getWindow: function(){ 5798 return this.window; 5799 } 5800 5801}); 5802 5803Window.implement({ 5804 5805 $: function(el, nocash){ 5806 if (el && el.$family && el.uid) return el; 5807 var type = $type(el); 5808 return ($[type]) ? $[type](el, nocash, this.document) : null; 5809 }, 5810 5811 $$: function(selector){ 5812 if (arguments.length == 1 && typeof selector == 'string') return this.document.getElements(selector); 5813 var elements = []; 5814 var args = Array.flatten(arguments); 5815 for (var i = 0, l = args.length; i < l; i++){ 5816 var item = args[i]; 5817 switch ($type(item)){ 5818 case 'element': elements.push(item); break; 5819 case 'string': elements.extend(this.document.getElements(item, true)); 5820 } 5821 } 5822 return new Elements(elements); 5823 }, 5824 5825 getDocument: function(){ 5826 return this.document; 5827 }, 5828 5829 getWindow: function(){ 5830 return this; 5831 } 5832 5833}); 5834 5835$.string = function(id, nocash, doc){ 5836 id = doc.getElementById(id); 5837 return (id) ? $.element(id, nocash) : null; 5838}; 5839 5840$.element = function(el, nocash){ 5841 $uid(el); 5842 if (!nocash && !el.$family && !(/^object|embed$/i).test(el.tagName)){ 5843 var proto = Element.Prototype; 5844 for (var p in proto) el[p] = proto[p]; 5845 }; 5846 return el; 5847}; 5848 5849$.object = function(obj, nocash, doc){ 5850 if (obj.toElement) return $.element(obj.toElement(doc), nocash); 5851 return null; 5852}; 5853 5854$.textnode = $.whitespace = $.window = $.document = $arguments(0); 5855 5856Native.implement([Element, Document], { 5857 5858 getElement: function(selector, nocash){ 5859 return $(this.getElements(selector, true)[0] || null, nocash); 5860 }, 5861 5862 getElements: function(tags, nocash){ 5863 tags = tags.split(','); 5864 var elements = []; 5865 var ddup = (tags.length > 1); 5866 tags.each(function(tag){ 5867 var partial = this.getElementsByTagName(tag.trim()); 5868 (ddup) ? elements.extend(partial) : elements = partial; 5869 }, this); 5870 return new Elements(elements, {ddup: ddup, cash: !nocash}); 5871 } 5872 5873}); 5874 5875(function(){ 5876 5877var collected = {}, storage = {}; 5878var props = {input: 'checked', option: 'selected', textarea: (Browser.Engine.webkit && Browser.Engine.version < 420) ? 'innerHTML' : 'value'}; 5879 5880var get = function(uid){ 5881 return (storage[uid] || (storage[uid] = {})); 5882}; 5883 5884var clean = function(item, retain){ 5885 if (!item) return; 5886 var uid = item.uid; 5887 if (Browser.Engine.trident){ 5888 if (item.clearAttributes){ 5889 var clone = retain && item.cloneNode(false); 5890 item.clearAttributes(); 5891 if (clone) item.mergeAttributes(clone); 5892 } else if (item.removeEvents){ 5893 item.removeEvents(); 5894 } 5895 if ((/object/i).test(item.tagName)){ 5896 for (var p in item){ 5897 if (typeof item[p] == 'function') item[p] = $empty; 5898 } 5899 Element.dispose(item); 5900 } 5901 } 5902 if (!uid) return; 5903 collected[uid] = storage[uid] = null; 5904}; 5905 5906var purge = function(){ 5907 Hash.each(collected, clean); 5908 if (Browser.Engine.trident) $A(document.getElementsByTagName('object')).each(clean); 5909 if (window.CollectGarbage) CollectGarbage(); 5910 collected = storage = null; 5911}; 5912 5913var walk = function(element, walk, start, match, all, nocash){ 5914 var el = element[start || walk]; 5915 var elements = []; 5916 while (el){ 5917 if (el.nodeType == 1 && (!match || Element.match(el, match))){ 5918 if (!all) return $(el, nocash); 5919 elements.push(el); 5920 } 5921 el = el[walk]; 5922 } 5923 return (all) ? new Elements(elements, {ddup: false, cash: !nocash}) : null; 5924}; 5925 5926var attributes = { 5927 'html': 'innerHTML', 5928 'class': 'className', 5929 'for': 'htmlFor', 5930 'text': (Browser.Engine.trident || (Browser.Engine.webkit && Browser.Engine.version < 420)) ? 'innerText' : 'textContent' 5931}; 5932var bools = ['compact', 'nowrap', 'ismap', 'declare', 'noshade', 'checked', 'disabled', 'readonly', 'multiple', 'selected', 'noresize', 'defer']; 5933var camels = ['value', 'accessKey', 'cellPadding', 'cellSpacing', 'colSpan', 'frameBorder', 'maxLength', 'readOnly', 'rowSpan', 'tabIndex', 'useMap']; 5934 5935bools = bools.associate(bools); 5936 5937Hash.extend(attributes, bools); 5938Hash.extend(attributes, camels.associate(camels.map(String.toLowerCase))); 5939 5940var inserters = { 5941 5942 before: function(context, element){ 5943 if (element.parentNode) element.parentNode.insertBefore(context, element); 5944 }, 5945 5946 after: function(context, element){ 5947 if (!element.parentNode) return; 5948 var next = element.nextSibling; 5949 (next) ? element.parentNode.insertBefore(context, next) : element.parentNode.appendChild(context); 5950 }, 5951 5952 bottom: function(context, element){ 5953 element.appendChild(context); 5954 }, 5955 5956 top: function(context, element){ 5957 var first = element.firstChild; 5958 (first) ? element.insertBefore(context, first) : element.appendChild(context); 5959 } 5960 5961}; 5962 5963inserters.inside = inserters.bottom; 5964 5965Hash.each(inserters, function(inserter, where){ 5966 5967 where = where.capitalize(); 5968 5969 Element.implement('inject' + where, function(el){ 5970 inserter(this, $(el, true)); 5971 return this; 5972 }); 5973 5974 Element.implement('grab' + where, function(el){ 5975 inserter($(el, true), this); 5976 return this; 5977 }); 5978 5979}); 5980 5981Element.implement({ 5982 5983 set: function(prop, value){ 5984 switch ($type(prop)){ 5985 case 'object': 5986 for (var p in prop) this.set(p, prop[p]); 5987 break; 5988 case 'string': 5989 var property = Element.Properties.get(prop); 5990 (property && property.set) ? property.set.apply(this, Array.slice(arguments, 1)) : this.setProperty(prop, value); 5991 } 5992 return this; 5993 }, 5994 5995 get: function(prop){ 5996 var property = Element.Properties.get(prop); 5997 return (property && property.get) ? property.get.apply(this, Array.slice(arguments, 1)) : this.getProperty(prop); 5998 }, 5999 6000 erase: function(prop){ 6001 var property = Element.Properties.get(prop); 6002 (property && property.erase) ? property.erase.apply(this) : this.removeProperty(prop); 6003 return this; 6004 }, 6005 6006 setProperty: function(attribute, value){ 6007 var key = attributes[attribute]; 6008 if (value == undefined) return this.removeProperty(attribute); 6009 if (key && bools[attribute]) value = !!value; 6010 (key) ? this[key] = value : this.setAttribute(attribute, '' + value); 6011 return this; 6012 }, 6013 6014 setProperties: function(attributes){ 6015 for (var attribute in attributes) this.setProperty(attribute, attributes[attribute]); 6016 return this; 6017 }, 6018 6019 getProperty: function(attribute){ 6020 var key = attributes[attribute]; 6021 var value = (key) ? this[key] : this.getAttribute(attribute, 2); 6022 return (bools[attribute]) ? !!value : (key) ? value : value || null; 6023 }, 6024 6025 getProperties: function(){ 6026 var args = $A(arguments); 6027 return args.map(this.getProperty, this).associate(args); 6028 }, 6029 6030 removeProperty: function(attribute){ 6031 var key = attributes[attribute]; 6032 (key) ? this[key] = (key && bools[attribute]) ? false : '' : this.removeAttribute(attribute); 6033 return this; 6034 }, 6035 6036 removeProperties: function(){ 6037 Array.each(arguments, this.removeProperty, this); 6038 return this; 6039 }, 6040 6041 hasClass: function(className){ 6042 return this.className.contains(className, ' '); 6043 }, 6044 6045 addClass: function(className){ 6046 if (!this.hasClass(className)) this.className = (this.className + ' ' + className).clean(); 6047 return this; 6048 }, 6049 6050 removeClass: function(className){ 6051 this.className = this.className.replace(new RegExp('(^|\\s)' + className + '(?:\\s|$)'), '$1'); 6052 return this; 6053 }, 6054 6055 toggleClass: function(className){ 6056 return this.hasClass(className) ? this.removeClass(className) : this.addClass(className); 6057 }, 6058 6059 adopt: function(){ 6060 Array.flatten(arguments).each(function(element){ 6061 element = $(element, true); 6062 if (element) this.appendChild(element); 6063 }, this); 6064 return this; 6065 }, 6066 6067 appendText: function(text, where){ 6068 return this.grab(this.getDocument().newTextNode(text), where); 6069 }, 6070 6071 grab: function(el, where){ 6072 inserters[where || 'bottom']($(el, true), this); 6073 return this; 6074 }, 6075 6076 inject: function(el, where){ 6077 inserters[where || 'bottom'](this, $(el, true)); 6078 return this; 6079 }, 6080 6081 replaces: function(el){ 6082 el = $(el, true); 6083 el.parentNode.replaceChild(this, el); 6084 return this; 6085 }, 6086 6087 wraps: function(el, where){ 6088 el = $(el, true); 6089 return this.replaces(el).grab(el, where); 6090 }, 6091 6092 getPrevious: function(match, nocash){ 6093 return walk(this, 'previousSibling', null, match, false, nocash); 6094 }, 6095 6096 getAllPrevious: function(match, nocash){ 6097 return walk(this, 'previousSibling', null, match, true, nocash); 6098 }, 6099 6100 getNext: function(match, nocash){ 6101 return walk(this, 'nextSibling', null, match, false, nocash); 6102 }, 6103 6104 getAllNext: function(match, nocash){ 6105 return walk(this, 'nextSibling', null, match, true, nocash); 6106 }, 6107 6108 getFirst: function(match, nocash){ 6109 return walk(this, 'nextSibling', 'firstChild', match, false, nocash); 6110 }, 6111 6112 getLast: function(match, nocash){ 6113 return walk(this, 'previousSibling', 'lastChild', match, false, nocash); 6114 }, 6115 6116 getParent: function(match, nocash){ 6117 return walk(this, 'parentNode', null, match, false, nocash); 6118 }, 6119 6120 getParents: function(match, nocash){ 6121 return walk(this, 'parentNode', null, match, true, nocash); 6122 }, 6123 6124 getSiblings: function(match, nocash) { 6125 return this.getParent().getChildren(match, nocash).erase(this); 6126 }, 6127 6128 getChildren: function(match, nocash){ 6129 return walk(this, 'nextSibling', 'firstChild', match, true, nocash); 6130 }, 6131 6132 getWindow: function(){ 6133 return this.ownerDocument.window; 6134 }, 6135 6136 getDocument: function(){ 6137 return this.ownerDocument; 6138 }, 6139 6140 getElementById: function(id, nocash){ 6141 var el = this.ownerDocument.getElementById(id); 6142 if (!el) return null; 6143 for (var parent = el.parentNode; parent != this; parent = parent.parentNode){ 6144 if (!parent) return null; 6145 } 6146 return $.element(el, nocash); 6147 }, 6148 6149 getSelected: function(){ 6150 return new Elements($A(this.options).filter(function(option){ 6151 return option.selected; 6152 })); 6153 }, 6154 6155 getComputedStyle: function(property){ 6156 if (this.currentStyle) return this.currentStyle[property.camelCase()]; 6157 var computed = this.getDocument().defaultView.getComputedStyle(this, null); 6158 return (computed) ? computed.getPropertyValue([property.hyphenate()]) : null; 6159 }, 6160 6161 toQueryString: function(){ 6162 var queryString = []; 6163 this.getElements('input, select, textarea', true).each(function(el){ 6164 if (!el.name || el.disabled) return; 6165 var value = (el.tagName.toLowerCase() == 'select') ? Element.getSelected(el).map(function(opt){ 6166 return opt.value; 6167 }) : ((el.type == 'radio' || el.type == 'checkbox') && !el.checked) ? null : el.value; 6168 $splat(value).each(function(val){ 6169 if (typeof val != 'undefined') queryString.push(el.name + '=' + encodeURIComponent(val)); 6170 }); 6171 }); 6172 return queryString.join('&'); 6173 }, 6174 6175 clone: function(contents, keepid){ 6176 contents = contents !== false; 6177 var clone = this.cloneNode(contents); 6178 var clean = function(node, element){ 6179 if (!keepid) node.removeAttribute('id'); 6180 if (Browser.Engine.trident){ 6181 node.clearAttributes(); 6182 node.mergeAttributes(element); 6183 node.removeAttribute('uid'); 6184 if (node.options){ 6185 var no = node.options, eo = element.options; 6186 for (var j = no.length; j--;) no[j].selected = eo[j].selected; 6187 } 6188 } 6189 var prop = props[element.tagName.toLowerCase()]; 6190 if (prop && element[prop]) node[prop] = element[prop]; 6191 }; 6192 6193 if (contents){ 6194 var ce = clone.getElementsByTagName('*'), te = this.getElementsByTagName('*'); 6195 for (var i = ce.length; i--;) clean(ce[i], te[i]); 6196 } 6197 6198 clean(clone, this); 6199 return $(clone); 6200 }, 6201 6202 destroy: function(){ 6203 Element.empty(this); 6204 Element.dispose(this); 6205 clean(this, true); 6206 return null; 6207 }, 6208 6209 empty: function(){ 6210 $A(this.childNodes).each(function(node){ 6211 Element.destroy(node); 6212 }); 6213 return this; 6214 }, 6215 6216 dispose: function(){ 6217 return (this.parentNode) ? this.parentNode.removeChild(this) : this; 6218 }, 6219 6220 hasChild: function(el){ 6221 el = $(el, true); 6222 if (!el) return false; 6223 if (Browser.Engine.webkit && Browser.Engine.version < 420) return $A(this.getElementsByTagName(el.tagName)).contains(el); 6224 return (this.contains) ? (this != el && this.contains(el)) : !!(this.compareDocumentPosition(el) & 16); 6225 }, 6226 6227 match: function(tag){ 6228 return (!tag || (tag == this) || (Element.get(this, 'tag') == tag)); 6229 } 6230 6231}); 6232 6233Native.implement([Element, Window, Document], { 6234 6235 addListener: function(type, fn){ 6236 if (type == 'unload'){ 6237 var old = fn, self = this; 6238 fn = function(){ 6239 self.removeListener('unload', fn); 6240 old(); 6241 }; 6242 } else { 6243 collected[this.uid] = this; 6244 } 6245 if (this.addEventListener) this.addEventListener(type, fn, false); 6246 else this.attachEvent('on' + type, fn); 6247 return this; 6248 }, 6249 6250 removeListener: function(type, fn){ 6251 if (this.removeEventListener) this.removeEventListener(type, fn, false); 6252 else this.detachEvent('on' + type, fn); 6253 return this; 6254 }, 6255 6256 retrieve: function(property, dflt){ 6257 var storage = get(this.uid), prop = storage[property]; 6258 if (dflt != undefined && prop == undefined) prop = storage[property] = dflt; 6259 return $pick(prop); 6260 }, 6261 6262 store: function(property, value){ 6263 var storage = get(this.uid); 6264 storage[property] = value; 6265 return this; 6266 }, 6267 6268 eliminate: function(property){ 6269 var storage = get(this.uid); 6270 delete storage[property]; 6271 return this; 6272 } 6273 6274}); 6275 6276window.addListener('unload', purge); 6277 6278})(); 6279 6280Element.Properties = new Hash; 6281 6282Element.Properties.style = { 6283 6284 set: function(style){ 6285 this.style.cssText = style; 6286 }, 6287 6288 get: function(){ 6289 return this.style.cssText; 6290 }, 6291 6292 erase: function(){ 6293 this.style.cssText = ''; 6294 } 6295 6296}; 6297 6298Element.Properties.tag = { 6299 6300 get: function(){ 6301 return this.tagName.toLowerCase(); 6302 } 6303 6304}; 6305 6306Element.Properties.html = (function(){ 6307 var wrapper = document.createElement('div'); 6308 6309 var translations = { 6310 table: [1, '<table>', '</table>'], 6311 select: [1, '<select>', '</select>'], 6312 tbody: [2, '<table><tbody>', '</tbody></table>'], 6313 tr: [3, '<table><tbody><tr>', '</tr></tbody></table>'] 6314 }; 6315 translations.thead = translations.tfoot = translations.tbody; 6316 6317 var html = { 6318 set: function(){ 6319 var html = Array.flatten(arguments).join(''); 6320 var wrap = Browser.Engine.trident && translations[this.get('tag')]; 6321 if (wrap){ 6322 var first = wrapper; 6323 first.innerHTML = wrap[1] + html + wrap[2]; 6324 for (var i = wrap[0]; i--;) first = first.firstChild; 6325 this.empty().adopt(first.childNodes); 6326 } else { 6327 this.innerHTML = html; 6328 } 6329 } 6330 }; 6331 6332 html.erase = html.set; 6333 6334 return html; 6335})(); 6336 6337if (Browser.Engine.webkit && Browser.Engine.version < 420) Element.Properties.text = { 6338 get: function(){ 6339 if (this.innerText) return this.innerText; 6340 var temp = this.ownerDocument.newElement('div', {html: this.innerHTML}).inject(this.ownerDocument.body); 6341 var text = temp.innerText; 6342 temp.destroy(); 6343 return text; 6344 } 6345}; 6346 6347 6348/* 6349Script: Element.Event.js 6350 Contains Element methods for dealing with events, and custom Events. 6351 6352License: 6353 MIT-style license. 6354*/ 6355 6356Element.Properties.events = {set: function(events){ 6357 this.addEvents(events); 6358}}; 6359 6360Native.implement([Element, Window, Document], { 6361 6362 addEvent: function(type, fn){ 6363 var events = this.retrieve('events', {}); 6364 events[type] = events[type] || {'keys': [], 'values': []}; 6365 if (events[type].keys.contains(fn)) return this; 6366 events[type].keys.push(fn); 6367 var realType = type, custom = Element.Events.get(type), condition = fn, self = this; 6368 if (custom){ 6369 if (custom.onAdd) custom.onAdd.call(this, fn); 6370 if (custom.condition){ 6371 condition = function(event){ 6372 if (custom.condition.call(this, event)) return fn.call(this, event); 6373 return true; 6374 }; 6375 } 6376 realType = custom.base || realType; 6377 } 6378 var defn = function(){ 6379 return fn.call(self); 6380 }; 6381 var nativeEvent = Element.NativeEvents[realType]; 6382 if (nativeEvent){ 6383 if (nativeEvent == 2){ 6384 defn = function(event){ 6385 event = new Event(event, self.getWindow()); 6386 if (condition.call(self, event) === false) event.stop(); 6387 }; 6388 } 6389 this.addListener(realType, defn); 6390 } 6391 events[type].values.push(defn); 6392 return this; 6393 }, 6394 6395 removeEvent: function(type, fn){ 6396 var events = this.retrieve('events'); 6397 if (!events || !events[type]) return this; 6398 var pos = events[type].keys.indexOf(fn); 6399 if (pos == -1) return this; 6400 events[type].keys.splice(pos, 1); 6401 var value = events[type].values.splice(pos, 1)[0]; 6402 var custom = Element.Events.get(type); 6403 if (custom){ 6404 if (custom.onRemove) custom.onRemove.call(this, fn); 6405 type = custom.base || type; 6406 } 6407 return (Element.NativeEvents[type]) ? this.removeListener(type, value) : this; 6408 }, 6409 6410 addEvents: function(events){ 6411 for (var event in events) this.addEvent(event, events[event]); 6412 return this; 6413 }, 6414 6415 removeEvents: function(events){ 6416 var type; 6417 if ($type(events) == 'object'){ 6418 for (type in events) this.removeEvent(type, events[type]); 6419 return this; 6420 } 6421 var attached = this.retrieve('events'); 6422 if (!attached) return this; 6423 if (!events){ 6424 for (type in attached) this.removeEvents(type); 6425 this.eliminate('events'); 6426 } else if (attached[events]){ 6427 while (attached[events].keys[0]) this.removeEvent(events, attached[events].keys[0]); 6428 attached[events] = null; 6429 } 6430 return this; 6431 }, 6432 6433 fireEvent: function(type, args, delay){ 6434 var events = this.retrieve('events'); 6435 if (!events || !events[type]) return this; 6436 events[type].keys.each(function(fn){ 6437 fn.create({'bind': this, 'delay': delay, 'arguments': args})(); 6438 }, this); 6439 return this; 6440 }, 6441 6442 cloneEvents: function(from, type){ 6443 from = $(from); 6444 var fevents = from.retrieve('events'); 6445 if (!fevents) return this; 6446 if (!type){ 6447 for (var evType in fevents) this.cloneEvents(from, evType); 6448 } else if (fevents[type]){ 6449 fevents[type].keys.each(function(fn){ 6450 this.addEvent(type, fn); 6451 }, this); 6452 } 6453 return this; 6454 } 6455 6456}); 6457 6458Element.NativeEvents = { 6459 click: 2, dblclick: 2, mouseup: 2, mousedown: 2, contextmenu: 2, //mouse buttons 6460 mousewheel: 2, DOMMouseScroll: 2, //mouse wheel 6461 mouseover: 2, mouseout: 2, mousemove: 2, selectstart: 2, selectend: 2, //mouse movement 6462 keydown: 2, keypress: 2, keyup: 2, //keyboard 6463 focus: 2, blur: 2, change: 2, reset: 2, select: 2, submit: 2, //form elements 6464 load: 1, unload: 1, beforeunload: 2, resize: 1, move: 1, DOMContentLoaded: 1, readystatechange: 1, //window 6465 error: 1, abort: 1, scroll: 1 //misc 6466}; 6467 6468(function(){ 6469 6470var $check = function(event){ 6471 var related = event.relatedTarget; 6472 if (related == undefined) return true; 6473 if (related === false) return false; 6474 return ($type(this) != 'document' && related != this && related.prefix != 'xul' && !this.hasChild(related)); 6475}; 6476 6477Element.Events = new Hash({ 6478 6479 mouseenter: { 6480 base: 'mouseover', 6481 condition: $check 6482 }, 6483 6484 mouseleave: { 6485 base: 'mouseout', 6486 condition: $check 6487 }, 6488 6489 mousewheel: { 6490 base: (Browser.Engine.gecko) ? 'DOMMouseScroll' : 'mousewheel' 6491 } 6492 6493}); 6494 6495})(); 6496 6497 6498/* 6499Script: Element.Style.js 6500 Contains methods for interacting with the styles of Elements in a fashionable way. 6501 6502License: 6503 MIT-style license. 6504*/ 6505 6506Element.Properties.styles = {set: function(styles){ 6507 this.setStyles(styles); 6508}}; 6509 6510Element.Properties.opacity = { 6511 6512 set: function(opacity, novisibility){ 6513 if (!novisibility){ 6514 if (opacity == 0){ 6515 if (this.style.visibility != 'hidden') this.style.visibility = 'hidden'; 6516 } else { 6517 if (this.style.visibility != 'visible') this.style.visibility = 'visible'; 6518 } 6519 } 6520 if (!this.currentStyle || !this.currentStyle.hasLayout) this.style.zoom = 1; 6521 if (Browser.Engine.trident) this.style.filter = (opacity == 1) ? '' : 'alpha(opacity=' + opacity * 100 + ')'; 6522 this.style.opacity = opacity; 6523 this.store('opacity', opacity); 6524 }, 6525 6526 get: function(){ 6527 return this.retrieve('opacity', 1); 6528 } 6529 6530}; 6531 6532Element.implement({ 6533 6534 setOpacity: function(value){ 6535 return this.set('opacity', value, true); 6536 }, 6537 6538 getOpacity: function(){ 6539 return this.get('opacity'); 6540 }, 6541 6542 setStyle: function(property, value){ 6543 switch (property){ 6544 case 'opacity': return this.set('opacity', parseFloat(value)); 6545 case 'float': property = (Browser.Engine.trident) ? 'styleFloat' : 'cssFloat'; 6546 } 6547 property = property.camelCase(); 6548 if ($type(value) != 'string'){ 6549 var map = (Element.Styles.get(property) || '@').split(' '); 6550 value = $splat(value).map(function(val, i){ 6551 if (!map[i]) return ''; 6552 return ($type(val) == 'number') ? map[i].replace('@', Math.round(val)) : val; 6553 }).join(' '); 6554 } else if (value == String(Number(value))){ 6555 value = Math.round(value); 6556 } 6557 this.style[property] = value; 6558 return this; 6559 }, 6560 6561 getStyle: function(property){ 6562 switch (property){ 6563 case 'opacity': return this.get('opacity'); 6564 case 'float': property = (Browser.Engine.trident) ? 'styleFloat' : 'cssFloat'; 6565 } 6566 property = property.camelCase(); 6567 var result = this.style[property]; 6568 if (!$chk(result)){ 6569 result = []; 6570 for (var style in Element.ShortStyles){ 6571 if (property != style) continue; 6572 for (var s in Element.ShortStyles[style]) result.push(this.getStyle(s)); 6573 return result.join(' '); 6574 } 6575 result = this.getComputedStyle(property); 6576 } 6577 if (result){ 6578 result = String(result); 6579 var color = result.match(/rgba?\([\d\s,]+\)/); 6580 if (color) result = result.replace(color[0], color[0].rgbToHex()); 6581 } 6582 if (Browser.Engine.presto || (Browser.Engine.trident && !$chk(parseInt(result, 10)))){ 6583 if (property.test(/^(height|width)$/)){ 6584 var values = (property == 'width') ? ['left', 'right'] : ['top', 'bottom'], size = 0; 6585 values.each(function(value){ 6586 size += this.getStyle('border-' + value + '-width').toInt() + this.getStyle('padding-' + value).toInt(); 6587 }, this); 6588 return this['offset' + property.capitalize()] - size + 'px'; 6589 } 6590 if ((Browser.Engine.presto) && String(result).test('px')) return result; 6591 if (property.test(/(border(.+)Width|margin|padding)/)) return '0px'; 6592 } 6593 return result; 6594 }, 6595 6596 setStyles: function(styles){ 6597 for (var style in styles) this.setStyle(style, styles[style]); 6598 return this; 6599 }, 6600 6601 getStyles: function(){ 6602 var result = {}; 6603 Array.each(arguments, function(key){ 6604 result[key] = this.getStyle(key); 6605 }, this); 6606 return result; 6607 } 6608 6609}); 6610 6611Element.Styles = new Hash({ 6612 left: '@px', top: '@px', bottom: '@px', right: '@px', 6613 width: '@px', height: '@px', maxWidth: '@px', maxHeight: '@px', minWidth: '@px', minHeight: '@px', 6614 backgroundColor: 'rgb(@, @, @)', backgroundPosition: '@px @px', color: 'rgb(@, @, @)', 6615 fontSize: '@px', letterSpacing: '@px', lineHeight: '@px', clip: 'rect(@px @px @px @px)', 6616 margin: '@px @px @px @px', padding: '@px @px @px @px', border: '@px @ rgb(@, @, @) @px @ rgb(@, @, @) @px @ rgb(@, @, @)', 6617 borderWidth: '@px @px @px @px', borderStyle: '@ @ @ @', borderColor: 'rgb(@, @, @) rgb(@, @, @) rgb(@, @, @) rgb(@, @, @)', 6618 zIndex: '@', 'zoom': '@', fontWeight: '@', textIndent: '@px', opacity: '@' 6619}); 6620 6621Element.ShortStyles = {margin: {}, padding: {}, border: {}, borderWidth: {}, borderStyle: {}, borderColor: {}}; 6622 6623['Top', 'Right', 'Bottom', 'Left'].each(function(direction){ 6624 var Short = Element.ShortStyles; 6625 var All = Element.Styles; 6626 ['margin', 'padding'].each(function(style){ 6627 var sd = style + direction; 6628 Short[style][sd] = All[sd] = '@px'; 6629 }); 6630 var bd = 'border' + direction; 6631 Short.border[bd] = All[bd] = '@px @ rgb(@, @, @)'; 6632 var bdw = bd + 'Width', bds = bd + 'Style', bdc = bd + 'Color'; 6633 Short[bd] = {}; 6634 Short.borderWidth[bdw] = Short[bd][bdw] = All[bdw] = '@px'; 6635 Short.borderStyle[bds] = Short[bd][bds] = All[bds] = '@'; 6636 Short.borderColor[bdc] = Short[bd][bdc] = All[bdc] = 'rgb(@, @, @)'; 6637}); 6638 6639 6640/* 6641Script: Element.Dimensions.js 6642 Contains methods to work with size, scroll, or positioning of Elements and the window object. 6643 6644License: 6645 MIT-style license. 6646 6647Credits: 6648 - Element positioning based on the [qooxdoo](http://qooxdoo.org/) code and smart browser fixes, [LGPL License](http://www.gnu.org/licenses/lgpl.html). 6649 - Viewport dimensions based on [YUI](http://developer.yahoo.com/yui/) code, [BSD License](http://developer.yahoo.com/yui/license.html). 6650*/ 6651 6652(function(){ 6653 6654Element.implement({ 6655 6656 scrollTo: function(x, y){ 6657 if (isBody(this)){ 6658 this.getWindow().scrollTo(x, y); 6659 } else { 6660 this.scrollLeft = x; 6661 this.scrollTop = y; 6662 } 6663 return this; 6664 }, 6665 6666 getSize: function(){ 6667 if (isBody(this)) return this.getWindow().getSize(); 6668 return {x: this.offsetWidth, y: this.offsetHeight}; 6669 }, 6670 6671 getScrollSize: function(){ 6672 if (isBody(this)) return this.getWindow().getScrollSize(); 6673 return {x: this.scrollWidth, y: this.scrollHeight}; 6674 }, 6675 6676 getScroll: function(){ 6677 if (isBody(this)) return this.getWindow().getScroll(); 6678 return {x: this.scrollLeft, y: this.scrollTop}; 6679 }, 6680 6681 getScrolls: function(){ 6682 var element = this, position = {x: 0, y: 0}; 6683 while (element && !isBody(element)){ 6684 position.x += element.scrollLeft; 6685 position.y += element.scrollTop; 6686 element = element.parentNode; 6687 } 6688 return position; 6689 }, 6690 6691 getOffsetParent: function(){ 6692 var element = this; 6693 if (isBody(element)) return null; 6694 if (!Browser.Engine.trident) return element.offsetParent; 6695 while ((element = element.parentNode) && !isBody(element)){ 6696 if (styleString(element, 'position') != 'static') return element; 6697 } 6698 return null; 6699 }, 6700 6701 getOffsets: function(){ 6702 if (Browser.Engine.trident){ 6703 var bound = this.getBoundingClientRect(), html = this.getDocument().documentElement; 6704 var isFixed = styleString(this, 'position') == 'fixed'; 6705 return { 6706 x: bound.left + ((isFixed) ? 0 : html.scrollLeft) - html.clientLeft, 6707 y: bound.top + ((isFixed) ? 0 : html.scrollTop) - html.clientTop 6708 }; 6709 } 6710 6711 var element = this, position = {x: 0, y: 0}; 6712 if (isBody(this)) return position; 6713 6714 while (element && !isBody(element)){ 6715 position.x += element.offsetLeft; 6716 position.y += element.offsetTop; 6717 6718 if (Browser.Engine.gecko){ 6719 if (!borderBox(element)){ 6720 position.x += leftBorder(element); 6721 position.y += topBorder(element); 6722 } 6723 var parent = element.parentNode; 6724 if (parent && styleString(parent, 'overflow') != 'visible'){ 6725 position.x += leftBorder(parent); 6726 position.y += topBorder(parent); 6727 } 6728 } else if (element != this && Browser.Engine.webkit){ 6729 position.x += leftBorder(element); 6730 position.y += topBorder(element); 6731 } 6732 6733 element = element.offsetParent; 6734 } 6735 if (Browser.Engine.gecko && !borderBox(this)){ 6736 position.x -= leftBorder(this); 6737 position.y -= topBorder(this); 6738 } 6739 return position; 6740 }, 6741 6742 getPosition: function(relative){ 6743 if (isBody(this)) return {x: 0, y: 0}; 6744 var offset = this.getOffsets(), scroll = this.getScrolls(); 6745 var position = {x: offset.x - scroll.x, y: offset.y - scroll.y}; 6746 var relativePosition = (relative && (relative = $(relative))) ? relative.getPosition() : {x: 0, y: 0}; 6747 return {x: position.x - relativePosition.x, y: position.y - relativePosition.y}; 6748 }, 6749 6750 getCoordinates: function(element){ 6751 if (isBody(this)) return this.getWindow().getCoordinates(); 6752 var position = this.getPosition(element), size = this.getSize(); 6753 var obj = {left: position.x, top: position.y, width: size.x, height: size.y}; 6754 obj.right = obj.left + obj.width; 6755 obj.bottom = obj.top + obj.height; 6756 return obj; 6757 }, 6758 6759 computePosition: function(obj){ 6760 return {left: obj.x - styleNumber(this, 'margin-left'), top: obj.y - styleNumber(this, 'margin-top')}; 6761 }, 6762 6763 position: function(obj){ 6764 return this.setStyles(this.computePosition(obj)); 6765 } 6766 6767}); 6768 6769Native.implement([Document, Window], { 6770 6771 getSize: function(){ 6772 if (Browser.Engine.presto || Browser.Engine.webkit) { 6773 var win = this.getWindow(); 6774 return {x: win.innerWidth, y: win.innerHeight}; 6775 } 6776 var doc = getCompatElement(this); 6777 return {x: doc.clientWidth, y: doc.clientHeight}; 6778 }, 6779 6780 getScroll: function(){ 6781 var win = this.getWindow(), doc = getCompatElement(this); 6782 return {x: win.pageXOffset || doc.scrollLeft, y: win.pageYOffset || doc.scrollTop}; 6783 }, 6784 6785 getScrollSize: function(){ 6786 var doc = getCompatElement(this), min = this.getSize(); 6787 return {x: Math.max(doc.scrollWidth, min.x), y: Math.max(doc.scrollHeight, min.y)}; 6788 }, 6789 6790 getPosition: function(){ 6791 return {x: 0, y: 0}; 6792 }, 6793 6794 getCoordinates: function(){ 6795 var size = this.getSize(); 6796 return {top: 0, left: 0, bottom: size.y, right: size.x, height: size.y, width: size.x}; 6797 } 6798 6799}); 6800 6801// private methods 6802 6803var styleString = Element.getComputedStyle; 6804 6805function styleNumber(element, style){ 6806 return styleString(element, style).toInt() || 0; 6807}; 6808 6809function borderBox(element){ 6810 return styleString(element, '-moz-box-sizing') == 'border-box'; 6811}; 6812 6813function topBorder(element){ 6814 return styleNumber(element, 'border-top-width'); 6815}; 6816 6817function leftBorder(element){ 6818 return styleNumber(element, 'border-left-width'); 6819}; 6820 6821function isBody(element){ 6822 return (/^(?:body|html)$/i).test(element.tagName); 6823}; 6824 6825function getCompatElement(element){ 6826 var doc = element.getDocument(); 6827 return (!doc.compatMode || doc.compatMode == 'CSS1Compat') ? doc.html : doc.body; 6828}; 6829 6830})(); 6831 6832//aliases 6833 6834Native.implement([Window, Document, Element], { 6835 6836 getHeight: function(){ 6837 return this.getSize().y; 6838 }, 6839 6840 getWidth: function(){ 6841 return this.getSize().x; 6842 }, 6843 6844 getScrollTop: function(){ 6845 return this.getScroll().y; 6846 }, 6847 6848 getScrollLeft: function(){ 6849 return this.getScroll().x; 6850 }, 6851 6852 getScrollHeight: function(){ 6853 return this.getScrollSize().y; 6854 }, 6855 6856 getScrollWidth: function(){ 6857 return this.getScrollSize().x; 6858 }, 6859 6860 getTop: function(){ 6861 return this.getPosition().y; 6862 }, 6863 6864 getLeft: function(){ 6865 return this.getPosition().x; 6866 } 6867 6868}); 6869 6870 6871/* 6872Script: Selectors.js 6873 Adds advanced CSS Querying capabilities for targeting elements. Also includes pseudoselectors support. 6874 6875License: 6876 MIT-style license. 6877*/ 6878 6879Native.implement([Document, Element], { 6880 6881 getElements: function(expression, nocash){ 6882 expression = expression.split(','); 6883 var items, local = {}; 6884 for (var i = 0, l = expression.length; i < l; i++){ 6885 var selector = expression[i], elements = Selectors.Utils.search(this, selector, local); 6886 if (i != 0 && elements.item) elements = $A(elements); 6887 items = (i == 0) ? elements : (items.item) ? $A(items).concat(elements) : items.concat(elements); 6888 } 6889 return new Elements(items, {ddup: (expression.length > 1), cash: !nocash}); 6890 } 6891 6892}); 6893 6894Element.implement({ 6895 6896 match: function(selector){ 6897 if (!selector || (selector == this)) return true; 6898 var tagid = Selectors.Utils.parseTagAndID(selector); 6899 var tag = tagid[0], id = tagid[1]; 6900 if (!Selectors.Filters.byID(this, id) || !Selectors.Filters.byTag(this, tag)) return false; 6901 var parsed = Selectors.Utils.parseSelector(selector); 6902 return (parsed) ? Selectors.Utils.filter(this, parsed, {}) : true; 6903 } 6904 6905}); 6906 6907var Selectors = {Cache: {nth: {}, parsed: {}}}; 6908 6909Selectors.RegExps = { 6910 id: (/#([\w-]+)/), 6911 tag: (/^(\w+|\*)/), 6912 quick: (/^(\w+|\*)$/), 6913 splitter: (/\s*([+>~\s])\s*([a-zA-Z#.*:\[])/g), 6914 combined: (/\.([\w-]+)|\[(\w+)(?:([!*^$~|]?=)(["']?)([^\4]*?)\4)?\]|:([\w-]+)(?:\(["']?(.*?)?["']?\)|$)/g) 6915}; 6916 6917Selectors.Utils = { 6918 6919 chk: function(item, uniques){ 6920 if (!uniques) return true; 6921 var uid = $uid(item); 6922 if (!uniques[uid]) return uniques[uid] = true; 6923 return false; 6924 }, 6925 6926 parseNthArgument: function(argument){ 6927 if (Selectors.Cache.nth[argument]) return Selectors.Cache.nth[argument]; 6928 var parsed = argument.match(/^([+-]?\d*)?([a-z]+)?([+-]?\d*)?$/); 6929 if (!parsed) return false; 6930 var inta = parseInt(parsed[1], 10); 6931 var a = (inta || inta === 0) ? inta : 1; 6932 var special = parsed[2] || false; 6933 var b = parseInt(parsed[3], 10) || 0; 6934 if (a != 0){ 6935 b--; 6936 while (b < 1) b += a; 6937 while (b >= a) b -= a; 6938 } else { 6939 a = b; 6940 special = 'index'; 6941 } 6942 switch (special){ 6943 case 'n': parsed = {a: a, b: b, special: 'n'}; break; 6944 case 'odd': parsed = {a: 2, b: 0, special: 'n'}; break; 6945 case 'even': parsed = {a: 2, b: 1, special: 'n'}; break; 6946 case 'first': parsed = {a: 0, special: 'index'}; break; 6947 case 'last': parsed = {special: 'last-child'}; break; 6948 case 'only': parsed = {special: 'only-child'}; break; 6949 default: parsed = {a: (a - 1), special: 'index'}; 6950 } 6951 6952 return Selectors.Cache.nth[argument] = parsed; 6953 }, 6954 6955 parseSelector: function(selector){ 6956 if (Selectors.Cache.parsed[selector]) return Selectors.Cache.parsed[selector]; 6957 var m, parsed = {classes: [], pseudos: [], attributes: []}; 6958 while ((m = Selectors.RegExps.combined.exec(selector))){ 6959 var cn = m[1], an = m[2], ao = m[3], av = m[5], pn = m[6], pa = m[7]; 6960 if (cn){ 6961 parsed.classes.push(cn); 6962 } else if (pn){ 6963 var parser = Selectors.Pseudo.get(pn); 6964 if (parser) parsed.pseudos.push({parser: parser, argument: pa}); 6965 else parsed.attributes.push({name: pn, operator: '=', value: pa}); 6966 } else if (an){ 6967 parsed.attributes.push({name: an, operator: ao, value: av}); 6968 } 6969 } 6970 if (!parsed.classes.length) delete parsed.classes; 6971 if (!parsed.attributes.length) delete parsed.attributes; 6972 if (!parsed.pseudos.length) delete parsed.pseudos; 6973 if (!parsed.classes && !parsed.attributes && !parsed.pseudos) parsed = null; 6974 return Selectors.Cache.parsed[selector] = parsed; 6975 }, 6976 6977 parseTagAndID: function(selector){ 6978 var tag = selector.match(Selectors.RegExps.tag); 6979 var id = selector.match(Selectors.RegExps.id); 6980 return [(tag) ? tag[1] : '*', (id) ? id[1] : false]; 6981 }, 6982 6983 filter: function(item, parsed, local){ 6984 var i; 6985 if (parsed.classes){ 6986 for (i = parsed.classes.length; i--; i){ 6987 var cn = parsed.classes[i]; 6988 if (!Selectors.Filters.byClass(item, cn)) return false; 6989 } 6990 } 6991 if (parsed.attributes){ 6992 for (i = parsed.attributes.length; i--; i){ 6993 var att = parsed.attributes[i]; 6994 if (!Selectors.Filters.byAttribute(item, att.name, att.operator, att.value)) return false; 6995 } 6996 } 6997 if (parsed.pseudos){ 6998 for (i = parsed.pseudos.length; i--; i){ 6999 var psd = parsed.pseudos[i]; 7000 if (!Selectors.Filters.byPseudo(item, psd.parser, psd.argument, local)) return false; 7001 } 7002 } 7003 return true; 7004 }, 7005 7006 getByTagAndID: function(ctx, tag, id){ 7007 if (id){ 7008 var item = (ctx.getElementById) ? ctx.getElementById(id, true) : Element.getElementById(ctx, id, true); 7009 return (item && Selectors.Filters.byTag(item, tag)) ? [item] : []; 7010 } else { 7011 return ctx.getElementsByTagName(tag); 7012 } 7013 }, 7014 7015 search: function(self, expression, local){ 7016 var splitters = []; 7017 7018 var selectors = expression.trim().replace(Selectors.RegExps.splitter, function(m0, m1, m2){ 7019 splitters.push(m1); 7020 return ':)' + m2; 7021 }).split(':)'); 7022 7023 var items, filtered, item; 7024 7025 for (var i = 0, l = selectors.length; i < l; i++){ 7026 7027 var selector = selectors[i]; 7028 7029 if (i == 0 && Selectors.RegExps.quick.test(selector)){ 7030 items = self.getElementsByTagName(selector); 7031 continue; 7032 } 7033 7034 var splitter = splitters[i - 1]; 7035 7036 var tagid = Selectors.Utils.parseTagAndID(selector); 7037 var tag = tagid[0], id = tagid[1]; 7038 7039 if (i == 0){ 7040 items = Selectors.Utils.getByTagAndID(self, tag, id); 7041 } else { 7042 var uniques = {}, found = []; 7043 for (var j = 0, k = items.length; j < k; j++) found = Selectors.Getters[splitter](found, items[j], tag, id, uniques); 7044 items = found; 7045 } 7046 7047 var parsed = Selectors.Utils.parseSelector(selector); 7048 7049 if (parsed){ 7050 filtered = []; 7051 for (var m = 0, n = items.length; m < n; m++){ 7052 item = items[m]; 7053 if (Selectors.Utils.filter(item, parsed, local)) filtered.push(item); 7054 } 7055 items = filtered; 7056 } 7057 7058 } 7059 7060 return items; 7061 7062 } 7063 7064}; 7065 7066Selectors.Getters = { 7067 7068 ' ': function(found, self, tag, id, uniques){ 7069 var items = Selectors.Utils.getByTagAndID(self, tag, id); 7070 for (var i = 0, l = items.length; i < l; i++){ 7071 var item = items[i]; 7072 if (Selectors.Utils.chk(item, uniques)) found.push(item); 7073 } 7074 return found; 7075 }, 7076 7077 '>': function(found, self, tag, id, uniques){ 7078 var children = Selectors.Utils.getByTagAndID(self, tag, id); 7079 for (var i = 0, l = children.length; i < l; i++){ 7080 var child = children[i]; 7081 if (child.parentNode == self && Selectors.Utils.chk(child, uniques)) found.push(child); 7082 } 7083 return found; 7084 }, 7085 7086 '+': function(found, self, tag, id, uniques){ 7087 while ((self = self.nextSibling)){ 7088 if (self.nodeType == 1){ 7089 if (Selectors.Utils.chk(self, uniques) && Selectors.Filters.byTag(self, tag) && Selectors.Filters.byID(self, id)) found.push(self); 7090 break; 7091 } 7092 } 7093 return found; 7094 }, 7095 7096 '~': function(found, self, tag, id, uniques){ 7097 while ((self = self.nextSibling)){ 7098 if (self.nodeType == 1){ 7099 if (!Selectors.Utils.chk(self, uniques)) break; 7100 if (Selectors.Filters.byTag(self, tag) && Selectors.Filters.byID(self, id)) found.push(self); 7101 } 7102 } 7103 return found; 7104 } 7105 7106}; 7107 7108Selectors.Filters = { 7109 7110 byTag: function(self, tag){ 7111 return (tag == '*' || (self.tagName && self.tagName.toLowerCase() == tag)); 7112 }, 7113 7114 byID: function(self, id){ 7115 return (!id || (self.id && self.id == id)); 7116 }, 7117 7118 byClass: function(self, klass){ 7119 return (self.className && self.className.contains(klass, ' ')); 7120 }, 7121 7122 byPseudo: function(self, parser, argument, local){ 7123 return parser.call(self, argument, local); 7124 }, 7125 7126 byAttribute: function(self, name, operator, value){ 7127 var result = Element.prototype.getProperty.call(self, name); 7128 if (!result) return (operator == '!='); 7129 if (!operator || value == undefined) return true; 7130 switch (operator){ 7131 case '=': return (result == value); 7132 case '*=': return (result.contains(value)); 7133 case '^=': return (result.substr(0, value.length) == value); 7134 case '$=': return (result.substr(result.length - value.length) == value); 7135 case '!=': return (result != value); 7136 case '~=': return result.contains(value, ' '); 7137 case '|=': return result.contains(value, '-'); 7138 } 7139 return false; 7140 } 7141 7142}; 7143 7144Selectors.Pseudo = new Hash({ 7145 7146 // w3c pseudo selectors 7147 7148 checked: function(){ 7149 return this.checked; 7150 }, 7151 7152 empty: function(){ 7153 return !(this.innerText || this.textContent || '').length; 7154 }, 7155 7156 not: function(selector){ 7157 return !Element.match(this, selector); 7158 }, 7159 7160 contains: function(text){ 7161 return (this.innerText || this.textContent || '').contains(text); 7162 }, 7163 7164 'first-child': function(){ 7165 return Selectors.Pseudo.index.call(this, 0); 7166 }, 7167 7168 'last-child': function(){ 7169 var element = this; 7170 while ((element = element.nextSibling)){ 7171 if (element.nodeType == 1) return false; 7172 } 7173 return true; 7174 }, 7175 7176 'only-child': function(){ 7177 var prev = this; 7178 while ((prev = prev.previousSibling)){ 7179 if (prev.nodeType == 1) return false; 7180 } 7181 var next = this; 7182 while ((next = next.nextSibling)){ 7183 if (next.nodeType == 1) return false; 7184 } 7185 return true; 7186 }, 7187 7188 'nth-child': function(argument, local){ 7189 argument = (argument == undefined) ? 'n' : argument; 7190 var parsed = Selectors.Utils.parseNthArgument(argument); 7191 if (parsed.special != 'n') return Selectors.Pseudo[parsed.special].call(this, parsed.a, local); 7192 var count = 0; 7193 local.positions = local.positions || {}; 7194 var uid = $uid(this); 7195 if (!local.positions[uid]){ 7196 var self = this; 7197 while ((self = self.previousSibling)){ 7198 if (self.nodeType != 1) continue; 7199 count ++; 7200 var position = local.positions[$uid(self)]; 7201 if (position != undefined){ 7202 count = position + count; 7203 break; 7204 } 7205 } 7206 local.positions[uid] = count; 7207 } 7208 return (local.positions[uid] % parsed.a == parsed.b); 7209 }, 7210 7211 // custom pseudo selectors 7212 7213 index: function(index){ 7214 var element = this, count = 0; 7215 while ((element = element.previousSibling)){ 7216 if (element.nodeType == 1 && ++count > index) return false; 7217 } 7218 return (count == index); 7219 }, 7220 7221 even: function(argument, local){ 7222 return Selectors.Pseudo['nth-child'].call(this, '2n+1', local); 7223 }, 7224 7225 odd: function(argument, local){ 7226 return Selectors.Pseudo['nth-child'].call(this, '2n', local); 7227 }, 7228 7229 selected: function() { 7230 return this.selected; 7231 } 7232 7233}); 7234 7235 7236/* 7237Script: Domready.js 7238 Contains the domready custom event. 7239 7240License: 7241 MIT-style license. 7242*/ 7243 7244Element.Events.domready = { 7245 7246 onAdd: function(fn){ 7247 if (Browser.loaded) fn.call(this); 7248 } 7249 7250}; 7251 7252(function(){ 7253 7254 var domready = function(){ 7255 if (Browser.loaded) return; 7256 Browser.loaded = true; 7257 window.fireEvent('domready'); 7258 document.fireEvent('domready'); 7259 }; 7260 7261 if (Browser.Engine.trident){ 7262 var temp = document.createElement('div'); 7263 (function(){ 7264 ($try(function(){ 7265 temp.doScroll('left'); 7266 return $(temp).inject(document.body).set('html', 'temp').dispose(); 7267 })) ? domready() : arguments.callee.delay(50); 7268 })(); 7269 } else if (Browser.Engine.webkit && Browser.Engine.version < 525){ 7270 (function(){ 7271 (['loaded', 'complete'].contains(document.readyState)) ? domready() : arguments.callee.delay(50); 7272 })(); 7273 } else { 7274 window.addEvent('load', domready); 7275 document.addEvent('DOMContentLoaded', domready); 7276 } 7277 7278})(); 7279 7280 7281/* 7282Script: JSON.js 7283 JSON encoder and decoder. 7284 7285License: 7286 MIT-style license. 7287 7288See Also: 7289 <http://www.json.org/> 7290*/ 7291 7292var JSON = new Hash({ 7293 7294 $specialChars: {'\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '"' : '\\"', '\\': '\\\\'}, 7295 7296 $replaceChars: function(chr){ 7297 return JSON.$specialChars[chr] || '\\u00' + Math.floor(chr.charCodeAt() / 16).toString(16) + (chr.charCodeAt() % 16).toString(16); 7298 }, 7299 7300 encode: function(obj){ 7301 switch ($type(obj)){ 7302 case 'string': 7303 return '"' + obj.replace(/[\x00-\x1f\\"]/g, JSON.$replaceChars) + '"'; 7304 case 'array': 7305 return '[' + String(obj.map(JSON.encode).filter($defined)) + ']'; 7306 case 'object': case 'hash': 7307 var string = []; 7308 Hash.each(obj, function(value, key){ 7309 var json = JSON.encode(value); 7310 if (json) string.push(JSON.encode(key) + ':' + json); 7311 }); 7312 return '{' + string + '}'; 7313 case 'number': case 'boolean': return String(obj); 7314 case false: return 'null'; 7315 } 7316 return null; 7317 }, 7318 7319 decode: function(string, secure){ 7320 if ($type(string) != 'string' || !string.length) return null; 7321 if (secure && !(/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(string.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''))) return null; 7322 return eval('(' + string + ')'); 7323 } 7324 7325}); 7326 7327Native.implement([Hash, Array, String, Number], { 7328 7329 toJSON: function(){ 7330 return JSON.encode(this); 7331 } 7332 7333}); 7334 7335 7336/* 7337Script: Cookie.js 7338 Class for creating, loading, and saving browser Cookies. 7339 7340License: 7341 MIT-style license. 7342 7343Credits: 7344 Based on the functions by Peter-Paul Koch (http://quirksmode.org). 7345*/ 7346 7347var Cookie = new Class({ 7348 7349 Implements: Options, 7350 7351 options: { 7352 path: false, 7353 domain: false, 7354 duration: false, 7355 secure: false, 7356 document: document 7357 }, 7358 7359 initialize: function(key, options){ 7360 this.key = key; 7361 this.setOptions(options); 7362 }, 7363 7364 write: function(value){ 7365 value = encodeURIComponent(value); 7366 if (this.options.domain) value += '; domain=' + this.options.domain; 7367 if (this.options.path) value += '; path=' + this.options.path; 7368 if (this.options.duration){ 7369 var date = new Date(); 7370 date.setTime(date.getTime() + this.options.duration * 24 * 60 * 60 * 1000); 7371 value += '; expires=' + date.toGMTString(); 7372 } 7373 if (this.options.secure) value += '; secure'; 7374 this.options.document.cookie = this.key + '=' + value; 7375 return this; 7376 }, 7377 7378 read: function(){ 7379 var value = this.options.document.cookie.match('(?:^|;)\\s*' + this.key.escapeRegExp() + '=([^;]*)'); 7380 return (value) ? decodeURIComponent(value[1]) : null; 7381 }, 7382 7383 dispose: function(){ 7384 new Cookie(this.key, $merge(this.options, {duration: -1})).write(''); 7385 return this; 7386 } 7387 7388}); 7389 7390Cookie.write = function(key, value, options){ 7391 return new Cookie(key, options).write(value); 7392}; 7393 7394Cookie.read = function(key){ 7395 return new Cookie(key).read(); 7396}; 7397 7398Cookie.dispose = function(key, options){ 7399 return new Cookie(key, options).dispose(); 7400}; 7401 7402 7403/* 7404Script: Swiff.js 7405 Wrapper for embedding SWF movies. Supports (and fixes) External Interface Communication. 7406 7407License: 7408 MIT-style license. 7409 7410Credits: 7411 Flash detection & Internet Explorer + Flash Player 9 fix inspired by SWFObject. 7412*/ 7413 7414var Swiff = new Class({ 7415 7416 Implements: [Options], 7417 7418 options: { 7419 id: null, 7420 height: 1, 7421 width: 1, 7422 container: null, 7423 properties: {}, 7424 params: { 7425 quality: 'high', 7426 allowScriptAccess: 'always', 7427 wMode: 'transparent', 7428 swLiveConnect: true 7429 }, 7430 callBacks: {}, 7431 vars: {} 7432 }, 7433 7434 toElement: function(){ 7435 return this.object; 7436 }, 7437 7438 initialize: function(path, options){ 7439 this.instance = 'Swiff_' + $time(); 7440 7441 this.setOptions(options); 7442 options = this.options; 7443 var id = this.id = options.id || this.instance; 7444 var container = $(options.container); 7445 7446 Swiff.CallBacks[this.instance] = {}; 7447 7448 var params = options.params, vars = options.vars, callBacks = options.callBacks; 7449 var properties = $extend({height: options.height, width: options.width}, options.properties); 7450 7451 var self = this; 7452 7453 for (var callBack in callBacks){ 7454 Swiff.CallBacks[this.instance][callBack] = (function(option){ 7455 return function(){ 7456 return option.apply(self.object, arguments); 7457 }; 7458 })(callBacks[callBack]); 7459 vars[callBack] = 'Swiff.CallBacks.' + this.instance + '.' + callBack; 7460 } 7461 7462 params.flashVars = Hash.toQueryString(vars); 7463 if (Browser.Engine.trident){ 7464 properties.classid = 'clsid:D27CDB6E-AE6D-11cf-96B8-444553540000'; 7465 params.movie = path; 7466 } else { 7467 properties.type = 'application/x-shockwave-flash'; 7468 properties.data = path; 7469 } 7470 var build = '<object id="' + id + '"'; 7471 for (var property in properties) build += ' ' + property + '="' + properties[property] + '"'; 7472 build += '>'; 7473 for (var param in params){ 7474 if (params[param]) build += '<param name="' + param + '" value="' + params[param] + '" />'; 7475 } 7476 build += '</object>'; 7477 this.object = ((container) ? container.empty() : new Element('div')).set('html', build).firstChild; 7478 }, 7479 7480 replaces: function(element){ 7481 element = $(element, true); 7482 element.parentNode.replaceChild(this.toElement(), element); 7483 return this; 7484 }, 7485 7486 inject: function(element){ 7487 $(element, true).appendChild(this.toElement()); 7488 return this; 7489 }, 7490 7491 remote: function(){ 7492 return Swiff.remote.apply(Swiff, [this.toElement()].extend(arguments)); 7493 } 7494 7495}); 7496 7497Swiff.CallBacks = {}; 7498 7499Swiff.remote = function(obj, fn){ 7500 var rs = obj.CallFunction('<invoke name="' + fn + '" returntype="javascript">' + __flash__argumentsToXML(arguments, 2) + '</invoke>'); 7501 return eval(rs); 7502}; 7503 7504 7505/* 7506Script: Fx.js 7507 Contains the basic animation logic to be extended by all other Fx Classes. 7508 7509License: 7510 MIT-style license. 7511*/ 7512 7513var Fx = new Class({ 7514 7515 Implements: [Chain, Events, Options], 7516 7517 options: { 7518 /* 7519 onStart: $empty, 7520 onCancel: $empty, 7521 onComplete: $empty, 7522 */ 7523 fps: 50, 7524 unit: false, 7525 duration: 500, 7526 link: 'ignore' 7527 }, 7528 7529 initialize: function(options){ 7530 this.subject = this.subject || this; 7531 this.setOptions(options); 7532 this.options.duration = Fx.Durations[this.options.duration] || this.options.duration.toInt(); 7533 var wait = this.options.wait; 7534 if (wait === false) this.options.link = 'cancel'; 7535 }, 7536 7537 getTransition: function(){ 7538 return function(p){ 7539 return -(Math.cos(Math.PI * p) - 1) / 2; 7540 }; 7541 }, 7542 7543 step: function(){ 7544 var time = $time(); 7545 if (time < this.time + this.options.duration){ 7546 var delta = this.transition((time - this.time) / this.options.duration); 7547 this.set(this.compute(this.from, this.to, delta)); 7548 } else { 7549 this.set(this.compute(this.from, this.to, 1)); 7550 this.complete(); 7551 } 7552 }, 7553 7554 set: function(now){ 7555 return now; 7556 }, 7557 7558 compute: function(from, to, delta){ 7559 return Fx.compute(from, to, delta); 7560 }, 7561 7562 check: function(){ 7563 if (!this.timer) return true; 7564 switch (this.options.link){ 7565 case 'cancel': this.cancel(); return true; 7566 case 'chain': this.chain(this.caller.bind(this, arguments)); return false; 7567 } 7568 return false; 7569 }, 7570 7571 start: function(from, to){ 7572 if (!this.check(from, to)) return this; 7573 this.from = from; 7574 this.to = to; 7575 this.time = 0; 7576 this.transition = this.getTransition(); 7577 this.startTimer(); 7578 this.onStart(); 7579 return this; 7580 }, 7581 7582 complete: function(){ 7583 if (this.stopTimer()) this.onComplete(); 7584 return this; 7585 }, 7586 7587 cancel: function(){ 7588 if (this.stopTimer()) this.onCancel(); 7589 return this; 7590 }, 7591 7592 onStart: function(){ 7593 this.fireEvent('start', this.subject); 7594 }, 7595 7596 onComplete: function(){ 7597 this.fireEvent('complete', this.subject); 7598 if (!this.callChain()) this.fireEvent('chainComplete', this.subject); 7599 }, 7600 7601 onCancel: function(){ 7602 this.fireEvent('cancel', this.subject).clearChain(); 7603 }, 7604 7605 pause: function(){ 7606 this.stopTimer(); 7607 return this; 7608 }, 7609 7610 resume: function(){ 7611 this.startTimer(); 7612 return this; 7613 }, 7614 7615 stopTimer: function(){ 7616 if (!this.timer) return false; 7617 this.time = $time() - this.time; 7618 this.timer = $clear(this.timer); 7619 return true; 7620 }, 7621 7622 startTimer: function(){ 7623 if (this.timer) return false; 7624 this.time = $time() - this.time; 7625 this.timer = this.step.periodical(Math.round(1000 / this.options.fps), this); 7626 return true; 7627 } 7628 7629}); 7630 7631Fx.compute = function(from, to, delta){ 7632 return (to - from) * delta + from; 7633}; 7634 7635Fx.Durations = {'short': 250, 'normal': 500, 'long': 1000}; 7636 7637 7638/* 7639Script: Fx.CSS.js 7640 Contains the CSS animation logic. Used by Fx.Tween, Fx.Morph, Fx.Elements. 7641 7642License: 7643 MIT-style license. 7644*/ 7645 7646Fx.CSS = new Class({ 7647 7648 Extends: Fx, 7649 7650 //prepares the base from/to object 7651 7652 prepare: function(element, property, values){ 7653 values = $splat(values); 7654 var values1 = values[1]; 7655 if (!$chk(values1)){ 7656 values[1] = values[0]; 7657 values[0] = element.getStyle(property); 7658 } 7659 var parsed = values.map(this.parse); 7660 return {from: parsed[0], to: parsed[1]}; 7661 }, 7662 7663 //parses a value into an array 7664 7665 parse: function(value){ 7666 value = $lambda(value)(); 7667 value = (typeof value == 'string') ? value.split(' ') : $splat(value); 7668 return value.map(function(val){ 7669 val = String(val); 7670 var found = false; 7671 Fx.CSS.Parsers.each(function(parser, key){ 7672 if (found) return; 7673 var parsed = parser.parse(val); 7674 if ($chk(parsed)) found = {value: parsed, parser: parser}; 7675 }); 7676 found = found || {value: val, parser: Fx.CSS.Parsers.String}; 7677 return found; 7678 }); 7679 }, 7680 7681 //computes by a from and to prepared objects, using their parsers. 7682 7683 compute: function(from, to, delta){ 7684 var computed = []; 7685 (Math.min(from.length, to.length)).times(function(i){ 7686 computed.push({value: from[i].parser.compute(from[i].value, to[i].value, delta), parser: from[i].parser}); 7687 }); 7688 computed.$family = {name: 'fx:css:value'}; 7689 return computed; 7690 }, 7691 7692 //serves the value as settable 7693 7694 serve: function(value, unit){ 7695 if ($type(value) != 'fx:css:value') value = this.parse(value); 7696 var returned = []; 7697 value.each(function(bit){ 7698 returned = returned.concat(bit.parser.serve(bit.value, unit)); 7699 }); 7700 return returned; 7701 }, 7702 7703 //renders the change to an element 7704 7705 render: function(element, property, value, unit){ 7706 element.setStyle(property, this.serve(value, unit)); 7707 }, 7708 7709 //searches inside the page css to find the values for a selector 7710 7711 search: function(selector){ 7712 if (Fx.CSS.Cache[selector]) return Fx.CSS.Cache[selector]; 7713 var to = {}; 7714 Array.each(document.styleSheets, function(sheet, j){ 7715 var href = sheet.href; 7716 if (href && href.contains('://') && !href.contains(document.domain)) return; 7717 var rules = sheet.rules || sheet.cssRules; 7718 Array.each(rules, function(rule, i){ 7719 if (!rule.style) return; 7720 var selectorText = (rule.selectorText) ? rule.selectorText.replace(/^\w+/, function(m){ 7721 return m.toLowerCase(); 7722 }) : null; 7723 if (!selectorText || !selectorText.test('^' + selector + '$')) return; 7724 Element.Styles.each(function(value, style){ 7725 if (!rule.style[style] || Element.ShortStyles[style]) return; 7726 value = String(rule.style[style]); 7727 to[style] = (value.test(/^rgb/)) ? value.rgbToHex() : value; 7728 }); 7729 }); 7730 }); 7731 return Fx.CSS.Cache[selector] = to; 7732 } 7733 7734}); 7735 7736Fx.CSS.Cache = {}; 7737 7738Fx.CSS.Parsers = new Hash({ 7739 7740 Color: { 7741 parse: function(value){ 7742 if (value.match(/^#[0-9a-f]{3,6}$/i)) return value.hexToRgb(true); 7743 return ((value = value.match(/(\d+),\s*(\d+),\s*(\d+)/))) ? [value[1], value[2], value[3]] : false; 7744 }, 7745 compute: function(from, to, delta){ 7746 return from.map(function(value, i){ 7747 return Math.round(Fx.compute(from[i], to[i], delta)); 7748 }); 7749 }, 7750 serve: function(value){ 7751 return value.map(Number); 7752 } 7753 }, 7754 7755 Number: { 7756 parse: parseFloat, 7757 compute: Fx.compute, 7758 serve: function(value, unit){ 7759 return (unit) ? value + unit : value; 7760 } 7761 }, 7762 7763 String: { 7764 parse: $lambda(false), 7765 compute: $arguments(1), 7766 serve: $arguments(0) 7767 } 7768 7769}); 7770 7771 7772/* 7773Script: Fx.Tween.js 7774 Formerly Fx.Style, effect to transition any CSS property for an element. 7775 7776License: 7777 MIT-style license. 7778*/ 7779 7780Fx.Tween = new Class({ 7781 7782 Extends: Fx.CSS, 7783 7784 initialize: function(element, options){ 7785 this.element = this.subject = $(element); 7786 this.parent(options); 7787 }, 7788 7789 set: function(property, now){ 7790 if (arguments.length == 1){ 7791 now = property; 7792 property = this.property || this.options.property; 7793 } 7794 this.render(this.element, property, now, this.options.unit); 7795 return this; 7796 }, 7797 7798 start: function(property, from, to){ 7799 if (!this.check(property, from, to)) return this; 7800 var args = Array.flatten(arguments); 7801 this.property = this.options.property || args.shift(); 7802 var parsed = this.prepare(this.element, this.property, args); 7803 return this.parent(parsed.from, parsed.to); 7804 } 7805 7806}); 7807 7808Element.Properties.tween = { 7809 7810 set: function(options){ 7811 var tween = this.retrieve('tween'); 7812 if (tween) tween.cancel(); 7813 return this.eliminate('tween').store('tween:options', $extend({link: 'cancel'}, options)); 7814 }, 7815 7816 get: function(options){ 7817 if (options || !this.retrieve('tween')){ 7818 if (options || !this.retrieve('tween:options')) this.set('tween', options); 7819 this.store('tween', new Fx.Tween(this, this.retrieve('tween:options'))); 7820 } 7821 return this.retrieve('tween'); 7822 } 7823 7824}; 7825 7826Element.implement({ 7827 7828 tween: function(property, from, to){ 7829 this.get('tween').start(arguments); 7830 return this; 7831 }, 7832 7833 fade: function(how){ 7834 var fade = this.get('tween'), o = 'opacity', toggle; 7835 how = $pick(how, 'toggle'); 7836 switch (how){ 7837 case 'in': fade.start(o, 1); break; 7838 case 'out': fade.start(o, 0); break; 7839 case 'show': fade.set(o, 1); break; 7840 case 'hide': fade.set(o, 0); break; 7841 case 'toggle': 7842 var flag = this.retrieve('fade:flag', this.get('opacity') == 1); 7843 fade.start(o, (flag) ? 0 : 1); 7844 this.store('fade:flag', !flag); 7845 toggle = true; 7846 break; 7847 default: fade.start(o, arguments); 7848 } 7849 if (!toggle) this.eliminate('fade:flag'); 7850 return this; 7851 }, 7852 7853 highlight: function(start, end){ 7854 if (!end){ 7855 end = this.retrieve('highlight:original', this.getStyle('background-color')); 7856 end = (end == 'transparent') ? '#fff' : end; 7857 } 7858 var tween = this.get('tween'); 7859 tween.start('background-color', start || '#ffff88', end).chain(function(){ 7860 this.setStyle('background-color', this.retrieve('highlight:original')); 7861 tween.callChain(); 7862 }.bind(this)); 7863 return this; 7864 } 7865 7866}); 7867 7868 7869/* 7870Script: Fx.Morph.js 7871 Formerly Fx.Styles, effect to transition any number of CSS properties for an element using an object of rules, or CSS based selector rules. 7872 7873License: 7874 MIT-style license. 7875*/ 7876 7877Fx.Morph = new Class({ 7878 7879 Extends: Fx.CSS, 7880 7881 initialize: function(element, options){ 7882 this.element = this.subject = $(element); 7883 this.parent(options); 7884 }, 7885 7886 set: function(now){ 7887 if (typeof now == 'string') now = this.search(now); 7888 for (var p in now) this.render(this.element, p, now[p], this.options.unit); 7889 return this; 7890 }, 7891 7892 compute: function(from, to, delta){ 7893 var now = {}; 7894 for (var p in from) now[p] = this.parent(from[p], to[p], delta); 7895 return now; 7896 }, 7897 7898 start: function(properties){ 7899 if (!this.check(properties)) return this; 7900 if (typeof properties == 'string') properties = this.search(properties); 7901 var from = {}, to = {}; 7902 for (var p in properties){ 7903 var parsed = this.prepare(this.element, p, properties[p]); 7904 from[p] = parsed.from; 7905 to[p] = parsed.to; 7906 } 7907 return this.parent(from, to); 7908 } 7909 7910}); 7911 7912Element.Properties.morph = { 7913 7914 set: function(options){ 7915 var morph = this.retrieve('morph'); 7916 if (morph) morph.cancel(); 7917 return this.eliminate('morph').store('morph:options', $extend({link: 'cancel'}, options)); 7918 }, 7919 7920 get: function(options){ 7921 if (options || !this.retrieve('morph')){ 7922 if (options || !this.retrieve('morph:options')) this.set('morph', options); 7923 this.store('morph', new Fx.Morph(this, this.retrieve('morph:options'))); 7924 } 7925 return this.retrieve('morph'); 7926 } 7927 7928}; 7929 7930Element.implement({ 7931 7932 morph: function(props){ 7933 this.get('morph').start(props); 7934 return this; 7935 } 7936 7937}); 7938 7939 7940/* 7941Script: Fx.Transitions.js 7942 Contains a set of advanced transitions to be used with any of the Fx Classes. 7943 7944License: 7945 MIT-style license. 7946 7947Credits: 7948 Easing Equations by Robert Penner, <http://www.robertpenner.com/easing/>, modified and optimized to be used with MooTools. 7949*/ 7950 7951Fx.implement({ 7952 7953 getTransition: function(){ 7954 var trans = this.options.transition || Fx.Transitions.Sine.easeInOut; 7955 if (typeof trans == 'string'){ 7956 var data = trans.split(':'); 7957 trans = Fx.Transitions; 7958 trans = trans[data[0]] || trans[data[0].capitalize()]; 7959 if (data[1]) trans = trans['ease' + data[1].capitalize() + (data[2] ? data[2].capitalize() : '')]; 7960 } 7961 return trans; 7962 } 7963 7964}); 7965 7966Fx.Transition = function(transition, params){ 7967 params = $splat(params); 7968 return $extend(transition, { 7969 easeIn: function(pos){ 7970 return transition(pos, params); 7971 }, 7972 easeOut: function(pos){ 7973 return 1 - transition(1 - pos, params); 7974 }, 7975 easeInOut: function(pos){ 7976 return (pos <= 0.5) ? transition(2 * pos, params) / 2 : (2 - transition(2 * (1 - pos), params)) / 2; 7977 } 7978 }); 7979}; 7980 7981Fx.Transitions = new Hash({ 7982 7983 linear: $arguments(0) 7984 7985}); 7986 7987Fx.Transitions.extend = function(transitions){ 7988 for (var transition in transitions) Fx.Transitions[transition] = new Fx.Transition(transitions[transition]); 7989}; 7990 7991Fx.Transitions.extend({ 7992 7993 Pow: function(p, x){ 7994 return Math.pow(p, x[0] || 6); 7995 }, 7996 7997 Expo: function(p){ 7998 return Math.pow(2, 8 * (p - 1)); 7999 }, 8000 8001 Circ: function(p){ 8002 return 1 - Math.sin(Math.acos(p)); 8003 }, 8004 8005 Sine: function(p){ 8006 return 1 - Math.sin((1 - p) * Math.PI / 2); 8007 }, 8008 8009 Back: function(p, x){ 8010 x = x[0] || 1.618; 8011 return Math.pow(p, 2) * ((x + 1) * p - x); 8012 }, 8013 8014 Bounce: function(p){ 8015 var value; 8016 for (var a = 0, b = 1; 1; a += b, b /= 2){ 8017 if (p >= (7 - 4 * a) / 11){ 8018 value = b * b - Math.pow((11 - 6 * a - 11 * p) / 4, 2); 8019 break; 8020 } 8021 } 8022 return value; 8023 }, 8024 8025 Elastic: function(p, x){ 8026 return Math.pow(2, 10 * --p) * Math.cos(20 * p * Math.PI * (x[0] || 1) / 3); 8027 } 8028 8029}); 8030 8031['Quad', 'Cubic', 'Quart', 'Quint'].each(function(transition, i){ 8032 Fx.Transitions[transition] = new Fx.Transition(function(p){ 8033 return Math.pow(p, [i + 2]); 8034 }); 8035}); 8036 8037 8038/* 8039Script: Request.js 8040 Powerful all purpose Request Class. Uses XMLHTTPRequest. 8041 8042License: 8043 MIT-style license. 8044*/ 8045 8046var Request = new Class({ 8047 8048 Implements: [Chain, Events, Options], 8049 8050 options: {/* 8051 onRequest: $empty, 8052 onComplete: $empty, 8053 onCancel: $empty, 8054 onSuccess: $empty, 8055 onFailure: $empty, 8056 onException: $empty,*/ 8057 url: '', 8058 data: '', 8059 headers: { 8060 'X-Requested-With': 'XMLHttpRequest', 8061 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' 8062 }, 8063 async: true, 8064 format: false, 8065 method: 'post', 8066 link: 'ignore', 8067 isSuccess: null, 8068 emulation: true, 8069 urlEncoded: true, 8070 encoding: 'utf-8', 8071 evalScripts: false, 8072 evalResponse: false, 8073 noCache: false 8074 }, 8075 8076 initialize: function(options){ 8077 this.xhr = new Browser.Request(); 8078 this.setOptions(options); 8079 this.options.isSuccess = this.options.isSuccess || this.isSuccess; 8080 this.headers = new Hash(this.options.headers); 8081 }, 8082 8083 onStateChange: function(){ 8084 if (this.xhr.readyState != 4 || !this.running) return; 8085 this.running = false; 8086 this.status = 0; 8087 $try(function(){ 8088 this.status = this.xhr.status; 8089 }.bind(this)); 8090 if (this.options.isSuccess.call(this, this.status)){ 8091 this.response = {text: this.xhr.responseText, xml: this.xhr.responseXML}; 8092 this.success(this.response.text, this.response.xml); 8093 } else { 8094 this.response = {text: null, xml: null}; 8095 this.failure(); 8096 } 8097 this.xhr.onreadystatechange = $empty; 8098 }, 8099 8100 isSuccess: function(){ 8101 return ((this.status >= 200) && (this.status < 300)); 8102 }, 8103 8104 processScripts: function(text){ 8105 if (this.options.evalResponse || (/(ecma|java)script/).test(this.getHeader('Content-type'))) return $exec(text); 8106 return text.stripScripts(this.options.evalScripts); 8107 }, 8108 8109 success: function(text, xml){ 8110 this.onSuccess(this.processScripts(text), xml); 8111 }, 8112 8113 onSuccess: function(){ 8114 this.fireEvent('complete', arguments).fireEvent('success', arguments).callChain(); 8115 }, 8116 8117 failure: function(){ 8118 this.onFailure(); 8119 }, 8120 8121 onFailure: function(){ 8122 this.fireEvent('complete').fireEvent('failure', this.xhr); 8123 }, 8124 8125 setHeader: function(name, value){ 8126 this.headers.set(name, value); 8127 return this; 8128 }, 8129 8130 getHeader: function(name){ 8131 return $try(function(){ 8132 return this.xhr.getResponseHeader(name); 8133 }.bind(this)); 8134 }, 8135 8136 check: function(){ 8137 if (!this.running) return true; 8138 switch (this.options.link){ 8139 case 'cancel': this.cancel(); return true; 8140 case 'chain': this.chain(this.caller.bind(this, arguments)); return false; 8141 } 8142 return false; 8143 }, 8144 8145 send: function(options){ 8146 if (!this.check(options)) return this; 8147 this.running = true; 8148 8149 var type = $type(options); 8150 if (type == 'string' || type == 'element') options = {data: options}; 8151 8152 var old = this.options; 8153 options = $extend({data: old.data, url: old.url, method: old.method}, options); 8154 var data = options.data, url = options.url, method = options.method; 8155 8156 switch ($type(data)){ 8157 case 'element': data = $(data).toQueryString(); break; 8158 case 'object': case 'hash': data = Hash.toQueryString(data); 8159 } 8160 8161 if (this.options.format){ 8162 var format = 'format=' + this.options.format; 8163 data = (data) ? format + '&' + data : format; 8164 } 8165 8166 if (this.options.emulation && ['put', 'delete'].contains(method)){ 8167 var _method = '_method=' + method; 8168 data = (data) ? _method + '&' + data : _method; 8169 method = 'post'; 8170 } 8171 8172 if (this.options.urlEncoded && method == 'post'){ 8173 var encoding = (this.options.encoding) ? '; charset=' + this.options.encoding : ''; 8174 this.headers.set('Content-type', 'application/x-www-form-urlencoded' + encoding); 8175 } 8176 8177 if(this.options.noCache) { 8178 var noCache = "noCache=" + new Date().getTime(); 8179 data = (data) ? noCache + '&' + data : noCache; 8180 } 8181 8182 8183 if (data && method == 'get'){ 8184 url = url + (url.contains('?') ? '&' : '?') + data; 8185 data = null; 8186 } 8187 8188 8189 this.xhr.open(method.toUpperCase(), url, this.options.async); 8190 8191 this.xhr.onreadystatechange = this.onStateChange.bind(this); 8192 8193 this.headers.each(function(value, key){ 8194 try { 8195 this.xhr.setRequestHeader(key, value); 8196 } catch (e){ 8197 this.fireEvent('exception', [key, value]); 8198 } 8199 }, this); 8200 8201 this.fireEvent('request'); 8202 this.xhr.send(data); 8203 if (!this.options.async) this.onStateChange(); 8204 return this; 8205 }, 8206 8207 cancel: function(){ 8208 if (!this.running) return this; 8209 this.running = false; 8210 this.xhr.abort(); 8211 this.xhr.onreadystatechange = $empty; 8212 this.xhr = new Browser.Request(); 8213 this.fireEvent('cancel'); 8214 return this; 8215 } 8216 8217}); 8218 8219(function(){ 8220 8221var methods = {}; 8222['get', 'post', 'put', 'delete', 'GET', 'POST', 'PUT', 'DELETE'].each(function(method){ 8223 methods[method] = function(){ 8224 var params = Array.link(arguments, {url: String.type, data: $defined}); 8225 return this.send($extend(params, {method: method.toLowerCase()})); 8226 }; 8227}); 8228 8229Request.implement(methods); 8230 8231})(); 8232 8233/* 8234Script: Request.HTML.js 8235 Extends the basic Request Class with additional methods for interacting with HTML responses. 8236 8237License: 8238 MIT-style license. 8239*/ 8240 8241Request.HTML = new Class({ 8242 8243 Extends: Request, 8244 8245 options: { 8246 update: false, 8247 append: false, 8248 evalScripts: true, 8249 filter: false 8250 }, 8251 8252 processHTML: function(text){ 8253 var match = text.match(/<body[^>]*>([\s\S]*?)<\/body>/i); 8254 text = (match) ? match[1] : text; 8255 8256 var container = new Element('div'); 8257 8258 return $try(function(){ 8259 var root = '<root>' + text + '</root>', doc; 8260 if (Browser.Engine.trident){ 8261 doc = new ActiveXObject('Microsoft.XMLDOM'); 8262 doc.async = false; 8263 doc.loadXML(root); 8264 } else { 8265 doc = new DOMParser().parseFromString(root, 'text/xml'); 8266 } 8267 root = doc.getElementsByTagName('root')[0]; 8268 if (!root) return null; 8269 for (var i = 0, k = root.childNodes.length; i < k; i++){ 8270 var child = Element.clone(root.childNodes[i], true, true); 8271 if (child) container.grab(child); 8272 } 8273 return container; 8274 }) || container.set('html', text); 8275 }, 8276 8277 success: function(text){ 8278 var options = this.options, response = this.response; 8279 8280 response.html = text.stripScripts(function(script){ 8281 response.javascript = script; 8282 }); 8283 8284 var temp = this.processHTML(response.html); 8285 8286 response.tree = temp.childNodes; 8287 response.elements = temp.getElements('*'); 8288 8289 if (options.filter) response.tree = response.elements.filter(options.filter); 8290 if (options.update) $(options.update).empty().set('html', response.html); 8291 else if (options.append) $(options.append).adopt(temp.getChildren()); 8292 if (options.evalScripts) $exec(response.javascript); 8293 8294 this.onSuccess(response.tree, response.elements, response.html, response.javascript); 8295 } 8296 8297}); 8298 8299Element.Properties.send = { 8300 8301 set: function(options){ 8302 var send = this.retrieve('send'); 8303 if (send) send.cancel(); 8304 return this.eliminate('send').store('send:options', $extend({ 8305 data: this, link: 'cancel', method: this.get('method') || 'post', url: this.get('action') 8306 }, options)); 8307 }, 8308 8309 get: function(options){ 8310 if (options || !this.retrieve('send')){ 8311 if (options || !this.retrieve('send:options')) this.set('send', options); 8312 this.store('send', new Request(this.retrieve('send:options'))); 8313 } 8314 return this.retrieve('send'); 8315 } 8316 8317}; 8318 8319Element.Properties.load = { 8320 8321 set: function(options){ 8322 var load = this.retrieve('load'); 8323 if (load) load.cancel(); 8324 return this.eliminate('load').store('load:options', $extend({data: this, link: 'cancel', update: this, method: 'get'}, options)); 8325 }, 8326 8327 get: function(options){ 8328 if (options || ! this.retrieve('load')){ 8329 if (options || !this.retrieve('load:options')) this.set('load', options); 8330 this.store('load', new Request.HTML(this.retrieve('load:options'))); 8331 } 8332 return this.retrieve('load'); 8333 } 8334 8335}; 8336 8337Element.implement({ 8338 8339 send: function(url){ 8340 var sender = this.get('send'); 8341 sender.send({data: this, url: url || sender.options.url}); 8342 return this; 8343 }, 8344 8345 load: function(){ 8346 this.get('load').send(Array.link(arguments, {data: Object.type, url: String.type})); 8347 return this; 8348 } 8349 8350}); 8351 8352 8353/* 8354Script: Request.JSON.js 8355 Extends the basic Request Class with additional methods for sending and receiving JSON data. 8356 8357License: 8358 MIT-style license. 8359*/ 8360 8361Request.JSON = new Class({ 8362 8363 Extends: Request, 8364 8365 options: { 8366 secure: true 8367 }, 8368 8369 initialize: function(options){ 8370 this.parent(options); 8371 this.headers.extend({'Accept': 'application/json', 'X-Request': 'JSON'}); 8372 }, 8373 8374 success: function(text){ 8375 this.response.json = JSON.decode(text, this.options.secure); 8376 this.onSuccess(this.response.json, text); 8377 } 8378 8379}); 8380/* Prototype JavaScript framework, version 1.6.0.3 8381 * (c) 2005-2008 Sam Stephenson 8382 * 8383 * Prototype is freely distributable under the terms of an MIT-style license. 8384 * For details, see the Prototype web site: http://www.prototypejs.org/ 8385 * 8386 *--------------------------------------------------------------------------*/ 8387 8388var Prototype = { 8389 Version: '1.6.0.3', 8390 8391 Browser: { 8392 IE: !!(window.attachEvent && 8393 navigator.userAgent.indexOf('Opera') === -1), 8394 Opera: navigator.userAgent.indexOf('Opera') > -1, 8395 WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1, 8396 Gecko: navigator.userAgent.indexOf('Gecko') > -1 && 8397 navigator.userAgent.indexOf('KHTML') === -1, 8398 MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/) 8399 }, 8400 8401 BrowserFeatures: { 8402 XPath: !!document.evaluate, 8403 SelectorsAPI: !!document.querySelector, 8404 ElementExtensions: !!window.HTMLElement, 8405 SpecificElementExtensions: 8406 document.createElement('div')['__proto__'] && 8407 document.createElement('div')['__proto__'] !== 8408 document.createElement('form')['__proto__'] 8409 }, 8410 8411 ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>', 8412 JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/, 8413 8414 emptyFunction: function() { }, 8415 K: function(x) { return x } 8416}; 8417 8418if (Prototype.Browser.MobileSafari) 8419 Prototype.BrowserFeatures.SpecificElementExtensions = false; 8420 8421 8422/* Based on Alex Arnell's inheritance implementation. */ 8423var Class = { 8424 create: function() { 8425 var parent = null, properties = $A(arguments); 8426 if (Object.isFunction(properties[0])) 8427 parent = properties.shift(); 8428 8429 function klass() { 8430 this.initialize.apply(this, arguments); 8431 } 8432 8433 Object.extend(klass, Class.Methods); 8434 klass.superclass = parent; 8435 klass.subclasses = []; 8436 8437 if (parent) { 8438 var subclass = function() { }; 8439 subclass.prototype = parent.prototype; 8440 klass.prototype = new subclass; 8441 parent.subclasses.push(klass); 8442 } 8443 8444 for (var i = 0; i < properties.length; i++) 8445 klass.addMethods(properties[i]); 8446 8447 if (!klass.prototype.initialize) 8448 klass.prototype.initialize = Prototype.emptyFunction; 8449 8450 klass.prototype.constructor = klass; 8451 8452 return klass; 8453 } 8454}; 8455 8456Class.Methods = { 8457 addMethods: function(source) { 8458 var ancestor = this.superclass && this.superclass.prototype; 8459 var properties = Object.keys(source); 8460 8461 if (!Object.keys({ toString: true }).length) 8462 properties.push("toString", "valueOf"); 8463 8464 for (var i = 0, length = properties.length; i < length; i++) { 8465 var property = properties[i], value = source[property]; 8466 if (ancestor && Object.isFunction(value) && 8467 value.argumentNames().first() == "$super") { 8468 var method = value; 8469 value = (function(m) { 8470 return function() { return ancestor[m].apply(this, arguments) }; 8471 })(property).wrap(method); 8472 8473 value.valueOf = method.valueOf.bind(method); 8474 value.toString = method.toString.bind(method); 8475 } 8476 this.prototype[property] = value; 8477 } 8478 8479 return this; 8480 } 8481}; 8482 8483var Abstract = { }; 8484 8485Object.extend = function(destination, source) { 8486 for (var property in source) 8487 destination[property] = source[property]; 8488 return destination; 8489}; 8490 8491Object.extend(Object, { 8492 inspect: function(object) { 8493 try { 8494 if (Object.isUndefined(object)) return 'undefined'; 8495 if (object === null) return 'null'; 8496 return object.inspect ? object.inspect() : String(object); 8497 } catch (e) { 8498 if (e instanceof RangeError) return '...'; 8499 throw e; 8500 } 8501 }, 8502 8503 toJSON: function(object) { 8504 var type = typeof object; 8505 switch (type) { 8506 case 'undefined': 8507 case 'function': 8508 case 'unknown': return; 8509 case 'boolean': return object.toString(); 8510 } 8511 8512 if (object === null) return 'null'; 8513 if (object.toJSON) return object.toJSON(); 8514 if (Object.isElement(object)) return; 8515 8516 var results = []; 8517 for (var property in object) { 8518 var value = Object.toJSON(object[property]); 8519 if (!Object.isUndefined(value)) 8520 results.push(property.toJSON() + ': ' + value); 8521 } 8522 8523 return '{' + results.join(', ') + '}'; 8524 }, 8525 8526 toQueryString: function(object) { 8527 return $H(object).toQueryString(); 8528 }, 8529 8530 toHTML: function(object) { 8531 return object && object.toHTML ? object.toHTML() : String.interpret(object); 8532 }, 8533 8534 keys: function(object) { 8535 var keys = []; 8536 for (var property in object) 8537 keys.push(property); 8538 return keys; 8539 }, 8540 8541 values: function(object) { 8542 var values = []; 8543 for (var property in object) 8544 values.push(object[property]); 8545 return values; 8546 }, 8547 8548 clone: function(object) { 8549 return Object.extend({ }, object); 8550 }, 8551 8552 isElement: function(object) { 8553 return !!(object && object.nodeType == 1); 8554 }, 8555 8556 isArray: function(object) { 8557 return object != null && typeof object == "object" && 8558 'splice' in object && 'join' in object; 8559 }, 8560 8561 isHash: function(object) { 8562 return object instanceof Hash; 8563 }, 8564 8565 isFunction: function(object) { 8566 return typeof object == "function"; 8567 }, 8568 8569 isString: function(object) { 8570 return typeof object == "string"; 8571 }, 8572 8573 isNumber: function(object) { 8574 return typeof object == "number"; 8575 }, 8576 8577 isUndefined: function(object) { 8578 return typeof object == "undefined"; 8579 } 8580}); 8581 8582Object.extend(Function.prototype, { 8583 argumentNames: function() { 8584 var names = this.toString().match(/^[\s\(]*function[^(]*\(([^\)]*)\)/)[1] 8585 .replace(/\s+/g, '').split(','); 8586 return names.length == 1 && !names[0] ? [] : names; 8587 }, 8588 8589 bind: function() { 8590 if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this; 8591 var __method = this, args = $A(arguments), object = args.shift(); 8592 return function() { 8593 return __method.apply(object, args.concat($A(arguments))); 8594 } 8595 }, 8596 8597 bindAsEventListener: function() { 8598 var __method = this, args = $A(arguments), object = args.shift(); 8599 return function(event) { 8600 return __method.apply(object, [event || window.event].concat(args)); 8601 } 8602 }, 8603 8604 curry: function() { 8605 if (!arguments.length) return this; 8606 var __method = this, args = $A(arguments); 8607 return function() { 8608 return __method.apply(this, args.concat($A(arguments))); 8609 } 8610 }, 8611 8612 delay: function() { 8613 var __method = this, args = $A(arguments), timeout = args.shift() * 1000; 8614 return window.setTimeout(function() { 8615 return __method.apply(__method, args); 8616 }, timeout); 8617 }, 8618 8619 defer: function() { 8620 var args = [0.01].concat($A(arguments)); 8621 return this.delay.apply(this, args); 8622 }, 8623 8624 wrap: function(wrapper) { 8625 var __method = this; 8626 return function() { 8627 return wrapper.apply(this, [__method.bind(this)].concat($A(arguments))); 8628 } 8629 }, 8630 8631 methodize: function() { 8632 if (this._methodized) return this._methodized; 8633 var __method = this; 8634 return this._methodized = function() { 8635 return __method.apply(null, [this].concat($A(arguments))); 8636 }; 8637 } 8638}); 8639 8640Date.prototype.toJSON = function() { 8641 return '"' + this.getUTCFullYear() + '-' + 8642 (this.getUTCMonth() + 1).toPaddedString(2) + '-' + 8643 this.getUTCDate().toPaddedString(2) + 'T' + 8644 this.getUTCHours().toPaddedString(2) + ':' + 8645 this.getUTCMinutes().toPaddedString(2) + ':' + 8646 this.getUTCSeconds().toPaddedString(2) + 'Z"'; 8647}; 8648 8649var Try = { 8650 these: function() { 8651 var returnValue; 8652 8653 for (var i = 0, length = arguments.length; i < length; i++) { 8654 var lambda = arguments[i]; 8655 try { 8656 returnValue = lambda(); 8657 break; 8658 } catch (e) { } 8659 } 8660 8661 return returnValue; 8662 } 8663}; 8664 8665RegExp.prototype.match = RegExp.prototype.test; 8666 8667RegExp.escape = function(str) { 8668 return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1'); 8669}; 8670 8671/*--------------------------------------------------------------------------*/ 8672 8673var PeriodicalExecuter = Class.create({ 8674 initialize: function(callback, frequency) { 8675 this.callback = callback; 8676 this.frequency = frequency; 8677 this.currentlyExecuting = false; 8678 8679 this.registerCallback(); 8680 }, 8681 8682 registerCallback: function() { 8683 this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); 8684 }, 8685 8686 execute: function() { 8687 this.callback(this); 8688 }, 8689 8690 stop: function() { 8691 if (!this.timer) return; 8692 clearInterval(this.timer); 8693 this.timer = null; 8694 }, 8695 8696 onTimerEvent: function() { 8697 if (!this.currentlyExecuting) { 8698 try { 8699 this.currentlyExecuting = true; 8700 this.execute(); 8701 } finally { 8702 this.currentlyExecuting = false; 8703 } 8704 } 8705 } 8706}); 8707Object.extend(String, { 8708 interpret: function(value) { 8709 return value == null ? '' : String(value); 8710 }, 8711 specialChar: { 8712 '\b': '\\b', 8713 '\t': '\\t', 8714 '\n': '\\n', 8715 '\f': '\\f', 8716 '\r': '\\r', 8717 '\\': '\\\\' 8718 } 8719}); 8720 8721Object.extend(String.prototype, { 8722 gsub: function(pattern, replacement) { 8723 var result = '', source = this, match; 8724 replacement = arguments.callee.prepareReplacement(replacement); 8725 8726 while (source.length > 0) { 8727 if (match = source.match(pattern)) { 8728 result += source.slice(0, match.index); 8729 result += String.interpret(replacement(match)); 8730 source = source.slice(match.index + match[0].length); 8731 } else { 8732 result += source, source = ''; 8733 } 8734 } 8735 return result; 8736 }, 8737 8738 sub: function(pattern, replacement, count) { 8739 replacement = this.gsub.prepareReplacement(replacement); 8740 count = Object.isUndefined(count) ? 1 : count; 8741 8742 return this.gsub(pattern, function(match) { 8743 if (--count < 0) return match[0]; 8744 return replacement(match); 8745 }); 8746 }, 8747 8748 scan: function(pattern, iterator) { 8749 this.gsub(pattern, iterator); 8750 return String(this); 8751 }, 8752 8753 truncate: function(length, truncation) { 8754 length = length || 30; 8755 truncation = Object.isUndefined(truncation) ? '...' : truncation; 8756 return this.length > length ? 8757 this.slice(0, length - truncation.length) + truncation : String(this); 8758 }, 8759 8760 strip: function() { 8761 return this.replace(/^\s+/, '').replace(/\s+$/, ''); 8762 }, 8763 8764 stripTags: function() { 8765 return this.replace(/<\/?[^>]+>/gi, ''); 8766 }, 8767 8768 stripScripts: function() { 8769 return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); 8770 }, 8771 8772 extractScripts: function() { 8773 var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); 8774 var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); 8775 return (this.match(matchAll) || []).map(function(scriptTag) { 8776 return (scriptTag.match(matchOne) || ['', ''])[1]; 8777 }); 8778 }, 8779 8780 evalScripts: function() { 8781 return this.extractScripts().map(function(script) { return eval(script) }); 8782 }, 8783 8784 escapeHTML: function() { 8785 var self = arguments.callee; 8786 self.text.data = this; 8787 return self.div.innerHTML; 8788 }, 8789 8790 unescapeHTML: function() { 8791 var div = new Element('div'); 8792 div.innerHTML = this.stripTags(); 8793 return div.childNodes[0] ? (div.childNodes.length > 1 ? 8794 $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) : 8795 div.childNodes[0].nodeValue) : ''; 8796 }, 8797 8798 toQueryParams: function(separator) { 8799 var match = this.strip().match(/([^?#]*)(#.*)?$/); 8800 if (!match) return { }; 8801 8802 return match[1].split(separator || '&').inject({ }, function(hash, pair) { 8803 if ((pair = pair.split('='))[0]) { 8804 var key = decodeURIComponent(pair.shift()); 8805 var value = pair.length > 1 ? pair.join('=') : pair[0]; 8806 if (value != undefined) value = decodeURIComponent(value); 8807 8808 if (key in hash) { 8809 if (!Object.isArray(hash[key])) hash[key] = [hash[key]]; 8810 hash[key].push(value); 8811 } 8812 else hash[key] = value; 8813 } 8814 return hash; 8815 }); 8816 }, 8817 8818 toArray: function() { 8819 return this.split(''); 8820 }, 8821 8822 succ: function() { 8823 return this.slice(0, this.length - 1) + 8824 String.fromCharCode(this.charCodeAt(this.length - 1) + 1); 8825 }, 8826 8827 times: function(count) { 8828 return count < 1 ? '' : new Array(count + 1).join(this); 8829 }, 8830 8831 camelize: function() { 8832 var parts = this.split('-'), len = parts.length; 8833 if (len == 1) return parts[0]; 8834 8835 var camelized = this.charAt(0) == '-' 8836 ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1) 8837 : parts[0]; 8838 8839 for (var i = 1; i < len; i++) 8840 camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1); 8841 8842 return camelized; 8843 }, 8844 8845 capitalize: function() { 8846 return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase(); 8847 }, 8848 8849 underscore: function() { 8850 return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase(); 8851 }, 8852 8853 dasherize: function() { 8854 return this.gsub(/_/,'-'); 8855 }, 8856 8857 inspect: function(useDoubleQuotes) { 8858 var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) { 8859 var character = String.specialChar[match[0]]; 8860 return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16); 8861 }); 8862 if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"'; 8863 return "'" + escapedString.replace(/'/g, '\\\'') + "'"; 8864 }, 8865 8866 toJSON: function() { 8867 return this.inspect(true); 8868 }, 8869 8870 unfilterJSON: function(filter) { 8871 return this.sub(filter || Prototype.JSONFilter, '#{1}'); 8872 }, 8873 8874 isJSON: function() { 8875 var str = this; 8876 if (str.blank()) return false; 8877 str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''); 8878 return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str); 8879 }, 8880 8881 evalJSON: function(sanitize) { 8882 var json = this.unfilterJSON(); 8883 try { 8884 if (!sanitize || json.isJSON()) return eval('(' + json + ')'); 8885 } catch (e) { } 8886 throw new SyntaxError('Badly formed JSON string: ' + this.inspect()); 8887 }, 8888 8889 include: function(pattern) { 8890 return this.indexOf(pattern) > -1; 8891 }, 8892 8893 startsWith: function(pattern) { 8894 return this.indexOf(pattern) === 0; 8895 }, 8896 8897 endsWith: function(pattern) { 8898 var d = this.length - pattern.length; 8899 return d >= 0 && this.lastIndexOf(pattern) === d; 8900 }, 8901 8902 empty: function() { 8903 return this == ''; 8904 }, 8905 8906 blank: function() { 8907 return /^\s*$/.test(this); 8908 }, 8909 8910 interpolate: function(object, pattern) { 8911 return new Template(this, pattern).evaluate(object); 8912 } 8913}); 8914 8915if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, { 8916 escapeHTML: function() { 8917 return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); 8918 }, 8919 unescapeHTML: function() { 8920 return this.stripTags().replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); 8921 } 8922}); 8923 8924String.prototype.gsub.prepareReplacement = function(replacement) { 8925 if (Object.isFunction(replacement)) return replacement; 8926 var template = new Template(replacement); 8927 return function(match) { return template.evaluate(match) }; 8928}; 8929 8930String.prototype.parseQuery = String.prototype.toQueryParams; 8931 8932Object.extend(String.prototype.escapeHTML, { 8933 div: document.createElement('div'), 8934 text: document.createTextNode('') 8935}); 8936 8937String.prototype.escapeHTML.div.appendChild(String.prototype.escapeHTML.text); 8938 8939var Template = Class.create({ 8940 initialize: function(template, pattern) { 8941 this.template = template.toString(); 8942 this.pattern = pattern || Template.Pattern; 8943 }, 8944 8945 evaluate: function(object) { 8946 if (Object.isFunction(object.toTemplateReplacements)) 8947 object = object.toTemplateReplacements(); 8948 8949 return this.template.gsub(this.pattern, function(match) { 8950 if (object == null) return ''; 8951 8952 var before = match[1] || ''; 8953 if (before == '\\') return match[2]; 8954 8955 var ctx = object, expr = match[3]; 8956 var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/; 8957 match = pattern.exec(expr); 8958 if (match == null) return before; 8959 8960 while (match != null) { 8961 var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1]; 8962 ctx = ctx[comp]; 8963 if (null == ctx || '' == match[3]) break; 8964 expr = expr.substring('[' == match[3] ? match[1].length : match[0].length); 8965 match = pattern.exec(expr); 8966 } 8967 8968 return before + String.interpret(ctx); 8969 }); 8970 } 8971}); 8972Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; 8973 8974var $break = { }; 8975 8976var Enumerable = { 8977 each: function(iterator, context) { 8978 var index = 0; 8979 try { 8980 this._each(function(value) { 8981 iterator.call(context, value, index++); 8982 }); 8983 } catch (e) { 8984 if (e != $break) throw e; 8985 } 8986 return this; 8987 }, 8988 8989 eachSlice: function(number, iterator, context) { 8990 var index = -number, slices = [], array = this.toArray(); 8991 if (number < 1) return array; 8992 while ((index += number) < array.length) 8993 slices.push(array.slice(index, index+number)); 8994 return slices.collect(iterator, context); 8995 }, 8996 8997 all: function(iterator, context) { 8998 iterator = iterator || Prototype.K; 8999 var result = true; 9000 this.each(function(value, index) { 9001 result = result && !!iterator.call(context, value, index); 9002 if (!result) throw $break; 9003 }); 9004 return result; 9005 }, 9006 9007 any: function(iterator, context) { 9008 iterator = iterator || Prototype.K; 9009 var result = false; 9010 this.each(function(value, index) { 9011 if (result = !!iterator.call(context, value, index)) 9012 throw $break; 9013 }); 9014 return result; 9015 }, 9016 9017 collect: function(iterator, context) { 9018 iterator = iterator || Prototype.K; 9019 var results = []; 9020 this.each(function(value, index) { 9021 results.push(iterator.call(context, value, index)); 9022 }); 9023 return results; 9024 }, 9025 9026 detect: function(iterator, context) { 9027 var result; 9028 this.each(function(value, index) { 9029 if (iterator.call(context, value, index)) { 9030 result = value; 9031 throw $break; 9032 } 9033 }); 9034 return result; 9035 }, 9036 9037 findAll: function(iterator, context) { 9038 var results = []; 9039 this.each(function(value, index) { 9040 if (iterator.call(context, value, index)) 9041 results.push(value); 9042 }); 9043 return results; 9044 }, 9045 9046 grep: function(filter, iterator, context) { 9047 iterator = iterator || Prototype.K; 9048 var results = []; 9049 9050 if (Object.isString(filter)) 9051 filter = new RegExp(filter); 9052 9053 this.each(function(value, index) { 9054 if (filter.match(value)) 9055 results.push(iterator.call(context, value, index)); 9056 }); 9057 return results; 9058 }, 9059 9060 include: function(object) { 9061 if (Object.isFunction(this.indexOf)) 9062 if (this.indexOf(object) != -1) return true; 9063 9064 var found = false; 9065 this.each(function(value) { 9066 if (value == object) { 9067 found = true; 9068 throw $break; 9069 } 9070 }); 9071 return found; 9072 }, 9073 9074 inGroupsOf: function(number, fillWith) { 9075 fillWith = Object.isUndefined(fillWith) ? null : fillWith; 9076 return this.eachSlice(number, function(slice) { 9077 while(slice.length < number) slice.push(fillWith); 9078 return slice; 9079 }); 9080 }, 9081 9082 inject: function(memo, iterator, context) { 9083 this.each(function(value, index) { 9084 memo = iterator.call(context, memo, value, index); 9085 }); 9086 return memo; 9087 }, 9088 9089 invoke: function(method) { 9090 var args = $A(arguments).slice(1); 9091 return this.map(function(value) { 9092 return value[method].apply(value, args); 9093 }); 9094 }, 9095 9096 max: function(iterator, context) { 9097 iterator = iterator || Prototype.K; 9098 var result; 9099 this.each(function(value, index) { 9100 value = iterator.call(context, value, index); 9101 if (result == null || value >= result) 9102 result = value; 9103 }); 9104 return result; 9105 }, 9106 9107 min: function(iterator, context) { 9108 iterator = iterator || Prototype.K; 9109 var result; 9110 this.each(function(value, index) { 9111 value = iterator.call(context, value, index); 9112 if (result == null || value < result) 9113 result = value; 9114 }); 9115 return result; 9116 }, 9117 9118 partition: function(iterator, context) { 9119 iterator = iterator || Prototype.K; 9120 var trues = [], falses = []; 9121 this.each(function(value, index) { 9122 (iterator.call(context, value, index) ? 9123 trues : falses).push(value); 9124 }); 9125 return [trues, falses]; 9126 }, 9127 9128 pluck: function(property) { 9129 var results = []; 9130 this.each(function(value) { 9131 results.push(value[property]); 9132 }); 9133 return results; 9134 }, 9135 9136 reject: function(iterator, context) { 9137 var results = []; 9138 this.each(function(value, index) { 9139 if (!iterator.call(context, value, index)) 9140 results.push(value); 9141 }); 9142 return results; 9143 }, 9144 9145 sortBy: function(iterator, context) { 9146 return this.map(function(value, index) { 9147 return { 9148 value: value, 9149 criteria: iterator.call(context, value, index) 9150 }; 9151 }).sort(function(left, right) { 9152 var a = left.criteria, b = right.criteria; 9153 return a < b ? -1 : a > b ? 1 : 0; 9154 }).pluck('value'); 9155 }, 9156 9157 toArray: function() { 9158 return this.map(); 9159 }, 9160 9161 zip: function() { 9162 var iterator = Prototype.K, args = $A(arguments); 9163 if (Object.isFunction(args.last())) 9164 iterator = args.pop(); 9165 9166 var collections = [this].concat(args).map($A); 9167 return this.map(function(value, index) { 9168 return iterator(collections.pluck(index)); 9169 }); 9170 }, 9171 9172 size: function() { 9173 return this.toArray().length; 9174 }, 9175 9176 inspect: function() { 9177 return '#<Enumerable:' + this.toArray().inspect() + '>'; 9178 } 9179}; 9180 9181Object.extend(Enumerable, { 9182 map: Enumerable.collect, 9183 find: Enumerable.detect, 9184 select: Enumerable.findAll, 9185 filter: Enumerable.findAll, 9186 member: Enumerable.include, 9187 entries: Enumerable.toArray, 9188 every: Enumerable.all, 9189 some: Enumerable.any 9190}); 9191function $A(iterable) { 9192 if (!iterable) return []; 9193 if (iterable.toArray) return iterable.toArray(); 9194 var length = iterable.length || 0, results = new Array(length); 9195 while (length--) results[length] = iterable[length]; 9196 return results; 9197} 9198 9199if (Prototype.Browser.WebKit) { 9200 $A = function(iterable) { 9201 if (!iterable) return []; 9202 // In Safari, only use the `toArray` method if it's not a NodeList. 9203 // A NodeList is a function, has an function `item` property, and a numeric 9204 // `length` property. Adapted from Google Doctype. 9205 if (!(typeof iterable === 'function' && typeof iterable.length === 9206 'number' && typeof iterable.item === 'function') && iterable.toArray) 9207 return iterable.toArray(); 9208 var length = iterable.length || 0, results = new Array(length); 9209 while (length--) results[length] = iterable[length]; 9210 return results; 9211 }; 9212} 9213 9214Array.from = $A; 9215 9216Object.extend(Array.prototype, Enumerable); 9217 9218if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse; 9219 9220Object.extend(Array.prototype, { 9221 _each: function(iterator) { 9222 for (var i = 0, length = this.length; i < length; i++) 9223 iterator(this[i]); 9224 }, 9225 9226 clear: function() { 9227 this.length = 0; 9228 return this; 9229 }, 9230 9231 first: function() { 9232 return this[0]; 9233 }, 9234 9235 last: function() { 9236 return this[this.length - 1]; 9237 }, 9238 9239 compact: function() { 9240 return this.select(function(value) { 9241 return value != null; 9242 }); 9243 }, 9244 9245 flatten: function() { 9246 return this.inject([], function(array, value) { 9247 return array.concat(Object.isArray(value) ? 9248 value.flatten() : [value]); 9249 }); 9250 }, 9251 9252 without: function() { 9253 var values = $A(arguments); 9254 return this.select(function(value) { 9255 return !values.include(value); 9256 }); 9257 }, 9258 9259 reverse: function(inline) { 9260 return (inline !== false ? this : this.toArray())._reverse(); 9261 }, 9262 9263 reduce: function() { 9264 return this.length > 1 ? this : this[0]; 9265 }, 9266 9267 uniq: function(sorted) { 9268 return this.inject([], function(array, value, index) { 9269 if (0 == index || (sorted ? array.last() != value : !array.include(value))) 9270 array.push(value); 9271 return array; 9272 }); 9273 }, 9274 9275 intersect: function(array) { 9276 return this.uniq().findAll(function(item) { 9277 return array.detect(function(value) { return item === value }); 9278 }); 9279 }, 9280 9281 clone: function() { 9282 return [].concat(this); 9283 }, 9284 9285 size: function() { 9286 return this.length; 9287 }, 9288 9289 inspect: function() { 9290 return '[' + this.map(Object.inspect).join(', ') + ']'; 9291 }, 9292 9293 toJSON: function() { 9294 var results = []; 9295 this.each(function(object) { 9296 var value = Object.toJSON(object); 9297 if (!Object.isUndefined(value)) results.push(value); 9298 }); 9299 return '[' + results.join(', ') + ']'; 9300 } 9301}); 9302 9303// use native browser JS 1.6 implementation if available 9304if (Object.isFunction(Array.prototype.forEach)) 9305 Array.prototype._each = Array.prototype.forEach; 9306 9307if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) { 9308 i || (i = 0); 9309 var length = this.length; 9310 if (i < 0) i = length + i; 9311 for (; i < length; i++) 9312 if (this[i] === item) return i; 9313 return -1; 9314}; 9315 9316if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) { 9317 i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1; 9318 var n = this.slice(0, i).reverse().indexOf(item); 9319 return (n < 0) ? n : i - n - 1; 9320}; 9321 9322Array.prototype.toArray = Array.prototype.clone; 9323 9324function $w(string) { 9325 if (!Object.isString(string)) return []; 9326 string = string.strip(); 9327 return string ? string.split(/\s+/) : []; 9328} 9329 9330if (Prototype.Browser.Opera){ 9331 Array.prototype.concat = function() { 9332 var array = []; 9333 for (var i = 0, length = this.length; i < length; i++) array.push(this[i]); 9334 for (var i = 0, length = arguments.length; i < length; i++) { 9335 if (Object.isArray(arguments[i])) { 9336 for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++) 9337 array.push(arguments[i][j]); 9338 } else { 9339 array.push(arguments[i]); 9340 } 9341 } 9342 return array; 9343 }; 9344} 9345Object.extend(Number.prototype, { 9346 toColorPart: function() { 9347 return this.toPaddedString(2, 16); 9348 }, 9349 9350 succ: function() { 9351 return this + 1; 9352 }, 9353 9354 times: function(iterator, context) { 9355 $R(0, this, true).each(iterator, context); 9356 return this; 9357 }, 9358 9359 toPaddedString: function(length, radix) { 9360 var string = this.toString(radix || 10); 9361 return '0'.times(length - string.length) + string; 9362 }, 9363 9364 toJSON: function() { 9365 return isFinite(this) ? this.toString() : 'null'; 9366 } 9367}); 9368 9369$w('abs round ceil floor').each(function(method){ 9370 Number.prototype[method] = Math[method].methodize(); 9371}); 9372function $H(object) { 9373 return new Hash(object); 9374}; 9375 9376var Hash = Class.create(Enumerable, (function() { 9377 9378 function toQueryPair(key, value) { 9379 if (Object.isUndefined(value)) return key; 9380 return key + '=' + encodeURIComponent(String.interpret(value)); 9381 } 9382 9383 return { 9384 initialize: function(object) { 9385 this._object = Object.isHash(object) ? object.toObject() : Object.clone(object); 9386 }, 9387 9388 _each: function(iterator) { 9389 for (var key in this._object) { 9390 var value = this._object[key], pair = [key, value]; 9391 pair.key = key; 9392 pair.value = value; 9393 iterator(pair); 9394 } 9395 }, 9396 9397 set: function(key, value) { 9398 return this._object[key] = value; 9399 }, 9400 9401 get: function(key) { 9402 // simulating poorly supported hasOwnProperty 9403 if (this._object[key] !== Object.prototype[key]) 9404 return this._object[key]; 9405 }, 9406 9407 unset: function(key) { 9408 var value = this._object[key]; 9409 delete this._object[key]; 9410 return value; 9411 }, 9412 9413 toObject: function() { 9414 return Object.clone(this._object); 9415 }, 9416 9417 keys: function() { 9418 return this.pluck('key'); 9419 }, 9420 9421 values: function() { 9422 return this.pluck('value'); 9423 }, 9424 9425 index: function(value) { 9426 var match = this.detect(function(pair) { 9427 return pair.value === value; 9428 }); 9429 return match && match.key; 9430 }, 9431 9432 merge: function(object) { 9433 return this.clone().update(object); 9434 }, 9435 9436 update: function(object) { 9437 return new Hash(object).inject(this, function(result, pair) { 9438 result.set(pair.key, pair.value); 9439 return result; 9440 }); 9441 }, 9442 9443 toQueryString: function() { 9444 return this.inject([], function(results, pair) { 9445 var key = encodeURIComponent(pair.key), values = pair.value; 9446 9447 if (values && typeof values == 'object') { 9448 if (Object.isArray(values)) 9449 return results.concat(values.map(toQueryPair.curry(key))); 9450 } else results.push(toQueryPair(key, values)); 9451 return results; 9452 }).join('&'); 9453 }, 9454 9455 inspect: function() { 9456 return '#<Hash:{' + this.map(function(pair) { 9457 return pair.map(Object.inspect).join(': '); 9458 }).join(', ') + '}>'; 9459 }, 9460 9461 toJSON: function() { 9462 return Object.toJSON(this.toObject()); 9463 }, 9464 9465 clone: function() { 9466 return new Hash(this); 9467 } 9468 } 9469})()); 9470 9471Hash.prototype.toTemplateReplacements = Hash.prototype.toObject; 9472Hash.from = $H; 9473var ObjectRange = Class.create(Enumerable, { 9474 initialize: function(start, end, exclusive) { 9475 this.start = start; 9476 this.end = end; 9477 this.exclusive = exclusive; 9478 }, 9479 9480 _each: function(iterator) { 9481 var value = this.start; 9482 while (this.include(value)) { 9483 iterator(value); 9484 value = value.succ(); 9485 } 9486 }, 9487 9488 include: function(value) { 9489 if (value < this.start) 9490 return false; 9491 if (this.exclusive) 9492 return value < this.end; 9493 return value <= this.end; 9494 } 9495}); 9496 9497var $R = function(start, end, exclusive) { 9498 return new ObjectRange(start, end, exclusive); 9499}; 9500 9501var Ajax = { 9502 getTransport: function() { 9503 return Try.these( 9504 function() {return new XMLHttpRequest()}, 9505 function() {return new ActiveXObject('Msxml2.XMLHTTP')}, 9506 function() {return new ActiveXObject('Microsoft.XMLHTTP')} 9507 ) || false; 9508 }, 9509 9510 activeRequestCount: 0 9511}; 9512 9513Ajax.Responders = { 9514 responders: [], 9515 9516 _each: function(iterator) { 9517 this.responders._each(iterator); 9518 }, 9519 9520 register: function(responder) { 9521 if (!this.include(responder)) 9522 this.responders.push(responder); 9523 }, 9524 9525 unregister: function(responder) { 9526 this.responders = this.responders.without(responder); 9527 }, 9528 9529 dispatch: function(callback, request, transport, json) { 9530 this.each(function(responder) { 9531 if (Object.isFunction(responder[callback])) { 9532 try { 9533 responder[callback].apply(responder, [request, transport, json]); 9534 } catch (e) { } 9535 } 9536 }); 9537 } 9538}; 9539 9540Object.extend(Ajax.Responders, Enumerable); 9541 9542Ajax.Responders.register({ 9543 onCreate: function() { Ajax.activeRequestCount++ }, 9544 onComplete: function() { Ajax.activeRequestCount-- } 9545}); 9546 9547Ajax.Base = Class.create({ 9548 initialize: function(options) { 9549 this.options = { 9550 method: 'post', 9551 asynchronous: true, 9552 contentType: 'application/x-www-form-urlencoded', 9553 encoding: 'UTF-8', 9554 parameters: '', 9555 evalJSON: true, 9556 evalJS: true 9557 }; 9558 Object.extend(this.options, options || { }); 9559 9560 this.options.method = this.options.method.toLowerCase(); 9561 9562 if (Object.isString(this.options.parameters)) 9563 this.options.parameters = this.options.parameters.toQueryParams(); 9564 else if (Object.isHash(this.options.parameters)) 9565 this.options.parameters = this.options.parameters.toObject(); 9566 } 9567}); 9568 9569Ajax.Request = Class.create(Ajax.Base, { 9570 _complete: false, 9571 9572 initialize: function($super, url, options) { 9573 $super(options); 9574 this.transport = Ajax.getTransport(); 9575 this.request(url); 9576 }, 9577 9578 request: function(url) { 9579 this.url = url; 9580 this.method = this.options.method; 9581 var params = Object.clone(this.options.parameters); 9582 9583 if (!['get', 'post'].include(this.method)) { 9584 // simulate other verbs over post 9585 params['_method'] = this.method; 9586 this.method = 'post'; 9587 } 9588 9589 this.parameters = params; 9590 9591 if (params = Object.toQueryString(params)) { 9592 // when GET, append parameters to URL 9593 if (this.method == 'get') 9594 this.url += (this.url.include('?') ? '&' : '?') + params; 9595 else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) 9596 params += '&_='; 9597 } 9598 9599 try { 9600 var response = new Ajax.Response(this); 9601 if (this.options.onCreate) this.options.onCreate(response); 9602 Ajax.Responders.dispatch('onCreate', this, response); 9603 9604 this.transport.open(this.method.toUpperCase(), this.url, 9605 this.options.asynchronous); 9606 9607 if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1); 9608 9609 this.transport.onreadystatechange = this.onStateChange.bind(this); 9610 this.setRequestHeaders(); 9611 9612 this.body = this.method == 'post' ? (this.options.postBody || params) : null; 9613 this.transport.send(this.body); 9614 9615 /* Force Firefox to handle ready state 4 for synchronous requests */ 9616 if (!this.options.asynchronous && this.transport.overrideMimeType) 9617 this.onStateChange(); 9618 9619 } 9620 catch (e) { 9621 this.dispatchException(e); 9622 } 9623 }, 9624 9625 onStateChange: function() { 9626 var readyState = this.transport.readyState; 9627 if (readyState > 1 && !((readyState == 4) && this._complete)) 9628 this.respondToReadyState(this.transport.readyState); 9629 }, 9630 9631 setRequestHeaders: function() { 9632 var headers = { 9633 'X-Requested-With': 'XMLHttpRequest', 9634 'X-Prototype-Version': Prototype.Version, 9635 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' 9636 }; 9637 9638 if (this.method == 'post') { 9639 headers['Content-type'] = this.options.contentType + 9640 (this.options.encoding ? '; charset=' + this.options.encoding : ''); 9641 9642 /* Force "Connection: close" for older Mozilla browsers to work 9643 * around a bug where XMLHttpRequest sends an incorrect 9644 * Content-length header. See Mozilla Bugzilla #246651. 9645 */ 9646 if (this.transport.overrideMimeType && 9647 (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005) 9648 headers['Connection'] = 'close'; 9649 } 9650 9651 // user-defined headers 9652 if (typeof this.options.requestHeaders == 'object') { 9653 var extras = this.options.requestHeaders; 9654 9655 if (Object.isFunction(extras.push)) 9656 for (var i = 0, length = extras.length; i < length; i += 2) 9657 headers[extras[i]] = extras[i+1]; 9658 else 9659 $H(extras).each(function(pair) { headers[pair.key] = pair.value }); 9660 } 9661 9662 for (var name in headers) 9663 this.transport.setRequestHeader(name, headers[name]); 9664 }, 9665 9666 success: function() { 9667 var status = this.getStatus(); 9668 return !status || (status >= 200 && status < 300); 9669 }, 9670 9671 getStatus: function() { 9672 try { 9673 return this.transport.status || 0; 9674 } catch (e) { return 0 } 9675 }, 9676 9677 respondToReadyState: function(readyState) { 9678 var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this); 9679 9680 if (state == 'Complete') { 9681 try { 9682 this._complete = true; 9683 (this.options['on' + response.status] 9684 || this.options['on' + (this.success() ? 'Success' : 'Failure')] 9685 || Prototype.emptyFunction)(response, response.headerJSON); 9686 } catch (e) { 9687 this.dispatchException(e); 9688 } 9689 9690 var contentType = response.getHeader('Content-type'); 9691 if (this.options.evalJS == 'force' 9692 || (this.options.evalJS && this.isSameOrigin() && contentType 9693 && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i))) 9694 this.evalResponse(); 9695 } 9696 9697 try { 9698 (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON); 9699 Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON); 9700 } catch (e) { 9701 this.dispatchException(e); 9702 } 9703 9704 if (state == 'Complete') { 9705 // avoid memory leak in MSIE: clean up 9706 this.transport.onreadystatechange = Prototype.emptyFunction; 9707 } 9708 }, 9709 9710 isSameOrigin: function() { 9711 var m = this.url.match(/^\s*https?:\/\/[^\/]*/); 9712 return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({ 9713 protocol: location.protocol, 9714 domain: document.domain, 9715 port: location.port ? ':' + location.port : '' 9716 })); 9717 }, 9718 9719 getHeader: function(name) { 9720 try { 9721 return this.transport.getResponseHeader(name) || null; 9722 } catch (e) { return null } 9723 }, 9724 9725 evalResponse: function() { 9726 try { 9727 return eval((this.transport.responseText || '').unfilterJSON()); 9728 } catch (e) { 9729 this.dispatchException(e); 9730 } 9731 }, 9732 9733 dispatchException: function(exception) { 9734 (this.options.onException || Prototype.emptyFunction)(this, exception); 9735 Ajax.Responders.dispatch('onException', this, exception); 9736 } 9737}); 9738 9739Ajax.Request.Events = 9740 ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; 9741 9742Ajax.Response = Class.create({ 9743 initialize: function(request){ 9744 this.request = request; 9745 var transport = this.transport = request.transport, 9746 readyState = this.readyState = transport.readyState; 9747 9748 if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) { 9749 this.status = this.getStatus(); 9750 this.statusText = this.getStatusText(); 9751 this.responseText = String.interpret(transport.responseText); 9752 this.headerJSON = this._getHeaderJSON(); 9753 } 9754 9755 if(readyState == 4) { 9756 var xml = transport.responseXML; 9757 this.responseXML = Object.isUndefined(xml) ? null : xml; 9758 this.responseJSON = this._getResponseJSON(); 9759 } 9760 }, 9761 9762 status: 0, 9763 statusText: '', 9764 9765 getStatus: Ajax.Request.prototype.getStatus, 9766 9767 getStatusText: function() { 9768 try { 9769 return this.transport.statusText || ''; 9770 } catch (e) { return '' } 9771 }, 9772 9773 getHeader: Ajax.Request.prototype.getHeader, 9774 9775 getAllHeaders: function() { 9776 try { 9777 return this.getAllResponseHeaders(); 9778 } catch (e) { return null } 9779 }, 9780 9781 getResponseHeader: function(name) { 9782 return this.transport.getResponseHeader(name); 9783 }, 9784 9785 getAllResponseHeaders: function() { 9786 return this.transport.getAllResponseHeaders(); 9787 }, 9788 9789 _getHeaderJSON: function() { 9790 var json = this.getHeader('X-JSON'); 9791 if (!json) return null; 9792 json = decodeURIComponent(escape(json)); 9793 try { 9794 return json.evalJSON(this.request.options.sanitizeJSON || 9795 !this.request.isSameOrigin()); 9796 } catch (e) { 9797 this.request.dispatchException(e); 9798 } 9799 }, 9800 9801 _getResponseJSON: function() { 9802 var options = this.request.options; 9803 if (!options.evalJSON || (options.evalJSON != 'force' && 9804 !(this.getHeader('Content-type') || '').include('application/json')) || 9805 this.responseText.blank()) 9806 return null; 9807 try { 9808 return this.responseText.evalJSON(options.sanitizeJSON || 9809 !this.request.isSameOrigin()); 9810 } catch (e) { 9811 this.request.dispatchException(e); 9812 } 9813 } 9814}); 9815 9816Ajax.Updater = Class.create(Ajax.Request, { 9817 initialize: function($super, container, url, options) { 9818 this.container = { 9819 success: (container.success || container), 9820 failure: (container.failure || (container.success ? null : container)) 9821 }; 9822 9823 options = Object.clone(options); 9824 var onComplete = options.onComplete; 9825 options.onComplete = (function(response, json) { 9826 this.updateContent(response.responseText); 9827 if (Object.isFunction(onComplete)) onComplete(response, json); 9828 }).bind(this); 9829 9830 $super(url, options); 9831 }, 9832 9833 updateContent: function(responseText) { 9834 var receiver = this.container[this.success() ? 'success' : 'failure'], 9835 options = this.options; 9836 9837 if (!options.evalScripts) responseText = responseText.stripScripts(); 9838 9839 if (receiver = $(receiver)) { 9840 if (options.insertion) { 9841 if (Object.isString(options.insertion)) { 9842 var insertion = { }; insertion[options.insertion] = responseText; 9843 receiver.insert(insertion); 9844 } 9845 else options.insertion(receiver, responseText); 9846 } 9847 else receiver.update(responseText); 9848 } 9849 } 9850}); 9851 9852Ajax.PeriodicalUpdater = Class.create(Ajax.Base, { 9853 initialize: function($super, container, url, options) { 9854 $super(options); 9855 this.onComplete = this.options.onComplete; 9856 9857 this.frequency = (this.options.frequency || 2); 9858 this.decay = (this.options.decay || 1); 9859 9860 this.updater = { }; 9861 this.container = container; 9862 this.url = url; 9863 9864 this.start(); 9865 }, 9866 9867 start: function() { 9868 this.options.onComplete = this.updateComplete.bind(this); 9869 this.onTimerEvent(); 9870 }, 9871 9872 stop: function() { 9873 this.updater.options.onComplete = undefined; 9874 clearTimeout(this.timer); 9875 (this.onComplete || Prototype.emptyFunction).apply(this, arguments); 9876 }, 9877 9878 updateComplete: function(response) { 9879 if (this.options.decay) { 9880 this.decay = (response.responseText == this.lastText ? 9881 this.decay * this.options.decay : 1); 9882 9883 this.lastText = response.responseText; 9884 } 9885 this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency); 9886 }, 9887 9888 onTimerEvent: function() { 9889 this.updater = new Ajax.Updater(this.container, this.url, this.options); 9890 } 9891}); 9892function $(element) { 9893 if (arguments.length > 1) { 9894 for (var i = 0, elements = [], length = arguments.length; i < length; i++) 9895 elements.push($(arguments[i])); 9896 return elements; 9897 } 9898 if (Object.isString(element)) 9899 element = document.getElementById(element); 9900 return Element.extend(element); 9901} 9902 9903if (Prototype.BrowserFeatures.XPath) { 9904 document._getElementsByXPath = function(expression, parentElement) { 9905 var results = []; 9906 var query = document.evaluate(expression, $(parentElement) || document, 9907 null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); 9908 for (var i = 0, length = query.snapshotLength; i < length; i++) 9909 results.push(Element.extend(query.snapshotItem(i))); 9910 return results; 9911 }; 9912} 9913 9914/*--------------------------------------------------------------------------*/ 9915 9916if (!window.Node) var Node = { }; 9917 9918if (!Node.ELEMENT_NODE) { 9919 // DOM level 2 ECMAScript Language Binding 9920 Object.extend(Node, { 9921 ELEMENT_NODE: 1, 9922 ATTRIBUTE_NODE: 2, 9923 TEXT_NODE: 3, 9924 CDATA_SECTION_NODE: 4, 9925 ENTITY_REFERENCE_NODE: 5, 9926 ENTITY_NODE: 6, 9927 PROCESSING_INSTRUCTION_NODE: 7, 9928 COMMENT_NODE: 8, 9929 DOCUMENT_NODE: 9, 9930 DOCUMENT_TYPE_NODE: 10, 9931 DOCUMENT_FRAGMENT_NODE: 11, 9932 NOTATION_NODE: 12 9933 }); 9934} 9935 9936(function() { 9937 var element = this.Element; 9938 this.Element = function(tagName, attributes) { 9939 attributes = attributes || { }; 9940 tagName = tagName.toLowerCase(); 9941 var cache = Element.cache; 9942 if (Prototype.Browser.IE && attributes.name) { 9943 tagName = '<' + tagName + ' name="' + attributes.name + '">'; 9944 delete attributes.name; 9945 return Element.writeAttribute(document.createElement(tagName), attributes); 9946 } 9947 if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName)); 9948 return Element.writeAttribute(cache[tagName].cloneNode(false), attributes); 9949 }; 9950 Object.extend(this.Element, element || { }); 9951 if (element) this.Element.prototype = element.prototype; 9952}).call(window); 9953 9954Element.cache = { }; 9955 9956Element.Methods = { 9957 visible: function(element) { 9958 return $(element).style.display != 'none'; 9959 }, 9960 9961 toggle: function(element) { 9962 element = $(element); 9963 Element[Element.visible(element) ? 'hide' : 'show'](element); 9964 return element; 9965 }, 9966 9967 hide: function(element) { 9968 element = $(element); 9969 element.style.display = 'none'; 9970 return element; 9971 }, 9972 9973 show: function(element) { 9974 element = $(element); 9975 element.style.display = ''; 9976 return element; 9977 }, 9978 9979 remove: function(element) { 9980 element = $(element); 9981 element.parentNode.removeChild(element); 9982 return element; 9983 }, 9984 9985 update: function(element, content) { 9986 element = $(element); 9987 if (content && content.toElement) content = content.toElement(); 9988 if (Object.isElement(content)) return element.update().insert(content); 9989 content = Object.toHTML(content); 9990 element.innerHTML = content.stripScripts(); 9991 content.evalScripts.bind(content).defer(); 9992 return element; 9993 }, 9994 9995 replace: function(element, content) { 9996 element = $(element); 9997 if (content && content.toElement) content = content.toElement(); 9998 else if (!Object.isElement(content)) { 9999 content = Object.toHTML(content); 10000 var range = element.ownerDocument.createRange(); 10001 range.selectNode(element); 10002 content.evalScripts.bind(content).defer(); 10003 content = range.createContextualFragment(content.stripScripts()); 10004 } 10005 element.parentNode.replaceChild(content, element); 10006 return element; 10007 }, 10008 10009 insert: function(element, insertions) { 10010 element = $(element); 10011 10012 if (Object.isString(insertions) || Object.isNumber(insertions) || 10013 Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML))) 10014 insertions = {bottom:insertions}; 10015 10016 var content, insert, tagName, childNodes; 10017 10018 for (var position in insertions) { 10019 content = insertions[position]; 10020 position = position.toLowerCase(); 10021 insert = Element._insertionTranslations[position]; 10022 10023 if (content && content.toElement) content = content.toElement(); 10024 if (Object.isElement(content)) { 10025 insert(element, content); 10026 continue; 10027 } 10028 10029 content = Object.toHTML(content); 10030 10031 tagName = ((position == 'before' || position == 'after') 10032 ? element.parentNode : element).tagName.toUpperCase(); 10033 10034 childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); 10035 10036 if (position == 'top' || position == 'after') childNodes.reverse(); 10037 childNodes.each(insert.curry(element)); 10038 10039 content.evalScripts.bind(content).defer(); 10040 } 10041 10042 return element; 10043 }, 10044 10045 wrap: function(element, wrapper, attributes) { 10046 element = $(element); 10047 if (Object.isElement(wrapper)) 10048 $(wrapper).writeAttribute(attributes || { }); 10049 else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes); 10050 else wrapper = new Element('div', wrapper); 10051 if (element.parentNode) 10052 element.parentNode.replaceChild(wrapper, element); 10053 wrapper.appendChild(element); 10054 return wrapper; 10055 }, 10056 10057 inspect: function(element) { 10058 element = $(element); 10059 var result = '<' + element.tagName.toLowerCase(); 10060 $H({'id': 'id', 'className': 'class'}).each(function(pair) { 10061 var property = pair.first(), attribute = pair.last(); 10062 var value = (element[property] || '').toString(); 10063 if (value) result += ' ' + attribute + '=' + value.inspect(true); 10064 }); 10065 return result + '>'; 10066 }, 10067 10068 recursivelyCollect: function(element, property) { 10069 element = $(element); 10070 var elements = []; 10071 while (element = element[property]) 10072 if (element.nodeType == 1) 10073 elements.push(Element.extend(element)); 10074 return elements; 10075 }, 10076 10077 ancestors: function(element) { 10078 return $(element).recursivelyCollect('parentNode'); 10079 }, 10080 10081 descendants: function(element) { 10082 return $(element).select("*"); 10083 }, 10084 10085 firstDescendant: function(element) { 10086 element = $(element).firstChild; 10087 while (element && element.nodeType != 1) element = element.nextSibling; 10088 return $(element); 10089 }, 10090 10091 immediateDescendants: function(element) { 10092 if (!(element = $(element).firstChild)) return []; 10093 while (element && element.nodeType != 1) element = element.nextSibling; 10094 if (element) return [element].concat($(element).nextSiblings()); 10095 return []; 10096 }, 10097 10098 previousSiblings: function(element) { 10099 return $(element).recursivelyCollect('previousSibling'); 10100 }, 10101 10102 nextSiblings: function(element) { 10103 return $(element).recursivelyCollect('nextSibling'); 10104 }, 10105 10106 siblings: function(element) { 10107 element = $(element); 10108 return element.previousSiblings().reverse().concat(element.nextSiblings()); 10109 }, 10110 10111 match: function(element, selector) { 10112 if (Object.isString(selector)) 10113 selector = new Selector(selector); 10114 return selector.match($(element)); 10115 }, 10116 10117 up: function(element, expression, index) { 10118 element = $(element); 10119 if (arguments.length == 1) return $(element.parentNode); 10120 var ancestors = element.ancestors(); 10121 return Object.isNumber(expression) ? ancestors[expression] : 10122 Selector.findElement(ancestors, expression, index); 10123 }, 10124 10125 down: function(element, expression, index) { 10126 element = $(element); 10127 if (arguments.length == 1) return element.firstDescendant(); 10128 return Object.isNumber(expression) ? element.descendants()[expression] : 10129 Element.select(element, expression)[index || 0]; 10130 }, 10131 10132 previous: function(element, expression, index) { 10133 element = $(element); 10134 if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element)); 10135 var previousSiblings = element.previousSiblings(); 10136 return Object.isNumber(expression) ? previousSiblings[expression] : 10137 Selector.findElement(previousSiblings, expression, index); 10138 }, 10139 10140 next: function(element, expression, index) { 10141 element = $(element); 10142 if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element)); 10143 var nextSiblings = element.nextSiblings(); 10144 return Object.isNumber(expression) ? nextSiblings[expression] : 10145 Selector.findElement(nextSiblings, expression, index); 10146 }, 10147 10148 select: function() { 10149 var args = $A(arguments), element = $(args.shift()); 10150 return Selector.findChildElements(element, args); 10151 }, 10152 10153 adjacent: function() { 10154 var args = $A(arguments), element = $(args.shift()); 10155 return Selector.findChildElements(element.parentNode, args).without(element); 10156 }, 10157 10158 identify: function(element) { 10159 element = $(element); 10160 var id = element.readAttribute('id'), self = arguments.callee; 10161 if (id) return id; 10162 do { id = 'anonymous_element_' + self.counter++ } while ($(id)); 10163 element.writeAttribute('id', id); 10164 return id; 10165 }, 10166 10167 readAttribute: function(element, name) { 10168 element = $(element); 10169 if (Prototype.Browser.IE) { 10170 var t = Element._attributeTranslations.read; 10171 if (t.values[name]) return t.values[name](element, name); 10172 if (t.names[name]) name = t.names[name]; 10173 if (name.include(':')) { 10174 return (!element.attributes || !element.attributes[name]) ? null : 10175 element.attributes[name].value; 10176 } 10177 } 10178 return element.getAttribute(name); 10179 }, 10180 10181 writeAttribute: function(element, name, value) { 10182 element = $(element); 10183 var attributes = { }, t = Element._attributeTranslations.write; 10184 10185 if (typeof name == 'object') attributes = name; 10186 else attributes[name] = Object.isUndefined(value) ? true : value; 10187 10188 for (var attr in attributes) { 10189 name = t.names[attr] || attr; 10190 value = attributes[attr]; 10191 if (t.values[attr]) name = t.values[attr](element, value); 10192 if (value === false || value === null) 10193 element.removeAttribute(name); 10194 else if (value === true) 10195 element.setAttribute(name, name); 10196 else element.setAttribute(name, value); 10197 } 10198 return element; 10199 }, 10200 10201 getHeight: function(element) { 10202 return $(element).getDimensions().height; 10203 }, 10204 10205 getWidth: function(element) { 10206 return $(element).getDimensions().width; 10207 }, 10208 10209 classNames: function(element) { 10210 return new Element.ClassNames(element); 10211 }, 10212 10213 hasClassName: function(element, className) { 10214 if (!(element = $(element))) return; 10215 var elementClassName = element.className; 10216 return (elementClassName.length > 0 && (elementClassName == className || 10217 new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName))); 10218 }, 10219 10220 addClassName: function(element, className) { 10221 if (!(element = $(element))) return; 10222 if (!element.hasClassName(className)) 10223 element.className += (element.className ? ' ' : '') + className; 10224 return element; 10225 }, 10226 10227 removeClassName: function(element, className) { 10228 if (!(element = $(element))) return; 10229 element.className = element.className.replace( 10230 new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip(); 10231 return element; 10232 }, 10233 10234 toggleClassName: function(element, className) { 10235 if (!(element = $(element))) return; 10236 return element[element.hasClassName(className) ? 10237 'removeClassName' : 'addClassName'](className); 10238 }, 10239 10240 // removes whitespace-only text node children 10241 cleanWhitespace: function(element) { 10242 element = $(element); 10243 var node = element.firstChild; 10244 while (node) { 10245 var nextNode = node.nextSibling; 10246 if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) 10247 element.removeChild(node); 10248 node = nextNode; 10249 } 10250 return element; 10251 }, 10252 10253 empty: function(element) { 10254 return $(element).innerHTML.blank(); 10255 }, 10256 10257 descendantOf: function(element, ancestor) { 10258 element = $(element), ancestor = $(ancestor); 10259 10260 if (element.compareDocumentPosition) 10261 return (element.compareDocumentPosition(ancestor) & 8) === 8; 10262 10263 if (ancestor.contains) 10264 return ancestor.contains(element) && ancestor !== element; 10265 10266 while (element = element.parentNode) 10267 if (element == ancestor) return true; 10268 10269 return false; 10270 }, 10271 10272 scrollTo: function(element) { 10273 element = $(element); 10274 var pos = element.cumulativeOffset(); 10275 window.scrollTo(pos[0], pos[1]); 10276 return element; 10277 }, 10278 10279 getStyle: function(element, style) { 10280 element = $(element); 10281 style = style == 'float' ? 'cssFloat' : style.camelize(); 10282 var value = element.style[style]; 10283 if (!value || value == 'auto') { 10284 var css = document.defaultView.getComputedStyle(element, null); 10285 value = css ? css[style] : null; 10286 } 10287 if (style == 'opacity') return value ? parseFloat(value) : 1.0; 10288 return value == 'auto' ? null : value; 10289 }, 10290 10291 getOpacity: function(element) { 10292 return $(element).getStyle('opacity'); 10293 }, 10294 10295 setStyle: function(element, styles) { 10296 element = $(element); 10297 var elementStyle = element.style, match; 10298 if (Object.isString(styles)) { 10299 element.style.cssText += ';' + styles; 10300 return styles.include('opacity') ? 10301 element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element; 10302 } 10303 for (var property in styles) 10304 if (property == 'opacity') element.setOpacity(styles[property]); 10305 else 10306 elementStyle[(property == 'float' || property == 'cssFloat') ? 10307 (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') : 10308 property] = styles[property]; 10309 10310 return element; 10311 }, 10312 10313 setOpacity: function(element, value) { 10314 element = $(element); 10315 element.style.opacity = (value == 1 || value === '') ? '' : 10316 (value < 0.00001) ? 0 : value; 10317 return element; 10318 }, 10319 10320 getDimensions: function(element) { 10321 element = $(element); 10322 var display = element.getStyle('display'); 10323 if (display != 'none' && display != null) // Safari bug 10324 return {width: element.offsetWidth, height: element.offsetHeight}; 10325 10326 // All *Width and *Height properties give 0 on elements with display none, 10327 // so enable the element temporarily 10328 var els = element.style; 10329 var originalVisibility = els.visibility; 10330 var originalPosition = els.position; 10331 var originalDisplay = els.display; 10332 els.visibility = 'hidden'; 10333 els.position = 'absolute'; 10334 els.display = 'block'; 10335 var originalWidth = element.clientWidth; 10336 var originalHeight = element.clientHeight; 10337 els.display = originalDisplay; 10338 els.position = originalPosition; 10339 els.visibility = originalVisibility; 10340 return {width: originalWidth, height: originalHeight}; 10341 }, 10342 10343 makePositioned: function(element) { 10344 element = $(element); 10345 var pos = Element.getStyle(element, 'position'); 10346 if (pos == 'static' || !pos) { 10347 element._madePositioned = true; 10348 element.style.position = 'relative'; 10349 // Opera returns the offset relative to the positioning context, when an 10350 // element is position relative but top and left have not been defined 10351 if (Prototype.Browser.Opera) { 10352 element.style.top = 0; 10353 element.style.left = 0; 10354 } 10355 } 10356 return element; 10357 }, 10358 10359 undoPositioned: function(element) { 10360 element = $(element); 10361 if (element._madePositioned) { 10362 element._madePositioned = undefined; 10363 element.style.position = 10364 element.style.top = 10365 element.style.left = 10366 element.style.bottom = 10367 element.style.right = ''; 10368 } 10369 return element; 10370 }, 10371 10372 makeClipping: function(element) { 10373 element = $(element); 10374 if (element._overflow) return element; 10375 element._overflow = Element.getStyle(element, 'overflow') || 'auto'; 10376 if (element._overflow !== 'hidden') 10377 element.style.overflow = 'hidden'; 10378 return element; 10379 }, 10380 10381 undoClipping: function(element) { 10382 element = $(element); 10383 if (!element._overflow) return element; 10384 element.style.overflow = element._overflow == 'auto' ? '' : element._overflow; 10385 element._overflow = null; 10386 return element; 10387 }, 10388 10389 cumulativeOffset: function(element) { 10390 var valueT = 0, valueL = 0; 10391 do { 10392 valueT += element.offsetTop || 0; 10393 valueL += element.offsetLeft || 0; 10394 element = element.offsetParent; 10395 } while (element); 10396 return Element._returnOffset(valueL, valueT); 10397 }, 10398 10399 positionedOffset: function(element) { 10400 var valueT = 0, valueL = 0; 10401 do { 10402 valueT += element.offsetTop || 0; 10403 valueL += element.offsetLeft || 0; 10404 element = element.offsetParent; 10405 if (element) { 10406 if (element.tagName.toUpperCase() == 'BODY') break; 10407 var p = Element.getStyle(element, 'position'); 10408 if (p !== 'static') break; 10409 } 10410 } while (element); 10411 return Element._returnOffset(valueL, valueT); 10412 }, 10413 10414 absolutize: function(element) { 10415 element = $(element); 10416 if (element.getStyle('position') == 'absolute') return element; 10417 // Position.prepare(); // To be done manually by Scripty when it needs it. 10418 10419 var offsets = element.positionedOffset(); 10420 var top = offsets[1]; 10421 var left = offsets[0]; 10422 var width = element.clientWidth; 10423 var height = element.clientHeight; 10424 10425 element._originalLeft = left - parseFloat(element.style.left || 0); 10426 element._originalTop = top - parseFloat(element.style.top || 0); 10427 element._originalWidth = element.style.width; 10428 element._originalHeight = element.style.height; 10429 10430 element.style.position = 'absolute'; 10431 element.style.top = top + 'px'; 10432 element.style.left = left + 'px'; 10433 element.style.width = width + 'px'; 10434 element.style.height = height + 'px'; 10435 return element; 10436 }, 10437 10438 relativize: function(element) { 10439 element = $(element); 10440 if (element.getStyle('position') == 'relative') return element; 10441 // Position.prepare(); // To be done manually by Scripty when it needs it. 10442 10443 element.style.position = 'relative'; 10444 var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); 10445 var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); 10446 10447 element.style.top = top + 'px'; 10448 element.style.left = left + 'px'; 10449 element.style.height = element._originalHeight; 10450 element.style.width = element._originalWidth; 10451 return element; 10452 }, 10453 10454 cumulativeScrollOffset: function(element) { 10455 var valueT = 0, valueL = 0; 10456 do { 10457 valueT += element.scrollTop || 0; 10458 valueL += element.scrollLeft || 0; 10459 element = element.parentNode; 10460 } while (element); 10461 return Element._returnOffset(valueL, valueT); 10462 }, 10463 10464 getOffsetParent: function(element) { 10465 if (element.offsetParent) return $(element.offsetParent); 10466 if (element == document.body) return $(element); 10467 10468 while ((element = element.parentNode) && element != document.body) 10469 if (Element.getStyle(element, 'position') != 'static') 10470 return $(element); 10471 10472 return $(document.body); 10473 }, 10474 10475 viewportOffset: function(forElement) { 10476 var valueT = 0, valueL = 0; 10477 10478 var element = forElement; 10479 do { 10480 valueT += element.offsetTop || 0; 10481 valueL += element.offsetLeft || 0; 10482 10483 // Safari fix 10484 if (element.offsetParent == document.body && 10485 Element.getStyle(element, 'position') == 'absolute') break; 10486 10487 } while (element = element.offsetParent); 10488 10489 element = forElement; 10490 do { 10491 if (!Prototype.Browser.Opera || (element.tagName && (element.tagName.toUpperCase() == 'BODY'))) { 10492 valueT -= element.scrollTop || 0; 10493 valueL -= element.scrollLeft || 0; 10494 } 10495 } while (element = element.parentNode); 10496 10497 return Element._returnOffset(valueL, valueT); 10498 }, 10499 10500 clonePosition: function(element, source) { 10501 var options = Object.extend({ 10502 setLeft: true, 10503 setTop: true, 10504 setWidth: true, 10505 setHeight: true, 10506 offsetTop: 0, 10507 offsetLeft: 0 10508 }, arguments[2] || { }); 10509 10510 // find page position of source 10511 source = $(source); 10512 var p = source.viewportOffset(); 10513 10514 // find coordinate system to use 10515 element = $(element); 10516 var delta = [0, 0]; 10517 var parent = null; 10518 // delta [0,0] will do fine with position: fixed elements, 10519 // position:absolute needs offsetParent deltas 10520 if (Element.getStyle(element, 'position') == 'absolute') { 10521 parent = element.getOffsetParent(); 10522 delta = parent.viewportOffset(); 10523 } 10524 10525 // correct by body offsets (fixes Safari) 10526 if (parent == document.body) { 10527 delta[0] -= document.body.offsetLeft; 10528 delta[1] -= document.body.offsetTop; 10529 } 10530 10531 // set position 10532 if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; 10533 if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; 10534 if (options.setWidth) element.style.width = source.offsetWidth + 'px'; 10535 if (options.setHeight) element.style.height = source.offsetHeight + 'px'; 10536 return element; 10537 } 10538}; 10539 10540Element.Methods.identify.counter = 1; 10541 10542Object.extend(Element.Methods, { 10543 getElementsBySelector: Element.Methods.select, 10544 childElements: Element.Methods.immediateDescendants 10545}); 10546 10547Element._attributeTranslations = { 10548 write: { 10549 names: { 10550 className: 'class', 10551 htmlFor: 'for' 10552 }, 10553 values: { } 10554 } 10555}; 10556 10557if (Prototype.Browser.Opera) { 10558 Element.Methods.getStyle = Element.Methods.getStyle.wrap( 10559 function(proceed, element, style) { 10560 switch (style) { 10561 case 'left': case 'top': case 'right': case 'bottom': 10562 if (proceed(element, 'position') === 'static') return null; 10563 case 'height': case 'width': 10564 // returns '0px' for hidden elements; we want it to return null 10565 if (!Element.visible(element)) return null; 10566 10567 // returns the border-box dimensions rather than the content-box 10568 // dimensions, so we subtract padding and borders from the value 10569 var dim = parseInt(proceed(element, style), 10); 10570 10571 if (dim !== element['offset' + style.capitalize()]) 10572 return dim + 'px'; 10573 10574 var properties; 10575 if (style === 'height') { 10576 properties = ['border-top-width', 'padding-top', 10577 'padding-bottom', 'border-bottom-width']; 10578 } 10579 else { 10580 properties = ['border-left-width', 'padding-left', 10581 'padding-right', 'border-right-width']; 10582 } 10583 return properties.inject(dim, function(memo, property) { 10584 var val = proceed(element, property); 10585 return val === null ? memo : memo - parseInt(val, 10); 10586 }) + 'px'; 10587 default: return proceed(element, style); 10588 } 10589 } 10590 ); 10591 10592 Element.Methods.readAttribute = Element.Methods.readAttribute.wrap( 10593 function(proceed, element, attribute) { 10594 if (attribute === 'title') return element.title; 10595 return proceed(element, attribute); 10596 } 10597 ); 10598} 10599 10600else if (Prototype.Browser.IE) { 10601 // IE doesn't report offsets correctly for static elements, so we change them 10602 // to "relative" to get the values, then change them back. 10603 Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap( 10604 function(proceed, element) { 10605 element = $(element); 10606 // IE throws an error if element is not in document 10607 try { element.offsetParent } 10608 catch(e) { return $(document.body) } 10609 var position = element.getStyle('position'); 10610 if (position !== 'static') return proceed(element); 10611 element.setStyle({ position: 'relative' }); 10612 var value = proceed(element); 10613 element.setStyle({ position: position }); 10614 return value; 10615 } 10616 ); 10617 10618 $w('positionedOffset viewportOffset').each(function(method) { 10619 Element.Methods[method] = Element.Methods[method].wrap( 10620 function(proceed, element) { 10621 element = $(element); 10622 try { element.offsetParent } 10623 catch(e) { return Element._returnOffset(0,0) } 10624 var position = element.getStyle('position'); 10625 if (position !== 'static') return proceed(element); 10626 // Trigger hasLayout on the offset parent so that IE6 reports 10627 // accurate offsetTop and offsetLeft values for position: fixed. 10628 var offsetParent = element.getOffsetParent(); 10629 if (offsetParent && offsetParent.getStyle('position') === 'fixed') 10630 offsetParent.setStyle({ zoom: 1 }); 10631 element.setStyle({ position: 'relative' }); 10632 var value = proceed(element); 10633 element.setStyle({ position: position }); 10634 return value; 10635 } 10636 ); 10637 }); 10638 10639 Element.Methods.cumulativeOffset = Element.Methods.cumulativeOffset.wrap( 10640 function(proceed, element) { 10641 try { element.offsetParent } 10642 catch(e) { return Element._returnOffset(0,0) } 10643 return proceed(element); 10644 } 10645 ); 10646 10647 Element.Methods.getStyle = function(element, style) { 10648 element = $(element); 10649 style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize(); 10650 var value = element.style[style]; 10651 if (!value && element.currentStyle) value = element.currentStyle[style]; 10652 10653 if (style == 'opacity') { 10654 if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/)) 10655 if (value[1]) return parseFloat(value[1]) / 100; 10656 return 1.0; 10657 } 10658 10659 if (value == 'auto') { 10660 if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none')) 10661 return element['offset' + style.capitalize()] + 'px'; 10662 return null; 10663 } 10664 return value; 10665 }; 10666 10667 Element.Methods.setOpacity = function(element, value) { 10668 function stripAlpha(filter){ 10669 return filter.replace(/alpha\([^\)]*\)/gi,''); 10670 } 10671 element = $(element); 10672 var currentStyle = element.currentStyle; 10673 if ((currentStyle && !currentStyle.hasLayout) || 10674 (!currentStyle && element.style.zoom == 'normal')) 10675 element.style.zoom = 1; 10676 10677 var filter = element.getStyle('filter'), style = element.style; 10678 if (value == 1 || value === '') { 10679 (filter = stripAlpha(filter)) ? 10680 style.filter = filter : style.removeAttribute('filter'); 10681 return element; 10682 } else if (value < 0.00001) value = 0; 10683 style.filter = stripAlpha(filter) + 10684 'alpha(opacity=' + (value * 100) + ')'; 10685 return element; 10686 }; 10687 10688 Element._attributeTranslations = { 10689 read: { 10690 names: { 10691 'class': 'className', 10692 'for': 'htmlFor' 10693 }, 10694 values: { 10695 _getAttr: function(element, attribute) { 10696 return element.getAttribute(attribute, 2); 10697 }, 10698 _getAttrNode: function(element, attribute) { 10699 var node = element.getAttributeNode(attribute); 10700 return node ? node.value : ""; 10701 }, 10702 _getEv: function(element, attribute) { 10703 attribute = element.getAttribute(attribute); 10704 return attribute ? attribute.toString().slice(23, -2) : null; 10705 }, 10706 _flag: function(element, attribute) { 10707 return $(element).hasAttribute(attribute) ? attribute : null; 10708 }, 10709 style: function(element) { 10710 return element.style.cssText.toLowerCase(); 10711 }, 10712 title: function(element) { 10713 return element.title; 10714 } 10715 } 10716 } 10717 }; 10718 10719 Element._attributeTranslations.write = { 10720 names: Object.extend({ 10721 cellpadding: 'cellPadding', 10722 cellspacing: 'cellSpacing' 10723 }, Element._attributeTranslations.read.names), 10724 values: { 10725 checked: function(element, value) { 10726 element.checked = !!value; 10727 }, 10728 10729 style: function(element, value) { 10730 element.style.cssText = value ? value : ''; 10731 } 10732 } 10733 }; 10734 10735 Element._attributeTranslations.has = {}; 10736 10737 $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' + 10738 'encType maxLength readOnly longDesc frameBorder').each(function(attr) { 10739 Element._attributeTranslations.write.names[attr.toLowerCase()] = attr; 10740 Element._attributeTranslations.has[attr.toLowerCase()] = attr; 10741 }); 10742 10743 (function(v) { 10744 Object.extend(v, { 10745 href: v._getAttr, 10746 src: v._getAttr, 10747 type: v._getAttr, 10748 action: v._getAttrNode, 10749 disabled: v._flag, 10750 checked: v._flag, 10751 readonly: v._flag, 10752 multiple: v._flag, 10753 onload: v._getEv, 10754 onunload: v._getEv, 10755 onclick: v._getEv, 10756 ondblclick: v._getEv, 10757 onmousedown: v._getEv, 10758 onmouseup: v._getEv, 10759 onmouseover: v._getEv, 10760 onmousemove: v._getEv, 10761 onmouseout: v._getEv, 10762 onfocus: v._getEv, 10763 onblur: v._getEv, 10764 onkeypress: v._getEv, 10765 onkeydown: v._getEv, 10766 onkeyup: v._getEv, 10767 onsubmit: v._getEv, 10768 onreset: v._getEv, 10769 onselect: v._getEv, 10770 onchange: v._getEv 10771 }); 10772 })(Element._attributeTranslations.read.values); 10773} 10774 10775else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) { 10776 Element.Methods.setOpacity = function(element, value) { 10777 element = $(element); 10778 element.style.opacity = (value == 1) ? 0.999999 : 10779 (value === '') ? '' : (value < 0.00001) ? 0 : value; 10780 return element; 10781 }; 10782} 10783 10784else if (Prototype.Browser.WebKit) { 10785 Element.Methods.setOpacity = function(element, value) { 10786 element = $(element); 10787 element.style.opacity = (value == 1 || value === '') ? '' : 10788 (value < 0.00001) ? 0 : value; 10789 10790 if (value == 1) 10791 if(element.tagName.toUpperCase() == 'IMG' && element.width) { 10792 element.width++; element.width--; 10793 } else try { 10794 var n = document.createTextNode(' '); 10795 element.appendChild(n); 10796 element.removeChild(n); 10797 } catch (e) { } 10798 10799 return element; 10800 }; 10801 10802 // Safari returns margins on body which is incorrect if the child is absolutely 10803 // positioned. For performance reasons, redefine Element#cumulativeOffset for 10804 // KHTML/WebKit only. 10805 Element.Methods.cumulativeOffset = function(element) { 10806 var valueT = 0, valueL = 0; 10807 do { 10808 valueT += element.offsetTop || 0; 10809 valueL += element.offsetLeft || 0; 10810 if (element.offsetParent == document.body) 10811 if (Element.getStyle(element, 'position') == 'absolute') break; 10812 10813 element = element.offsetParent; 10814 } while (element); 10815 10816 return Element._returnOffset(valueL, valueT); 10817 }; 10818} 10819 10820if (Prototype.Browser.IE || Prototype.Browser.Opera) { 10821 // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements 10822 Element.Methods.update = function(element, content) { 10823 element = $(element); 10824 10825 if (content && content.toElement) content = content.toElement(); 10826 if (Object.isElement(content)) return element.update().insert(content); 10827 10828 content = Object.toHTML(content); 10829 var tagName = element.tagName.toUpperCase(); 10830 10831 if (tagName in Element._insertionTranslations.tags) { 10832 $A(element.childNodes).each(function(node) { element.removeChild(node) }); 10833 Element._getContentFromAnonymousElement(tagName, content.stripScripts()) 10834 .each(function(node) { element.appendChild(node) }); 10835 } 10836 else element.innerHTML = content.stripScripts(); 10837 10838 content.evalScripts.bind(content).defer(); 10839 return element; 10840 }; 10841} 10842 10843if ('outerHTML' in document.createElement('div')) { 10844 Element.Methods.replace = function(element, content) { 10845 element = $(element); 10846 10847 if (content && content.toElement) content = content.toElement(); 10848 if (Object.isElement(content)) { 10849 element.parentNode.replaceChild(content, element); 10850 return element; 10851 } 10852 10853 content = Object.toHTML(content); 10854 var parent = element.parentNode, tagName = parent.tagName.toUpperCase(); 10855 10856 if (Element._insertionTranslations.tags[tagName]) { 10857 var nextSibling = element.next(); 10858 var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); 10859 parent.removeChild(element); 10860 if (nextSibling) 10861 fragments.each(function(node) { parent.insertBefore(node, nextSibling) }); 10862 else 10863 fragments.each(function(node) { parent.appendChild(node) }); 10864 } 10865 else element.outerHTML = content.stripScripts(); 10866 10867 content.evalScripts.bind(content).defer(); 10868 return element; 10869 }; 10870} 10871 10872Element._returnOffset = function(l, t) { 10873 var result = [l, t]; 10874 result.left = l; 10875 result.top = t; 10876 return result; 10877}; 10878 10879Element._getContentFromAnonymousElement = function(tagName, html) { 10880 var div = new Element('div'), t = Element._insertionTranslations.tags[tagName]; 10881 if (t) { 10882 div.innerHTML = t[0] + html + t[1]; 10883 t[2].times(function() { div = div.firstChild }); 10884 } else div.innerHTML = html; 10885 return $A(div.childNodes); 10886}; 10887 10888Element._insertionTranslations = { 10889 before: function(element, node) { 10890 element.parentNode.insertBefore(node, element); 10891 }, 10892 top: function(element, node) { 10893 element.insertBefore(node, element.firstChild); 10894 }, 10895 bottom: function(element, node) { 10896 element.appendChild(node); 10897 }, 10898 after: function(element, node) { 10899 element.parentNode.insertBefore(node, element.nextSibling); 10900 }, 10901 tags: { 10902 TABLE: ['<table>', '</table>', 1], 10903 TBODY: ['<table><tbody>', '</tbody></table>', 2], 10904 TR: ['<table><tbody><tr>', '</tr></tbody></table>', 3], 10905 TD: ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4], 10906 SELECT: ['<select>', '</select>', 1] 10907 } 10908}; 10909 10910(function() { 10911 Object.extend(this.tags, { 10912 THEAD: this.tags.TBODY, 10913 TFOOT: this.tags.TBODY, 10914 TH: this.tags.TD 10915 }); 10916}).call(Element._insertionTranslations); 10917 10918Element.Methods.Simulated = { 10919 hasAttribute: function(element, attribute) { 10920 attribute = Element._attributeTranslations.has[attribute] || attribute; 10921 var node = $(element).getAttributeNode(attribute); 10922 return !!(node && node.specified); 10923 } 10924}; 10925 10926Element.Methods.ByTag = { }; 10927 10928Object.extend(Element, Element.Methods); 10929 10930if (!Prototype.BrowserFeatures.ElementExtensions && 10931 document.createElement('div')['__proto__']) { 10932 window.HTMLElement = { }; 10933 window.HTMLElement.prototype = document.createElement('div')['__proto__']; 10934 Prototype.BrowserFeatures.ElementExtensions = true; 10935} 10936 10937Element.extend = (function() { 10938 if (Prototype.BrowserFeatures.SpecificElementExtensions) 10939 return Prototype.K; 10940 10941 var Methods = { }, ByTag = Element.Methods.ByTag; 10942 10943 var extend = Object.extend(function(element) { 10944 if (!element || element._extendedByPrototype || 10945 element.nodeType != 1 || element == window) return element; 10946 10947 var methods = Object.clone(Methods), 10948 tagName = element.tagName.toUpperCase(), property, value; 10949 10950 // extend methods for specific tags 10951 if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]); 10952 10953 for (property in methods) { 10954 value = methods[property]; 10955 if (Object.isFunction(value) && !(property in element)) 10956 element[property] = value.methodize(); 10957 } 10958 10959 element._extendedByPrototype = Prototype.emptyFunction; 10960 return element; 10961 10962 }, { 10963 refresh: function() { 10964 // extend methods for all tags (Safari doesn't need this) 10965 if (!Prototype.BrowserFeatures.ElementExtensions) { 10966 Object.extend(Methods, Element.Methods); 10967 Object.extend(Methods, Element.Methods.Simulated); 10968 } 10969 } 10970 }); 10971 10972 extend.refresh(); 10973 return extend; 10974})(); 10975 10976Element.hasAttribute = function(element, attribute) { 10977 if (element.hasAttribute) return element.hasAttribute(attribute); 10978 return Element.Methods.Simulated.hasAttribute(element, attribute); 10979}; 10980 10981Element.addMethods = function(methods) { 10982 var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag; 10983 10984 if (!methods) { 10985 Object.extend(Form, Form.Methods); 10986 Object.extend(Form.Element, Form.Element.Methods); 10987 Object.extend(Element.Methods.ByTag, { 10988 "FORM": Object.clone(Form.Methods), 10989 "INPUT": Object.clone(Form.Element.Methods), 10990 "SELECT": Object.clone(Form.Element.Methods), 10991 "TEXTAREA": Object.clone(Form.Element.Methods) 10992 }); 10993 } 10994 10995 if (arguments.length == 2) { 10996 var tagName = methods; 10997 methods = arguments[1]; 10998 } 10999 11000 if (!tagName) Object.extend(Element.Methods, methods || { }); 11001 else { 11002 if (Object.isArray(tagName)) tagName.each(extend); 11003 else extend(tagName); 11004 } 11005 11006 function extend(tagName) { 11007 tagName = tagName.toUpperCase(); 11008 if (!Element.Methods.ByTag[tagName]) 11009 Element.Methods.ByTag[tagName] = { }; 11010 Object.extend(Element.Methods.ByTag[tagName], methods); 11011 } 11012 11013 function copy(methods, destination, onlyIfAbsent) { 11014 onlyIfAbsent = onlyIfAbsent || false; 11015 for (var property in methods) { 11016 var value = methods[property]; 11017 if (!Object.isFunction(value)) continue; 11018 if (!onlyIfAbsent || !(property in destination)) 11019 destination[property] = value.methodize(); 11020 } 11021 } 11022 11023 function findDOMClass(tagName) { 11024 var klass; 11025 var trans = { 11026 "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph", 11027 "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList", 11028 "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading", 11029 "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote", 11030 "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION": 11031 "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD": 11032 "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR": 11033 "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET": 11034 "FrameSet", "IFRAME": "IFrame" 11035 }; 11036 if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element'; 11037 if (window[klass]) return window[klass]; 11038 klass = 'HTML' + tagName + 'Element'; 11039 if (window[klass]) return window[klass]; 11040 klass = 'HTML' + tagName.capitalize() + 'Element'; 11041 if (window[klass]) return window[klass]; 11042 11043 window[klass] = { }; 11044 window[klass].prototype = document.createElement(tagName)['__proto__']; 11045 return window[klass]; 11046 } 11047 11048 if (F.ElementExtensions) { 11049 copy(Element.Methods, HTMLElement.prototype); 11050 copy(Element.Methods.Simulated, HTMLElement.prototype, true); 11051 } 11052 11053 if (F.SpecificElementExtensions) { 11054 for (var tag in Element.Methods.ByTag) { 11055 var klass = findDOMClass(tag); 11056 if (Object.isUndefined(klass)) continue; 11057 copy(T[tag], klass.prototype); 11058 } 11059 } 11060 11061 Object.extend(Element, Element.Methods); 11062 delete Element.ByTag; 11063 11064 if (Element.extend.refresh) Element.extend.refresh(); 11065 Element.cache = { }; 11066}; 11067 11068document.viewport = { 11069 getDimensions: function() { 11070 var dimensions = { }, B = Prototype.Browser; 11071 $w('width height').each(function(d) { 11072 var D = d.capitalize(); 11073 if (B.WebKit && !document.evaluate) { 11074 // Safari <3.0 needs self.innerWidth/Height 11075 dimensions[d] = self['inner' + D]; 11076 } else if (B.Opera && parseFloat(window.opera.version()) < 9.5) { 11077 // Opera <9.5 needs document.body.clientWidth/Height 11078 dimensions[d] = document.body['client' + D] 11079 } else { 11080 dimensions[d] = document.documentElement['client' + D]; 11081 } 11082 }); 11083 return dimensions; 11084 }, 11085 11086 getWidth: function() { 11087 return this.getDimensions().width; 11088 }, 11089 11090 getHeight: function() { 11091 return this.getDimensions().height; 11092 }, 11093 11094 getScrollOffsets: function() { 11095 return Element._returnOffset( 11096 window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft, 11097 window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop); 11098 } 11099}; 11100/* Portions of the Selector class are derived from Jack Slocum's DomQuery, 11101 * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style 11102 * license. Please see http://www.yui-ext.com/ for more information. */ 11103 11104var Selector = Class.create({ 11105 initialize: function(expression) { 11106 this.expression = expression.strip(); 11107 11108 if (this.shouldUseSelectorsAPI()) { 11109 this.mode = 'selectorsAPI'; 11110 } else if (this.shouldUseXPath()) { 11111 this.mode = 'xpath'; 11112 this.compileXPathMatcher(); 11113 } else { 11114 this.mode = "normal"; 11115 this.compileMatcher(); 11116 } 11117 11118 }, 11119 11120 shouldUseXPath: function() { 11121 if (!Prototype.BrowserFeatures.XPath) return false; 11122 11123 var e = this.expression; 11124 11125 // Safari 3 chokes on :*-of-type and :empty 11126 if (Prototype.Browser.WebKit && 11127 (e.include("-of-type") || e.include(":empty"))) 11128 return false; 11129 11130 // XPath can't do namespaced attributes, nor can it read 11131 // the "checked" property from DOM nodes 11132 if ((/(\[[\w-]*?:|:checked)/).test(e)) 11133 return false; 11134 11135 return true; 11136 }, 11137 11138 shouldUseSelectorsAPI: function() { 11139 if (!Prototype.BrowserFeatures.SelectorsAPI) return false; 11140 11141 if (!Selector._div) Selector._div = new Element('div'); 11142 11143 // Make sure the browser treats the selector as valid. Test on an 11144 // isolated element to minimize cost of this check. 11145 try { 11146 Selector._div.querySelector(this.expression); 11147 } catch(e) { 11148 return false; 11149 } 11150 11151 return true; 11152 }, 11153 11154 compileMatcher: function() { 11155 var e = this.expression, ps = Selector.patterns, h = Selector.handlers, 11156 c = Selector.criteria, le, p, m; 11157 11158 if (Selector._cache[e]) { 11159 this.matcher = Selector._cache[e]; 11160 return; 11161 } 11162 11163 this.matcher = ["this.matcher = function(root) {", 11164 "var r = root, h = Selector.handlers, c = false, n;"]; 11165 11166 while (e && le != e && (/\S/).test(e)) { 11167 le = e; 11168 for (var i in ps) { 11169 p = ps[i]; 11170 if (m = e.match(p)) { 11171 this.matcher.push(Object.isFunction(c[i]) ? c[i](m) : 11172 new Template(c[i]).evaluate(m)); 11173 e = e.replace(m[0], ''); 11174 break; 11175 } 11176 } 11177 } 11178 11179 this.matcher.push("return h.unique(n);\n}"); 11180 eval(this.matcher.join('\n')); 11181 Selector._cache[this.expression] = this.matcher; 11182 }, 11183 11184 compileXPathMatcher: function() { 11185 var e = this.expression, ps = Selector.patterns, 11186 x = Selector.xpath, le, m; 11187 11188 if (Selector._cache[e]) { 11189 this.xpath = Selector._cache[e]; return; 11190 } 11191 11192 this.matcher = ['.//*']; 11193 while (e && le != e && (/\S/).test(e)) { 11194 le = e; 11195 for (var i in ps) { 11196 if (m = e.match(ps[i])) { 11197 this.matcher.push(Object.isFunction(x[i]) ? x[i](m) : 11198 new Template(x[i]).evaluate(m)); 11199 e = e.replace(m[0], ''); 11200 break; 11201 } 11202 } 11203 } 11204 11205 this.xpath = this.matcher.join(''); 11206 Selector._cache[this.expression] = this.xpath; 11207 }, 11208 11209 findElements: function(root) { 11210 root = root || document; 11211 var e = this.expression, results; 11212 11213 switch (this.mode) { 11214 case 'selectorsAPI': 11215 // querySelectorAll queries document-wide, then filters to descendants 11216 // of the context element. That's not what we want. 11217 // Add an explicit context to the selector if necessary. 11218 if (root !== document) { 11219 var oldId = root.id, id = $(root).identify(); 11220 e = "#" + id + " " + e; 11221 } 11222 11223 results = $A(root.querySelectorAll(e)).map(Element.extend); 11224 root.id = oldId; 11225 11226 return results; 11227 case 'xpath': 11228 return document._getElementsByXPath(this.xpath, root); 11229 default: 11230 return this.matcher(root); 11231 } 11232 }, 11233 11234 match: function(element) { 11235 this.tokens = []; 11236 11237 var e = this.expression, ps = Selector.patterns, as = Selector.assertions; 11238 var le, p, m; 11239 11240 while (e && le !== e && (/\S/).test(e)) { 11241 le = e; 11242 for (var i in ps) { 11243 p = ps[i]; 11244 if (m = e.match(p)) { 11245 // use the Selector.assertions methods unless the selector 11246 // is too complex. 11247 if (as[i]) { 11248 this.tokens.push([i, Object.clone(m)]); 11249 e = e.replace(m[0], ''); 11250 } else { 11251 // reluctantly do a document-wide search 11252 // and look for a match in the array 11253 return this.findElements(document).include(element); 11254 } 11255 } 11256 } 11257 } 11258 11259 var match = true, name, matches; 11260 for (var i = 0, token; token = this.tokens[i]; i++) { 11261 name = token[0], matches = token[1]; 11262 if (!Selector.assertions[name](element, matches)) { 11263 match = false; break; 11264 } 11265 } 11266 11267 return match; 11268 }, 11269 11270 toString: function() { 11271 return this.expression; 11272 }, 11273 11274 inspect: function() { 11275 return "#<Selector:" + this.expression.inspect() + ">"; 11276 } 11277}); 11278 11279Object.extend(Selector, { 11280 _cache: { }, 11281 11282 xpath: { 11283 descendant: "//*", 11284 child: "/*", 11285 adjacent: "/following-sibling::*[1]", 11286 laterSibling: '/following-sibling::*', 11287 tagName: function(m) { 11288 if (m[1] == '*') return ''; 11289 return "[local-name()='" + m[1].toLowerCase() + 11290 "' or local-name()='" + m[1].toUpperCase() + "']"; 11291 }, 11292 className: "[contains(concat(' ', @class, ' '), ' #{1} ')]", 11293 id: "[@id='#{1}']", 11294 attrPresence: function(m) { 11295 m[1] = m[1].toLowerCase(); 11296 return new Template("[@#{1}]").evaluate(m); 11297 }, 11298 attr: function(m) { 11299 m[1] = m[1].toLowerCase(); 11300 m[3] = m[5] || m[6]; 11301 return new Template(Selector.xpath.operators[m[2]]).evaluate(m); 11302 }, 11303 pseudo: function(m) { 11304 var h = Selector.xpath.pseudos[m[1]]; 11305 if (!h) return ''; 11306 if (Object.isFunction(h)) return h(m); 11307 return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m); 11308 }, 11309 operators: { 11310 '=': "[@#{1}='#{3}']", 11311 '!=': "[@#{1}!='#{3}']", 11312 '^=': "[starts-with(@#{1}, '#{3}')]", 11313 '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']", 11314 '*=': "[contains(@#{1}, '#{3}')]", 11315 '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]", 11316 '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]" 11317 }, 11318 pseudos: { 11319 'first-child': '[not(preceding-sibling::*)]', 11320 'last-child': '[not(following-sibling::*)]', 11321 'only-child': '[not(preceding-sibling::* or following-sibling::*)]', 11322 'empty': "[count(*) = 0 and (count(text()) = 0)]", 11323 'checked': "[@checked]", 11324 'disabled': "[(@disabled) and (@type!='hidden')]", 11325 'enabled': "[not(@disabled) and (@type!='hidden')]", 11326 'not': function(m) { 11327 var e = m[6], p = Selector.patterns, 11328 x = Selector.xpath, le, v; 11329 11330 var exclusion = []; 11331 while (e && le != e && (/\S/).test(e)) { 11332 le = e; 11333 for (var i in p) { 11334 if (m = e.match(p[i])) { 11335 v = Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m); 11336 exclusion.push("(" + v.substring(1, v.length - 1) + ")"); 11337 e = e.replace(m[0], ''); 11338 break; 11339 } 11340 } 11341 } 11342 return "[not(" + exclusion.join(" and ") + ")]"; 11343 }, 11344 'nth-child': function(m) { 11345 return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m); 11346 }, 11347 'nth-last-child': function(m) { 11348 return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m); 11349 }, 11350 'nth-of-type': function(m) { 11351 return Selector.xpath.pseudos.nth("position() ", m); 11352 }, 11353 'nth-last-of-type': function(m) { 11354 return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m); 11355 }, 11356 'first-of-type': function(m) { 11357 m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m); 11358 }, 11359 'last-of-type': function(m) { 11360 m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m); 11361 }, 11362 'only-of-type': function(m) { 11363 var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m); 11364 }, 11365 nth: function(fragment, m) { 11366 var mm, formula = m[6], predicate; 11367 if (formula == 'even') formula = '2n+0'; 11368 if (formula == 'odd') formula = '2n+1'; 11369 if (mm = formula.match(/^(\d+)$/)) // digit only 11370 return '[' + fragment + "= " + mm[1] + ']'; 11371 if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b 11372 if (mm[1] == "-") mm[1] = -1; 11373 var a = mm[1] ? Number(mm[1]) : 1; 11374 var b = mm[2] ? Number(mm[2]) : 0; 11375 predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " + 11376 "((#{fragment} - #{b}) div #{a} >= 0)]"; 11377 return new Template(predicate).evaluate({ 11378 fragment: fragment, a: a, b: b }); 11379 } 11380 } 11381 } 11382 }, 11383 11384 criteria: { 11385 tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;', 11386 className: 'n = h.className(n, r, "#{1}", c); c = false;', 11387 id: 'n = h.id(n, r, "#{1}", c); c = false;', 11388 attrPresence: 'n = h.attrPresence(n, r, "#{1}", c); c = false;', 11389 attr: function(m) { 11390 m[3] = (m[5] || m[6]); 11391 return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(m); 11392 }, 11393 pseudo: function(m) { 11394 if (m[6]) m[6] = m[6].replace(/"/g, '\\"'); 11395 return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m); 11396 }, 11397 descendant: 'c = "descendant";', 11398 child: 'c = "child";', 11399 adjacent: 'c = "adjacent";', 11400 laterSibling: 'c = "laterSibling";' 11401 }, 11402 11403 patterns: { 11404 // combinators must be listed first 11405 // (and descendant needs to be last combinator) 11406 laterSibling: /^\s*~\s*/, 11407 child: /^\s*>\s*/, 11408 adjacent: /^\s*\+\s*/, 11409 descendant: /^\s/, 11410 11411 // selectors follow 11412 tagName: /^\s*(\*|[\w\-]+)(\b|$)?/, 11413 id: /^#([\w\-\*]+)(\b|$)/, 11414 className: /^\.([\w\-\*]+)(\b|$)/, 11415 pseudo: 11416/^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/, 11417 attrPresence: /^\[((?:[\w]+:)?[\w]+)\]/, 11418 attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/ 11419 }, 11420 11421 // for Selector.match and Element#match 11422 assertions: { 11423 tagName: function(element, matches) { 11424 return matches[1].toUpperCase() == element.tagName.toUpperCase(); 11425 }, 11426 11427 className: function(element, matches) { 11428 return Element.hasClassName(element, matches[1]); 11429 }, 11430 11431 id: function(element, matches) { 11432 return element.id === matches[1]; 11433 }, 11434 11435 attrPresence: function(element, matches) { 11436 return Element.hasAttribute(element, matches[1]); 11437 }, 11438 11439 attr: function(element, matches) { 11440 var nodeValue = Element.readAttribute(element, matches[1]); 11441 return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]); 11442 } 11443 }, 11444 11445 handlers: { 11446 // UTILITY FUNCTIONS 11447 // joins two collections 11448 concat: function(a, b) { 11449 for (var i = 0, node; node = b[i]; i++) 11450 a.push(node); 11451 return a; 11452 }, 11453 11454 // marks an array of nodes for counting 11455 mark: function(nodes) { 11456 var _true = Prototype.emptyFunction; 11457 for (var i = 0, node; node = nodes[i]; i++) 11458 node._countedByPrototype = _true; 11459 return nodes; 11460 }, 11461 11462 unmark: function(nodes) { 11463 for (var i = 0, node; node = nodes[i]; i++) 11464 node._countedByPrototype = undefined; 11465 return nodes; 11466 }, 11467 11468 // mark each child node with its position (for nth calls) 11469 // "ofType" flag indicates whether we're indexing for nth-of-type 11470 // rather than nth-child 11471 index: function(parentNode, reverse, ofType) { 11472 parentNode._countedByPrototype = Prototype.emptyFunction; 11473 if (reverse) { 11474 for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) { 11475 var node = nodes[i]; 11476 if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++; 11477 } 11478 } else { 11479 for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++) 11480 if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++; 11481 } 11482 }, 11483 11484 // filters out duplicates and extends all nodes 11485 unique: function(nodes) { 11486 if (nodes.length == 0) return nodes; 11487 var results = [], n; 11488 for (var i = 0, l = nodes.length; i < l; i++) 11489 if (!(n = nodes[i])._countedByPrototype) { 11490 n._countedByPrototype = Prototype.emptyFunction; 11491 results.push(Element.extend(n)); 11492 } 11493 return Selector.handlers.unmark(results); 11494 }, 11495 11496 // COMBINATOR FUNCTIONS 11497 descendant: function(nodes) { 11498 var h = Selector.handlers; 11499 for (var i = 0, results = [], node; node = nodes[i]; i++) 11500 h.concat(results, node.getElementsByTagName('*')); 11501 return results; 11502 }, 11503 11504 child: function(nodes) { 11505 var h = Selector.handlers; 11506 for (var i = 0, results = [], node; node = nodes[i]; i++) { 11507 for (var j = 0, child; child = node.childNodes[j]; j++) 11508 if (child.nodeType == 1 && child.tagName != '!') results.push(child); 11509 } 11510 return results; 11511 }, 11512 11513 adjacent: function(nodes) { 11514 for (var i = 0, results = [], node; node = nodes[i]; i++) { 11515 var next = this.nextElementSibling(node); 11516 if (next) results.push(next); 11517 } 11518 return results; 11519 }, 11520 11521 laterSibling: function(nodes) { 11522 var h = Selector.handlers; 11523 for (var i = 0, results = [], node; node = nodes[i]; i++) 11524 h.concat(results, Element.nextSiblings(node)); 11525 return results; 11526 }, 11527 11528 nextElementSibling: function(node) { 11529 while (node = node.nextSibling) 11530 if (node.nodeType == 1) return node; 11531 return null; 11532 }, 11533 11534 previousElementSibling: function(node) { 11535 while (node = node.previousSibling) 11536 if (node.nodeType == 1) return node; 11537 return null; 11538 }, 11539 11540 // TOKEN FUNCTIONS 11541 tagName: function(nodes, root, tagName, combinator) { 11542 var uTagName = tagName.toUpperCase(); 11543 var results = [], h = Selector.handlers; 11544 if (nodes) { 11545 if (combinator) { 11546 // fastlane for ordinary descendant combinators 11547 if (combinator == "descendant") { 11548 for (var i = 0, node; node = nodes[i]; i++) 11549 h.concat(results, node.getElementsByTagName(tagName)); 11550 return results; 11551 } else nodes = this[combinator](nodes); 11552 if (tagName == "*") return nodes; 11553 } 11554 for (var i = 0, node; node = nodes[i]; i++) 11555 if (node.tagName.toUpperCase() === uTagName) results.push(node); 11556 return results; 11557 } else return root.getElementsByTagName(tagName); 11558 }, 11559 11560 id: function(nodes, root, id, combinator) { 11561 var targetNode = $(id), h = Selector.handlers; 11562 if (!targetNode) return []; 11563 if (!nodes && root == document) return [targetNode]; 11564 if (nodes) { 11565 if (combinator) { 11566 if (combinator == 'child') { 11567 for (var i = 0, node; node = nodes[i]; i++) 11568 if (targetNode.parentNode == node) return [targetNode]; 11569 } else if (combinator == 'descendant') { 11570 for (var i = 0, node; node = nodes[i]; i++) 11571 if (Element.descendantOf(targetNode, node)) return [targetNode]; 11572 } else if (combinator == 'adjacent') { 11573 for (var i = 0, node; node = nodes[i]; i++) 11574 if (Selector.handlers.previousElementSibling(targetNode) == node) 11575 return [targetNode]; 11576 } else nodes = h[combinator](nodes); 11577 } 11578 for (var i = 0, node; node = nodes[i]; i++) 11579 if (node == targetNode) return [targetNode]; 11580 return []; 11581 } 11582 return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : []; 11583 }, 11584 11585 className: function(nodes, root, className, combinator) { 11586 if (nodes && combinator) nodes = this[combinator](nodes); 11587 return Selector.handlers.byClassName(nodes, root, className); 11588 }, 11589 11590 byClassName: function(nodes, root, className) { 11591 if (!nodes) nodes = Selector.handlers.descendant([root]); 11592 var needle = ' ' + className + ' '; 11593 for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) { 11594 nodeClassName = node.className; 11595 if (nodeClassName.length == 0) continue; 11596 if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle)) 11597 results.push(node); 11598 } 11599 return results; 11600 }, 11601 11602 attrPresence: function(nodes, root, attr, combinator) { 11603 if (!nodes) nodes = root.getElementsByTagName("*"); 11604 if (nodes && combinator) nodes = this[combinator](nodes); 11605 var results = []; 11606 for (var i = 0, node; node = nodes[i]; i++) 11607 if (Element.hasAttribute(node, attr)) results.push(node); 11608 return results; 11609 }, 11610 11611 attr: function(nodes, root, attr, value, operator, combinator) { 11612 if (!nodes) nodes = root.getElementsByTagName("*"); 11613 if (nodes && combinator) nodes = this[combinator](nodes); 11614 var handler = Selector.operators[operator], results = []; 11615 for (var i = 0, node; node = nodes[i]; i++) { 11616 var nodeValue = Element.readAttribute(node, attr); 11617 if (nodeValue === null) continue; 11618 if (handler(nodeValue, value)) results.push(node); 11619 } 11620 return results; 11621 }, 11622 11623 pseudo: function(nodes, name, value, root, combinator) { 11624 if (nodes && combinator) nodes = this[combinator](nodes); 11625 if (!nodes) nodes = root.getElementsByTagName("*"); 11626 return Selector.pseudos[name](nodes, value, root); 11627 } 11628 }, 11629 11630 pseudos: { 11631 'first-child': function(nodes, value, root) { 11632 for (var i = 0, results = [], node; node = nodes[i]; i++) { 11633 if (Selector.handlers.previousElementSibling(node)) continue; 11634 results.push(node); 11635 } 11636 return results; 11637 }, 11638 'last-child': function(nodes, value, root) { 11639 for (var i = 0, results = [], node; node = nodes[i]; i++) { 11640 if (Selector.handlers.nextElementSibling(node)) continue; 11641 results.push(node); 11642 } 11643 return results; 11644 }, 11645 'only-child': function(nodes, value, root) { 11646 var h = Selector.handlers; 11647 for (var i = 0, results = [], node; node = nodes[i]; i++) 11648 if (!h.previousElementSibling(node) && !h.nextElementSibling(node)) 11649 results.push(node); 11650 return results; 11651 }, 11652 'nth-child': function(nodes, formula, root) { 11653 return Selector.pseudos.nth(nodes, formula, root); 11654 }, 11655 'nth-last-child': function(nodes, formula, root) { 11656 return Selector.pseudos.nth(nodes, formula, root, true); 11657 }, 11658 'nth-of-type': function(nodes, formula, root) { 11659 return Selector.pseudos.nth(nodes, formula, root, false, true); 11660 }, 11661 'nth-last-of-type': function(nodes, formula, root) { 11662 return Selector.pseudos.nth(nodes, formula, root, true, true); 11663 }, 11664 'first-of-type': function(nodes, formula, root) { 11665 return Selector.pseudos.nth(nodes, "1", root, false, true); 11666 }, 11667 'last-of-type': function(nodes, formula, root) { 11668 return Selector.pseudos.nth(nodes, "1", root, true, true); 11669 }, 11670 'only-of-type': function(nodes, formula, root) { 11671 var p = Selector.pseudos; 11672 return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root); 11673 }, 11674 11675 // handles the an+b logic 11676 getIndices: function(a, b, total) { 11677 if (a == 0) return b > 0 ? [b] : []; 11678 return $R(1, total).inject([], function(memo, i) { 11679 if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i); 11680 return memo; 11681 }); 11682 }, 11683 11684 // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type 11685 nth: function(nodes, formula, root, reverse, ofType) { 11686 if (nodes.length == 0) return []; 11687 if (formula == 'even') formula = '2n+0'; 11688 if (formula == 'odd') formula = '2n+1'; 11689 var h = Selector.handlers, results = [], indexed = [], m; 11690 h.mark(nodes); 11691 for (var i = 0, node; node = nodes[i]; i++) { 11692 if (!node.parentNode._countedByPrototype) { 11693 h.index(node.parentNode, reverse, ofType); 11694 indexed.push(node.parentNode); 11695 } 11696 } 11697 if (formula.match(/^\d+$/)) { // just a number 11698 formula = Number(formula); 11699 for (var i = 0, node; node = nodes[i]; i++) 11700 if (node.nodeIndex == formula) results.push(node); 11701 } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b 11702 if (m[1] == "-") m[1] = -1; 11703 var a = m[1] ? Number(m[1]) : 1; 11704 var b = m[2] ? Number(m[2]) : 0; 11705 var indices = Selector.pseudos.getIndices(a, b, nodes.length); 11706 for (var i = 0, node, l = indices.length; node = nodes[i]; i++) { 11707 for (var j = 0; j < l; j++) 11708 if (node.nodeIndex == indices[j]) results.push(node); 11709 } 11710 } 11711 h.unmark(nodes); 11712 h.unmark(indexed); 11713 return results; 11714 }, 11715 11716 'empty': function(nodes, value, root) { 11717 for (var i = 0, results = [], node; node = nodes[i]; i++) { 11718 // IE treats comments as element nodes 11719 if (node.tagName == '!' || node.firstChild) continue; 11720 results.push(node); 11721 } 11722 return results; 11723 }, 11724 11725 'not': function(nodes, selector, root) { 11726 var h = Selector.handlers, selectorType, m; 11727 var exclusions = new Selector(selector).findElements(root); 11728 h.mark(exclusions); 11729 for (var i = 0, results = [], node; node = nodes[i]; i++) 11730 if (!node._countedByPrototype) results.push(node); 11731 h.unmark(exclusions); 11732 return results; 11733 }, 11734 11735 'enabled': function(nodes, value, root) { 11736 for (var i = 0, results = [], node; node = nodes[i]; i++) 11737 if (!node.disabled && (!node.type || node.type !== 'hidden')) 11738 results.push(node); 11739 return results; 11740 }, 11741 11742 'disabled': function(nodes, value, root) { 11743 for (var i = 0, results = [], node; node = nodes[i]; i++) 11744 if (node.disabled) results.push(node); 11745 return results; 11746 }, 11747 11748 'checked': function(nodes, value, root) { 11749 for (var i = 0, results = [], node; node = nodes[i]; i++) 11750 if (node.checked) results.push(node); 11751 return results; 11752 } 11753 }, 11754 11755 operators: { 11756 '=': function(nv, v) { return nv == v; }, 11757 '!=': function(nv, v) { return nv != v; }, 11758 '^=': function(nv, v) { return nv == v || nv && nv.startsWith(v); }, 11759 '$=': function(nv, v) { return nv == v || nv && nv.endsWith(v); }, 11760 '*=': function(nv, v) { return nv == v || nv && nv.include(v); }, 11761 '$=': function(nv, v) { return nv.endsWith(v); }, 11762 '*=': function(nv, v) { return nv.include(v); }, 11763 '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); }, 11764 '|=': function(nv, v) { return ('-' + (nv || "").toUpperCase() + 11765 '-').include('-' + (v || "").toUpperCase() + '-'); } 11766 }, 11767 11768 split: function(expression) { 11769 var expressions = []; 11770 expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) { 11771 expressions.push(m[1].strip()); 11772 }); 11773 return expressions; 11774 }, 11775 11776 matchElements: function(elements, expression) { 11777 var matches = $$(expression), h = Selector.handlers; 11778 h.mark(matches); 11779 for (var i = 0, results = [], element; element = elements[i]; i++) 11780 if (element._countedByPrototype) results.push(element); 11781 h.unmark(matches); 11782 return results; 11783 }, 11784 11785 findElement: function(elements, expression, index) { 11786 if (Object.isNumber(expression)) { 11787 index = expression; expression = false; 11788 } 11789 return Selector.matchElements(elements, expression || '*')[index || 0]; 11790 }, 11791 11792 findChildElements: function(element, expressions) { 11793 expressions = Selector.split(expressions.join(',')); 11794 var results = [], h = Selector.handlers; 11795 for (var i = 0, l = expressions.length, selector; i < l; i++) { 11796 selector = new Selector(expressions[i].strip()); 11797 h.concat(results, selector.findElements(element)); 11798 } 11799 return (l > 1) ? h.unique(results) : results; 11800 } 11801}); 11802 11803if (Prototype.Browser.IE) { 11804 Object.extend(Selector.handlers, { 11805 // IE returns comment nodes on getElementsByTagName("*"). 11806 // Filter them out. 11807 concat: function(a, b) { 11808 for (var i = 0, node; node = b[i]; i++) 11809 if (node.tagName !== "!") a.push(node); 11810 return a; 11811 }, 11812 11813 // IE improperly serializes _countedByPrototype in (inner|outer)HTML. 11814 unmark: function(nodes) { 11815 for (var i = 0, node; node = nodes[i]; i++) 11816 node.removeAttribute('_countedByPrototype'); 11817 return nodes; 11818 } 11819 }); 11820} 11821 11822function $$() { 11823 return Selector.findChildElements(document, $A(arguments)); 11824} 11825var Form = { 11826 reset: function(form) { 11827 $(form).reset(); 11828 return form; 11829 }, 11830 11831 serializeElements: function(elements, options) { 11832 if (typeof options != 'object') options = { hash: !!options }; 11833 else if (Object.isUndefined(options.hash)) options.hash = true; 11834 var key, value, submitted = false, submit = options.submit; 11835 11836 var data = elements.inject({ }, function(result, element) { 11837 if (!element.disabled && element.name) { 11838 key = element.name; value = $(element).getValue(); 11839 if (value != null && element.type != 'file' && (element.type != 'submit' || (!submitted && 11840 submit !== false && (!submit || key == submit) && (submitted = true)))) { 11841 if (key in result) { 11842 // a key is already present; construct an array of values 11843 if (!Object.isArray(result[key])) result[key] = [result[key]]; 11844 result[key].push(value); 11845 } 11846 else result[key] = value; 11847 } 11848 } 11849 return result; 11850 }); 11851 11852 return options.hash ? data : Object.toQueryString(data); 11853 } 11854}; 11855 11856Form.Methods = { 11857 serialize: function(form, options) { 11858 return Form.serializeElements(Form.getElements(form), options); 11859 }, 11860 11861 getElements: function(form) { 11862 return $A($(form).getElementsByTagName('*')).inject([], 11863 function(elements, child) { 11864 if (Form.Element.Serializers[child.tagName.toLowerCase()]) 11865 elements.push(Element.extend(child)); 11866 return elements; 11867 } 11868 ); 11869 }, 11870 11871 getInputs: function(form, typeName, name) { 11872 form = $(form); 11873 var inputs = form.getElementsByTagName('input'); 11874 11875 if (!typeName && !name) return $A(inputs).map(Element.extend); 11876 11877 for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) { 11878 var input = inputs[i]; 11879 if ((typeName && input.type != typeName) || (name && input.name != name)) 11880 continue; 11881 matchingInputs.push(Element.extend(input)); 11882 } 11883 11884 return matchingInputs; 11885 }, 11886 11887 disable: function(form) { 11888 form = $(form); 11889 Form.getElements(form).invoke('disable'); 11890 return form; 11891 }, 11892 11893 enable: function(form) { 11894 form = $(form); 11895 Form.getElements(form).invoke('enable'); 11896 return form; 11897 }, 11898 11899 findFirstElement: function(form) { 11900 var elements = $(form).getElements().findAll(function(element) { 11901 return 'hidden' != element.type && !element.disabled; 11902 }); 11903 var firstByIndex = elements.findAll(function(element) { 11904 return element.hasAttribute('tabIndex') && element.tabIndex >= 0; 11905 }).sortBy(function(element) { return element.tabIndex }).first(); 11906 11907 return firstByIndex ? firstByIndex : elements.find(function(element) { 11908 return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); 11909 }); 11910 }, 11911 11912 focusFirstElement: function(form) { 11913 form = $(form); 11914 form.findFirstElement().activate(); 11915 return form; 11916 }, 11917 11918 request: function(form, options) { 11919 form = $(form), options = Object.clone(options || { }); 11920 11921 var params = options.parameters, action = form.readAttribute('action') || ''; 11922 if (action.blank()) action = window.location.href; 11923 options.parameters = form.serialize(true); 11924 11925 if (params) { 11926 if (Object.isString(params)) params = params.toQueryParams(); 11927 Object.extend(options.parameters, params); 11928 } 11929 11930 if (form.hasAttribute('method') && !options.method) 11931 options.method = form.method; 11932 11933 return new Ajax.Request(action, options); 11934 } 11935}; 11936 11937/*--------------------------------------------------------------------------*/ 11938 11939Form.Element = { 11940 focus: function(element) { 11941 $(element).focus(); 11942 return element; 11943 }, 11944 11945 select: function(element) { 11946 $(element).select(); 11947 return element; 11948 } 11949}; 11950 11951Form.Element.Methods = { 11952 serialize: function(element) { 11953 element = $(element); 11954 if (!element.disabled && element.name) { 11955 var value = element.getValue(); 11956 if (value != undefined) { 11957 var pair = { }; 11958 pair[element.name] = value; 11959 return Object.toQueryString(pair); 11960 } 11961 } 11962 return ''; 11963 }, 11964 11965 getValue: function(element) { 11966 element = $(element); 11967 var method = element.tagName.toLowerCase(); 11968 return Form.Element.Serializers[method](element); 11969 }, 11970 11971 setValue: function(element, value) { 11972 element = $(element); 11973 var method = element.tagName.toLowerCase(); 11974 Form.Element.Serializers[method](element, value); 11975 return element; 11976 }, 11977 11978 clear: function(element) { 11979 $(element).value = ''; 11980 return element; 11981 }, 11982 11983 present: function(element) { 11984 return $(element).value != ''; 11985 }, 11986 11987 activate: function(element) { 11988 element = $(element); 11989 try { 11990 element.focus(); 11991 if (element.select && (element.tagName.toLowerCase() != 'input' || 11992 !['button', 'reset', 'submit'].include(element.type))) 11993 element.select(); 11994 } catch (e) { } 11995 return element; 11996 }, 11997 11998 disable: function(element) { 11999 element = $(element); 12000 element.disabled = true; 12001 return element; 12002 }, 12003 12004 enable: function(element) { 12005 element = $(element); 12006 element.disabled = false; 12007 return element; 12008 } 12009}; 12010 12011/*--------------------------------------------------------------------------*/ 12012 12013var Field = Form.Element; 12014var $F = Form.Element.Methods.getValue; 12015 12016/*--------------------------------------------------------------------------*/ 12017 12018Form.Element.Serializers = { 12019 input: function(element, value) { 12020 switch (element.type.toLowerCase()) { 12021 case 'checkbox': 12022 case 'radio': 12023 return Form.Element.Serializers.inputSelector(element, value); 12024 default: 12025 return Form.Element.Serializers.textarea(element, value); 12026 } 12027 }, 12028 12029 inputSelector: function(element, value) { 12030 if (Object.isUndefined(value)) return element.checked ? element.value : null; 12031 else element.checked = !!value; 12032 }, 12033 12034 textarea: function(element, value) { 12035 if (Object.isUndefined(value)) return element.value; 12036 else element.value = value; 12037 }, 12038 12039 select: function(element, value) { 12040 if (Object.isUndefined(value)) 12041 return this[element.type == 'select-one' ? 12042 'selectOne' : 'selectMany'](element); 12043 else { 12044 var opt, currentValue, single = !Object.isArray(value); 12045 for (var i = 0, length = element.length; i < length; i++) { 12046 opt = element.options[i]; 12047 currentValue = this.optionValue(opt); 12048 if (single) { 12049 if (currentValue == value) { 12050 opt.selected = true; 12051 return; 12052 } 12053 } 12054 else opt.selected = value.include(currentValue); 12055 } 12056 } 12057 }, 12058 12059 selectOne: function(element) { 12060 var index = element.selectedIndex; 12061 return index >= 0 ? this.optionValue(element.options[index]) : null; 12062 }, 12063 12064 selectMany: function(element) { 12065 var values, length = element.length; 12066 if (!length) return null; 12067 12068 for (var i = 0, values = []; i < length; i++) { 12069 var opt = element.options[i]; 12070 if (opt.selected) values.push(this.optionValue(opt)); 12071 } 12072 return values; 12073 }, 12074 12075 optionValue: function(opt) { 12076 // extend element because hasAttribute may not be native 12077 return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text; 12078 } 12079}; 12080 12081/*--------------------------------------------------------------------------*/ 12082 12083Abstract.TimedObserver = Class.create(PeriodicalExecuter, { 12084 initialize: function($super, element, frequency, callback) { 12085 $super(callback, frequency); 12086 this.element = $(element); 12087 this.lastValue = this.getValue(); 12088 }, 12089 12090 execute: function() { 12091 var value = this.getValue(); 12092 if (Object.isString(this.lastValue) && Object.isString(value) ? 12093 this.lastValue != value : String(this.lastValue) != String(value)) { 12094 this.callback(this.element, value); 12095 this.lastValue = value; 12096 } 12097 } 12098}); 12099 12100Form.Element.Observer = Class.create(Abstract.TimedObserver, { 12101 getValue: function() { 12102 return Form.Element.getValue(this.element); 12103 } 12104}); 12105 12106Form.Observer = Class.create(Abstract.TimedObserver, { 12107 getValue: function() { 12108 return Form.serialize(this.element); 12109 } 12110}); 12111 12112/*--------------------------------------------------------------------------*/ 12113 12114Abstract.EventObserver = Class.create({ 12115 initialize: function(element, callback) { 12116 this.element = $(element); 12117 this.callback = callback; 12118 12119 this.lastValue = this.getValue(); 12120 if (this.element.tagName.toLowerCase() == 'form') 12121 this.registerFormCallbacks(); 12122 else 12123 this.registerCallback(this.element); 12124 }, 12125 12126 onElementEvent: function() { 12127 var value = this.getValue(); 12128 if (this.lastValue != value) { 12129 this.callback(this.element, value); 12130 this.lastValue = value; 12131 } 12132 }, 12133 12134 registerFormCallbacks: function() { 12135 Form.getElements(this.element).each(this.registerCallback, this); 12136 }, 12137 12138 registerCallback: function(element) { 12139 if (element.type) { 12140 switch (element.type.toLowerCase()) { 12141 case 'checkbox': 12142 case 'radio': 12143 Event.observe(element, 'click', this.onElementEvent.bind(this)); 12144 break; 12145 default: 12146 Event.observe(element, 'change', this.onElementEvent.bind(this)); 12147 break; 12148 } 12149 } 12150 } 12151}); 12152 12153Form.Element.EventObserver = Class.create(Abstract.EventObserver, { 12154 getValue: function() { 12155 return Form.Element.getValue(this.element); 12156 } 12157}); 12158 12159Form.EventObserver = Class.create(Abstract.EventObserver, { 12160 getValue: function() { 12161 return Form.serialize(this.element); 12162 } 12163}); 12164if (!window.Event) var Event = { }; 12165 12166Object.extend(Event, { 12167 KEY_BACKSPACE: 8, 12168 KEY_TAB: 9, 12169 KEY_RETURN: 13, 12170 KEY_ESC: 27, 12171 KEY_LEFT: 37, 12172 KEY_UP: 38, 12173 KEY_RIGHT: 39, 12174 KEY_DOWN: 40, 12175 KEY_DELETE: 46, 12176 KEY_HOME: 36, 12177 KEY_END: 35, 12178 KEY_PAGEUP: 33, 12179 KEY_PAGEDOWN: 34, 12180 KEY_INSERT: 45, 12181 12182 cache: { }, 12183 12184 relatedTarget: function(event) { 12185 var element; 12186 switch(event.type) { 12187 case 'mouseover': element = event.fromElement; break; 12188 case 'mouseout': element = event.toElement; break; 12189 default: return null; 12190 } 12191 return Element.extend(element); 12192 } 12193}); 12194 12195Event.Methods = (function() { 12196 var isButton; 12197 12198 if (Prototype.Browser.IE) { 12199 var buttonMap = { 0: 1, 1: 4, 2: 2 }; 12200 isButton = function(event, code) { 12201 return event.button == buttonMap[code]; 12202 }; 12203 12204 } else if (Prototype.Browser.WebKit) { 12205 isButton = function(event, code) { 12206 switch (code) { 12207 case 0: return event.which == 1 && !event.metaKey; 12208 case 1: return event.which == 1 && event.metaKey; 12209 default: return false; 12210 } 12211 }; 12212 12213 } else { 12214 isButton = function(event, code) { 12215 return event.which ? (event.which === code + 1) : (event.button === code); 12216 }; 12217 } 12218 12219 return { 12220 isLeftClick: function(event) { return isButton(event, 0) }, 12221 isMiddleClick: function(event) { return isButton(event, 1) }, 12222 isRightClick: function(event) { return isButton(event, 2) }, 12223 12224 element: function(event) { 12225 event = Event.extend(event); 12226 12227 var node = event.target, 12228 type = event.type, 12229 currentTarget = event.currentTarget; 12230 12231 if (currentTarget && currentTarget.tagName) { 12232 // Firefox screws up the "click" event when moving between radio buttons 12233 // via arrow keys. It also screws up the "load" and "error" events on images, 12234 // reporting the document as the target instead of the original image. 12235 if (type === 'load' || type === 'error' || 12236 (type === 'click' && currentTarget.tagName.toLowerCase() === 'input' 12237 && currentTarget.type === 'radio')) 12238 node = currentTarget; 12239 } 12240 if (node.nodeType == Node.TEXT_NODE) node = node.parentNode; 12241 return Element.extend(node); 12242 }, 12243 12244 findElement: function(event, expression) { 12245 var element = Event.element(event); 12246 if (!expression) return element; 12247 var elements = [element].concat(element.ancestors()); 12248 return Selector.findElement(elements, expression, 0); 12249 }, 12250 12251 pointer: function(event) { 12252 var docElement = document.documentElement, 12253 body = document.body || { scrollLeft: 0, scrollTop: 0 }; 12254 return { 12255 x: event.pageX || (event.clientX + 12256 (docElement.scrollLeft || body.scrollLeft) - 12257 (docElement.clientLeft || 0)), 12258 y: event.pageY || (event.clientY + 12259 (docElement.scrollTop || body.scrollTop) - 12260 (docElement.clientTop || 0)) 12261 }; 12262 }, 12263 12264 pointerX: function(event) { return Event.pointer(event).x }, 12265 pointerY: function(event) { return Event.pointer(event).y }, 12266 12267 stop: function(event) { 12268 Event.extend(event); 12269 event.preventDefault(); 12270 event.stopPropagation(); 12271 event.stopped = true; 12272 } 12273 }; 12274})(); 12275 12276Event.extend = (function() { 12277 var methods = Object.keys(Event.Methods).inject({ }, function(m, name) { 12278 m[name] = Event.Methods[name].methodize(); 12279 return m; 12280 }); 12281 12282 if (Prototype.Browser.IE) { 12283 Object.extend(methods, { 12284 stopPropagation: function() { this.cancelBubble = true }, 12285 preventDefault: function() { this.returnValue = false }, 12286 inspect: function() { return "[object Event]" } 12287 }); 12288 12289 return function(event) { 12290 if (!event) return false; 12291 if (event._extendedByPrototype) return event; 12292 12293 event._extendedByPrototype = Prototype.emptyFunction; 12294 var pointer = Event.pointer(event); 12295 Object.extend(event, { 12296 target: event.srcElement, 12297 relatedTarget: Event.relatedTarget(event), 12298 pageX: pointer.x, 12299 pageY: pointer.y 12300 }); 12301 return Object.extend(event, methods); 12302 }; 12303 12304 } else { 12305 Event.prototype = Event.prototype || document.createEvent("HTMLEvents")['__proto__']; 12306 Object.extend(Event.prototype, methods); 12307 return Prototype.K; 12308 } 12309})(); 12310 12311Object.extend(Event, (function() { 12312 var cache = Event.cache; 12313 12314 function getEventID(element) { 12315 if (element._prototypeEventID) return element._prototypeEventID[0]; 12316 arguments.callee.id = arguments.callee.id || 1; 12317 return element._prototypeEventID = [++arguments.callee.id]; 12318 } 12319 12320 function getDOMEventName(eventName) { 12321 if (eventName && eventName.include(':')) return "dataavailable"; 12322 return eventName; 12323 } 12324 12325 function getCacheForID(id) { 12326 return cache[id] = cache[id] || { }; 12327 } 12328 12329 function getWrappersForEventName(id, eventName) { 12330 var c = getCacheForID(id); 12331 return c[eventName] = c[eventName] || []; 12332 } 12333 12334 function createWrapper(element, eventName, handler) { 12335 var id = getEventID(element); 12336 var c = getWrappersForEventName(id, eventName); 12337 if (c.pluck("handler").include(handler)) return false; 12338 12339 var wrapper = function(event) { 12340 if (!Event || !Event.extend || 12341 (event.eventName && event.eventName != eventName)) 12342 return false; 12343 12344 Event.extend(event); 12345 handler.call(element, event); 12346 }; 12347 12348 wrapper.handler = handler; 12349 c.push(wrapper); 12350 return wrapper; 12351 } 12352 12353 function findWrapper(id, eventName, handler) { 12354 var c = getWrappersForEventName(id, eventName); 12355 return c.find(function(wrapper) { return wrapper.handler == handler }); 12356 } 12357 12358 function destroyWrapper(id, eventName, handler) { 12359 var c = getCacheForID(id); 12360 if (!c[eventName]) return false; 12361 c[eventName] = c[eventName].without(findWrapper(id, eventName, handler)); 12362 } 12363 12364 function destroyCache() { 12365 for (var id in cache) 12366 for (var eventName in cache[id]) 12367 cache[id][eventName] = null; 12368 } 12369 12370 12371 // Internet Explorer needs to remove event handlers on page unload 12372 // in order to avoid memory leaks. 12373 if (window.attachEvent) { 12374 window.attachEvent("onunload", destroyCache); 12375 } 12376 12377 // Safari has a dummy event handler on page unload so that it won't 12378 // use its bfcache. Safari <= 3.1 has an issue with restoring the "document" 12379 // object when page is returned to via the back button using its bfcache. 12380 if (Prototype.Browser.WebKit) { 12381 window.addEventListener('unload', Prototype.emptyFunction, false); 12382 } 12383 12384 return { 12385 observe: function(element, eventName, handler) { 12386 element = $(element); 12387 var name = getDOMEventName(eventName); 12388 12389 var wrapper = createWrapper(element, eventName, handler); 12390 if (!wrapper) return element; 12391 12392 if (element.addEventListener) { 12393 element.addEventListener(name, wrapper, false); 12394 } else { 12395 element.attachEvent("on" + name, wrapper); 12396 } 12397 12398 return element; 12399 }, 12400 12401 stopObserving: function(element, eventName, handler) { 12402 element = $(element); 12403 var id = getEventID(element), name = getDOMEventName(eventName); 12404 12405 if (!handler && eventName) { 12406 getWrappersForEventName(id, eventName).each(function(wrapper) { 12407 element.stopObserving(eventName, wrapper.handler); 12408 }); 12409 return element; 12410 12411 } else if (!eventName) { 12412 Object.keys(getCacheForID(id)).each(function(eventName) { 12413 element.stopObserving(eventName); 12414 }); 12415 return element; 12416 } 12417 12418 var wrapper = findWrapper(id, eventName, handler); 12419 if (!wrapper) return element; 12420 12421 if (element.removeEventListener) { 12422 element.removeEventListener(name, wrapper, false); 12423 } else { 12424 element.detachEvent("on" + name, wrapper); 12425 } 12426 12427 destroyWrapper(id, eventName, handler); 12428 12429 return element; 12430 }, 12431 12432 fire: function(element, eventName, memo) { 12433 element = $(element); 12434 if (element == document && document.createEvent && !element.dispatchEvent) 12435 element = document.documentElement; 12436 12437 var event; 12438 if (document.createEvent) { 12439 event = document.createEvent("HTMLEvents"); 12440 event.initEvent("dataavailable", true, true); 12441 } else { 12442 event = document.createEventObject(); 12443 event.eventType = "ondataavailable"; 12444 } 12445 12446 event.eventName = eventName; 12447 event.memo = memo || { }; 12448 12449 if (document.createEvent) { 12450 element.dispatchEvent(event); 12451 } else { 12452 element.fireEvent(event.eventType, event); 12453 } 12454 12455 return Event.extend(event); 12456 } 12457 }; 12458})()); 12459 12460Object.extend(Event, Event.Methods); 12461 12462Element.addMethods({ 12463 fire: Event.fire, 12464 observe: Event.observe, 12465 stopObserving: Event.stopObserving 12466}); 12467 12468Object.extend(document, { 12469 fire: Element.Methods.fire.methodize(), 12470 observe: Element.Methods.observe.methodize(), 12471 stopObserving: Element.Methods.stopObserving.methodize(), 12472 loaded: false 12473}); 12474 12475(function() { 12476 /* Support for the DOMContentLoaded event is based on work by Dan Webb, 12477 Matthias Miller, Dean Edwards and John Resig. */ 12478 12479 var timer; 12480 12481 function fireContentLoadedEvent() { 12482 if (document.loaded) return; 12483 if (timer) window.clearInterval(timer); 12484 document.fire("dom:loaded"); 12485 document.loaded = true; 12486 } 12487 12488 if (document.addEventListener) { 12489 if (Prototype.Browser.WebKit) { 12490 timer = window.setInterval(function() { 12491 if (/loaded|complete/.test(document.readyState)) 12492 fireContentLoadedEvent(); 12493 }, 0); 12494 12495 Event.observe(window, "load", fireContentLoadedEvent); 12496 12497 } else { 12498 document.addEventListener("DOMContentLoaded", 12499 fireContentLoadedEvent, false); 12500 } 12501 12502 } else { 12503 document.write("<script id=__onDOMContentLoaded defer src=//:><\/script>"); 12504 $("__onDOMContentLoaded").onreadystatechange = function() { 12505 if (this.readyState == "complete") { 12506 this.onreadystatechange = null; 12507 fireContentLoadedEvent(); 12508 } 12509 }; 12510 } 12511})(); 12512/*------------------------------- DEPRECATED -------------------------------*/ 12513 12514Hash.toQueryString = Object.toQueryString; 12515 12516var Toggle = { display: Element.toggle }; 12517 12518Element.Methods.childOf = Element.Methods.descendantOf; 12519 12520var Insertion = { 12521 Before: function(element, content) { 12522 return Element.insert(element, {before:content}); 12523 }, 12524 12525 Top: function(element, content) { 12526 return Element.insert(element, {top:content}); 12527 }, 12528 12529 Bottom: function(element, content) { 12530 return Element.insert(element, {bottom:content}); 12531 }, 12532 12533 After: function(element, content) { 12534 return Element.insert(element, {after:content}); 12535 } 12536}; 12537 12538var $continue = new Error('"throw $continue" is deprecated, use "return" instead'); 12539 12540// This should be moved to script.aculo.us; notice the deprecated methods 12541// further below, that map to the newer Element methods. 12542var Position = { 12543 // set to true if needed, warning: firefox performance problems 12544 // NOT neeeded for page scrolling, only if draggable contained in 12545 // scrollable elements 12546 includeScrollOffsets: false, 12547 12548 // must be called before calling withinIncludingScrolloffset, every time the 12549 // page is scrolled 12550 prepare: function() { 12551 this.deltaX = window.pageXOffset 12552 || document.documentElement.scrollLeft 12553 || document.body.scrollLeft 12554 || 0; 12555 this.deltaY = window.pageYOffset 12556 || document.documentElement.scrollTop 12557 || document.body.scrollTop 12558 || 0; 12559 }, 12560 12561 // caches x/y coordinate pair to use with overlap 12562 within: function(element, x, y) { 12563 if (this.includeScrollOffsets) 12564 return this.withinIncludingScrolloffsets(element, x, y); 12565 this.xcomp = x; 12566 this.ycomp = y; 12567 this.offset = Element.cumulativeOffset(element); 12568 12569 return (y >= this.offset[1] && 12570 y < this.offset[1] + element.offsetHeight && 12571 x >= this.offset[0] && 12572 x < this.offset[0] + element.offsetWidth); 12573 }, 12574 12575 withinIncludingScrolloffsets: function(element, x, y) { 12576 var offsetcache = Element.cumulativeScrollOffset(element); 12577 12578 this.xcomp = x + offsetcache[0] - this.deltaX; 12579 this.ycomp = y + offsetcache[1] - this.deltaY; 12580 this.offset = Element.cumulativeOffset(element); 12581 12582 return (this.ycomp >= this.offset[1] && 12583 this.ycomp < this.offset[1] + element.offsetHeight && 12584 this.xcomp >= this.offset[0] && 12585 this.xcomp < this.offset[0] + element.offsetWidth); 12586 }, 12587 12588 // within must be called directly before 12589 overlap: function(mode, element) { 12590 if (!mode) return 0; 12591 if (mode == 'vertical') 12592 return ((this.offset[1] + element.offsetHeight) - this.ycomp) / 12593 element.offsetHeight; 12594 if (mode == 'horizontal') 12595 return ((this.offset[0] + element.offsetWidth) - this.xcomp) / 12596 element.offsetWidth; 12597 }, 12598 12599 // Deprecation layer -- use newer Element methods now (1.5.2). 12600 12601 cumulativeOffset: Element.Methods.cumulativeOffset, 12602 12603 positionedOffset: Element.Methods.positionedOffset, 12604 12605 absolutize: function(element) { 12606 Position.prepare(); 12607 return Element.absolutize(element); 12608 }, 12609 12610 relativize: function(element) { 12611 Position.prepare(); 12612 return Element.relativize(element); 12613 }, 12614 12615 realOffset: Element.Methods.cumulativeScrollOffset, 12616 12617 offsetParent: Element.Methods.getOffsetParent, 12618 12619 page: Element.Methods.viewportOffset, 12620 12621 clone: function(source, target, options) { 12622 options = options || { }; 12623 return Element.clonePosition(target, source, options); 12624 } 12625}; 12626 12627/*--------------------------------------------------------------------------*/ 12628 12629if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){ 12630 function iter(name) { 12631 return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]"; 12632 } 12633 12634 instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ? 12635 function(element, className) { 12636 className = className.toString().strip(); 12637 var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className); 12638 return cond ? document._getElementsByXPath('.//*' + cond, element) : []; 12639 } : function(element, className) { 12640 className = className.toString().strip(); 12641 var elements = [], classNames = (/\s/.test(className) ? $w(className) : null); 12642 if (!classNames && !className) return elements; 12643 12644 var nodes = $(element).getElementsByTagName('*'); 12645 className = ' ' + className + ' '; 12646 12647 for (var i = 0, child, cn; child = nodes[i]; i++) { 12648 if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) || 12649 (classNames && classNames.all(function(name) { 12650 return !name.toString().blank() && cn.include(' ' + name + ' '); 12651 })))) 12652 elements.push(Element.extend(child)); 12653 } 12654 return elements; 12655 }; 12656 12657 return function(className, parentElement) { 12658 return $(parentElement || document.body).getElementsByClassName(className); 12659 }; 12660}(Element.Methods); 12661 12662/*--------------------------------------------------------------------------*/ 12663 12664Element.ClassNames = Class.create(); 12665Element.ClassNames.prototype = { 12666 initialize: function(element) { 12667 this.element = $(element); 12668 }, 12669 12670 _each: function(iterator) { 12671 this.element.className.split(/\s+/).select(function(name) { 12672 return name.length > 0; 12673 })._each(iterator); 12674 }, 12675 12676 set: function(className) { 12677 this.element.className = className; 12678 }, 12679 12680 add: function(classNameToAdd) { 12681 if (this.include(classNameToAdd)) return; 12682 this.set($A(this).concat(classNameToAdd).join(' ')); 12683 }, 12684 12685 remove: function(classNameToRemove) { 12686 if (!this.include(classNameToRemove)) return; 12687 this.set($A(this).without(classNameToRemove).join(' ')); 12688 }, 12689 12690 toString: function() { 12691 return $A(this).join(' '); 12692 } 12693}; 12694 12695Object.extend(Element.ClassNames.prototype, Enumerable); 12696 12697/*--------------------------------------------------------------------------*/ 12698 12699Element.addMethods(); 12700