1 (function(){
2 /*
3 * jQuery 1.2.6 - New Wave Javascript
4 *
5 * Copyright (c) 2008 John Resig (jquery.com)
6 * Dual licensed under the MIT (MIT-LICENSE.txt)
7 * and GPL (GPL-LICENSE.txt) licenses.
8 *
9 * $Date: 2008-05-24 14:22:17 -0400 (Sat, 24 May 2008) $
10 * $Rev: 5685 $
11 */
12
13
14 // Map over jQuery in case of overwrite
15 var _jQuery = window.jQuery,
16 // Map over the $ in case of overwrite
17 _$ = window.$;
18
19 var jQuery = window.jQuery = window.$ = function( selector, context ) {
20 // The jQuery object is actually just the init constructor 'enhanced'
21 return new jQuery.fn.init( selector, context );
22 };
23
24 // A simple way to check for HTML strings or ID strings
25 // (both of which we optimize for)
26 var quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/,
27
28 // Is it a simple selector
29 isSimple = /^.[^:#\[\.]*$/,
30
31 // Will speed up references to undefined, and allows munging its name.
32 undefined;
33
34 jQuery.fn = jQuery.prototype = {
35 init: function( selector, context ) {
36 // Make sure that a selection was provided
37 selector = selector || document;
38
39 // Handle $(DOMElement)
40 if ( selector.nodeType ) {
41 this[0] = selector;
42 this.length = 1;
43 return this;
44 }
45 // Handle HTML strings
46 if ( typeof selector == "string" ) {
47 // Are we dealing with HTML string or an ID?
48 var match = quickExpr.exec( selector );
49
50 // Verify a match, and that no context was specified for #id
51 if ( match && (match[1] || !context) ) {
52
53 // HANDLE: $(html) -> $(array)
54 if ( match[1] )
55 selector = jQuery.clean( [ match[1] ], context );
56
57 // HANDLE: $("#id")
58 else {
59 var elem = document.getElementById( match[3] );
60
61 // Make sure an element was located
62 if ( elem ){
63 // Handle the case where IE and Opera return items
64 // by name instead of ID
65 if ( elem.id != match[3] )
66 return jQuery().find( selector );
67
68 // Otherwise, we inject the element directly into the jQuery object
69 return jQuery( elem );
70 }
71 selector = [];
72 }
73
74 // HANDLE: $(expr, [context])
75 // (which is just equivalent to: $(content).find(expr)
76 } else
77 return jQuery( context ).find( selector );
78
79 // HANDLE: $(function)
80 // Shortcut for document ready
81 } else if ( jQuery.isFunction( selector ) )
82 return jQuery( document )[ jQuery.fn.ready ? "ready" : "load" ]( selector );
83
84 return this.setArray(jQuery.makeArray(selector));
85 },
86
87 // The current version of jQuery being used
88 jquery: "1.2.6",
89
90 // The number of elements contained in the matched element set
91 size: function() {
92 return this.length;
93 },
94
95 // The number of elements contained in the matched element set
96 length: 0,
97
98 // Get the Nth element in the matched element set OR
99 // Get the whole matched element set as a clean array
100 get: function( num ) {
101 return num == undefined ?
102
103 // Return a 'clean' array
104 jQuery.makeArray( this ) :
105
106 // Return just the object
107 this[ num ];
108 },
109
110 // Take an array of elements and push it onto the stack
111 // (returning the new matched element set)
112 pushStack: function( elems ) {
113 // Build a new jQuery matched element set
114 var ret = jQuery( elems );
115
116 // Add the old object onto the stack (as a reference)
117 ret.prevObject = this;
118
119 // Return the newly-formed element set
120 return ret;
121 },
122
123 // Force the current matched set of elements to become
124 // the specified array of elements (destroying the stack in the process)
125 // You should use pushStack() in order to do this, but maintain the stack
126 setArray: function( elems ) {
127 // Resetting the length to 0, then using the native Array push
128 // is a super-fast way to populate an object with array-like properties
129 this.length = 0;
130 Array.prototype.push.apply( this, elems );
131
132 return this;
133 },
134
135 // Execute a callback for every element in the matched set.
136 // (You can seed the arguments with an array of args, but this is
137 // only used internally.)
138 each: function( callback, args ) {
139 return jQuery.each( this, callback, args );
140 },
141
142 // Determine the position of an element within
143 // the matched set of elements
144 index: function( elem ) {
145 var ret = -1;
146
147 // Locate the position of the desired element
148 return jQuery.inArray(
149 // If it receives a jQuery object, the first element is used
150 elem && elem.jquery ? elem[0] : elem
151 , this );
152 },
153
154 attr: function( name, value, type ) {
155 var options = name;
156
157 // Look for the case where we're accessing a style value
158 if ( name.constructor == String )
159 if ( value === undefined )
160 return this[0] && jQuery[ type || "attr" ]( this[0], name );
161
162 else {
163 options = {};
164 options[ name ] = value;
165 }
166
167 // Check to see if we're setting style values
168 return this.each(function(i){
169 // Set all the styles
170 for ( name in options )
171 jQuery.attr(
172 type ?
173 this.style :
174 this,
175 name, jQuery.prop( this, options[ name ], type, i, name )
176 );
177 });
178 },
179
180 css: function( key, value ) {
181 // ignore negative width and height values
182 if ( (key == 'width' || key == 'height') && parseFloat(value) < 0 )
183 value = undefined;
184 return this.attr( key, value, "curCSS" );
185 },
186
187 text: function( text ) {
188 if ( typeof text != "object" && text != null )
189 return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
190
191 var ret = "";
192
193 jQuery.each( text || this, function(){
194 jQuery.each( this.childNodes, function(){
195 if ( this.nodeType != 8 )
196 ret += this.nodeType != 1 ?
197 this.nodeValue :
198 jQuery.fn.text( [ this ] );
199 });
200 });
201
202 return ret;
203 },
204
205 wrapAll: function( html ) {
206 if ( this[0] )
207 // The elements to wrap the target around
208 jQuery( html, this[0].ownerDocument )
209 .clone()
210 .insertBefore( this[0] )
211 .map(function(){
212 var elem = this;
213
214 while ( elem.firstChild )
215 elem = elem.firstChild;
216
217 return elem;
218 })
219 .append(this);
220
221 return this;
222 },
223
224 wrapInner: function( html ) {
225 return this.each(function(){
226 jQuery( this ).contents().wrapAll( html );
227 });
228 },
229
230 wrap: function( html ) {
231 return this.each(function(){
232 jQuery( this ).wrapAll( html );
233 });
234 },
235
236 append: function() {
237 return this.domManip(arguments, true, false, function(elem){
238 if (this.nodeType == 1)
239 this.appendChild( elem );
240 });
241 },
242
243 prepend: function() {
244 return this.domManip(arguments, true, true, function(elem){
245 if (this.nodeType == 1)
246 this.insertBefore( elem, this.firstChild );
247 });
248 },
249
250 before: function() {
251 return this.domManip(arguments, false, false, function(elem){
252 this.parentNode.insertBefore( elem, this );
253 });
254 },
255
256 after: function() {
257 return this.domManip(arguments, false, true, function(elem){
258 this.parentNode.insertBefore( elem, this.nextSibling );
259 });
260 },
261
262 end: function() {
263 return this.prevObject || jQuery( [] );
264 },
265
266 find: function( selector ) {
267 var elems = jQuery.map(this, function(elem){
268 return jQuery.find( selector, elem );
269 });
270
271 return this.pushStack( /[^+>] [^+>]/.test( selector ) || selector.indexOf("..") > -1 ?
272 jQuery.unique( elems ) :
273 elems );
274 },
275
276 clone: function( events ) {
277 // Do the clone
278 var ret = this.map(function(){
279 if ( jQuery.browser.msie && !jQuery.isXMLDoc(this) ) {
280 // IE copies events bound via attachEvent when
281 // using cloneNode. Calling detachEvent on the
282 // clone will also remove the events from the orignal
283 // In order to get around this, we use innerHTML.
284 // Unfortunately, this means some modifications to
285 // attributes in IE that are actually only stored
286 // as properties will not be copied (such as the
287 // the name attribute on an input).
288 var clone = this.cloneNode(true),
289 container = document.createElement("div");
290 container.appendChild(clone);
291 return jQuery.clean([container.innerHTML])[0];
292 } else
293 return this.cloneNode(true);
294 });
295
296 // Need to set the expando to null on the cloned set if it exists
297 // removeData doesn't work here, IE removes it from the original as well
298 // this is primarily for IE but the data expando shouldn't be copied over in any browser
299 var clone = ret.find("*").andSelf().each(function(){
300 if ( this[ expando ] != undefined )
301 this[ expando ] = null;
302 });
303
304 // Copy the events from the original to the clone
305 if ( events === true )
306 this.find("*").andSelf().each(function(i){
307 if (this.nodeType == 3)
308 return;
309 var events = jQuery.data( this, "events" );
310
311 for ( var type in events )
312 for ( var handler in events[ type ] )
313 jQuery.event.add( clone[ i ], type, events[ type ][ handler ], events[ type ][ handler ].data );
314 });
315
316 // Return the cloned set
317 return ret;
318 },
319
320 filter: function( selector ) {
321 return this.pushStack(
322 jQuery.isFunction( selector ) &&
323 jQuery.grep(this, function(elem, i){
324 return selector.call( elem, i );
325 }) ||
326
327 jQuery.multiFilter( selector, this ) );
328 },
329
330 not: function( selector ) {
331 if ( selector.constructor == String )
332 // test special case where just one selector is passed in
333 if ( isSimple.test( selector ) )
334 return this.pushStack( jQuery.multiFilter( selector, this, true ) );
335 else
336 selector = jQuery.multiFilter( selector, this );
337
338 var isArrayLike = selector.length && selector[selector.length - 1] !== undefined && !selector.nodeType;
339 return this.filter(function() {
340 return isArrayLike ? jQuery.inArray( this, selector ) < 0 : this != selector;
341 });
342 },
343
344 add: function( selector ) {
345 return this.pushStack( jQuery.unique( jQuery.merge(
346 this.get(),
347 typeof selector == 'string' ?
348 jQuery( selector ) :
349 jQuery.makeArray( selector )
350 )));
351 },
352
353 is: function( selector ) {
354 return !!selector && jQuery.multiFilter( selector, this ).length > 0;
355 },
356
357 hasClass: function( selector ) {
358 return this.is( "." + selector );
359 },
360
361 val: function( value ) {
362 if ( value == undefined ) {
363
364 if ( this.length ) {
365 var elem = this[0];
366
367 // We need to handle select boxes special
368 if ( jQuery.nodeName( elem, "select" ) ) {
369 var index = elem.selectedIndex,
370 values = [],
371 options = elem.options,
372 one = elem.type == "select-one";
373
374 // Nothing was selected
375 if ( index < 0 )
376 return null;
377
378 // Loop through all the selected options
379 for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
380 var option = options[ i ];
381
382 if ( option.selected ) {
383 // Get the specifc value for the option
384 value = jQuery.browser.msie && !option.attributes.value.specified ? option.text : option.value;
385
386 // We don't need an array for one selects
387 if ( one )
388 return value;
389
390 // Multi-Selects return an array
391 values.push( value );
392 }
393 }
394
395 return values;
396
397 // Everything else, we just grab the value
398 } else
399 return (this[0].value || "").replace(/\r/g, "");
400
401 }
402
403 return undefined;
404 }
405
406 if( value.constructor == Number )
407 value += '';
408
409 return this.each(function(){
410 if ( this.nodeType != 1 )
411 return;
412
413 if ( value.constructor == Array && /radio|checkbox/.test( this.type ) )
414 this.checked = (jQuery.inArray(this.value, value) >= 0 ||
415 jQuery.inArray(this.name, value) >= 0);
416
417 else if ( jQuery.nodeName( this, "select" ) ) {
418 var values = jQuery.makeArray(value);
419
420 jQuery( "option", this ).each(function(){
421 this.selected = (jQuery.inArray( this.value, values ) >= 0 ||
422 jQuery.inArray( this.text, values ) >= 0);
423 });
424
425 if ( !values.length )
426 this.selectedIndex = -1;
427
428 } else
429 this.value = value;
430 });
431 },
432
433 html: function( value ) {
434 return value == undefined ?
435 (this[0] ?
436 this[0].innerHTML :
437 null) :
438 this.empty().append( value );
439 },
440
441 replaceWith: function( value ) {
442 return this.after( value ).remove();
443 },
444
445 eq: function( i ) {
446 return this.slice( i, i + 1 );
447 },
448
449 slice: function() {
450 return this.pushStack( Array.prototype.slice.apply( this, arguments ) );
451 },
452
453 map: function( callback ) {
454 return this.pushStack( jQuery.map(this, function(elem, i){
455 return callback.call( elem, i, elem );
456 }));
457 },
458
459 andSelf: function() {
460 return this.add( this.prevObject );
461 },
462
463 data: function( key, value ){
464 var parts = key.split(".");
465 parts[1] = parts[1] ? "." + parts[1] : "";
466
467 if ( value === undefined ) {
468 var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
469
470 if ( data === undefined && this.length )
471 data = jQuery.data( this[0], key );
472
473 return data === undefined && parts[1] ?
474 this.data( parts[0] ) :
475 data;
476 } else
477 return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function(){
478 jQuery.data( this, key, value );
479 });
480 },
481
482 removeData: function( key ){
483 return this.each(function(){
484 jQuery.removeData( this, key );
485 });
486 },
487
488 domManip: function( args, table, reverse, callback ) {
489 var clone = this.length > 1, elems;
490
491 return this.each(function(){
492 if ( !elems ) {
493 elems = jQuery.clean( args, this.ownerDocument );
494
495 if ( reverse )
496 elems.reverse();
497 }
498
499 var obj = this;
500
501 if ( table && jQuery.nodeName( this, "table" ) && jQuery.nodeName( elems[0], "tr" ) )
502 obj = this.getElementsByTagName("tbody")[0] || this.appendChild( this.ownerDocument.createElement("tbody") );
503
504 var scripts = jQuery( [] );
505
506 jQuery.each(elems, function(){
507 var elem = clone ?
508 jQuery( this ).clone( true )[0] :
509 this;
510
511 // execute all scripts after the elements have been injected
512 if ( jQuery.nodeName( elem, "script" ) )
513 scripts = scripts.add( elem );
514 else {
515 // Remove any inner scripts for later evaluation
516 if ( elem.nodeType == 1 )
517 scripts = scripts.add( jQuery( "script", elem ).remove() );
518
519 // Inject the elements into the document
520 callback.call( obj, elem );
521 }
522 });
523
524 scripts.each( evalScript );
525 });
526 }
527 };
528
529 // Give the init function the jQuery prototype for later instantiation
530 jQuery.fn.init.prototype = jQuery.fn;
531
532 function evalScript( i, elem ) {
533 if ( elem.src )
534 jQuery.ajax({
535 url: elem.src,
536 async: false,
537 dataType: "script"
538 });
539
540 else
541 jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
542
543 if ( elem.parentNode )
544 elem.parentNode.removeChild( elem );
545 }
546
547 function now(){
548 return +new Date;
549 }
550
551 jQuery.extend = jQuery.fn.extend = function() {
552 // copy reference to target object
553 var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;
554
555 // Handle a deep copy situation
556 if ( target.constructor == Boolean ) {
557 deep = target;
558 target = arguments[1] || {};
559 // skip the boolean and the target
560 i = 2;
561 }
562
563 // Handle case when target is a string or something (possible in deep copy)
564 if ( typeof target != "object" && typeof target != "function" )
565 target = {};
566
567 // extend jQuery itself if only one argument is passed
568 if ( length == i ) {
569 target = this;
570 --i;
571 }
572
573 for ( ; i < length; i++ )
574 // Only deal with non-null/undefined values
575 if ( (options = arguments[ i ]) != null )
576 // Extend the base object
577 for ( var name in options ) {
578 var src = target[ name ], copy = options[ name ];
579
580 // Prevent never-ending loop
581 if ( target === copy )
582 continue;
583
584 // Recurse if we're merging object values
585 if ( deep && copy && typeof copy == "object" && !copy.nodeType )
586 target[ name ] = jQuery.extend( deep,
587 // Never move original objects, clone them
588 src || ( copy.length != null ? [ ] : { } )
589 , copy );
590
591 // Don't bring in undefined values
592 else if ( copy !== undefined )
593 target[ name ] = copy;
594
595 }
596
597 // Return the modified object
598 return target;
599 };
600
601 var expando = "jQuery" + now(), uuid = 0, windowData = {},
602 // exclude the following css properties to add px
603 exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i,
604 // cache defaultView
605 defaultView = document.defaultView || {};
606
607 jQuery.extend({
608 noConflict: function( deep ) {
609 window.$ = _$;
610
611 if ( deep )
612 window.jQuery = _jQuery;
613
614 return jQuery;
615 },
616
617 // See test/unit/core.js for details concerning this function.
618 isFunction: function( fn ) {
619 return !!fn && typeof fn != "string" && !fn.nodeName &&
620 fn.constructor != Array && /^[\s[]?function/.test( fn + "" );
621 },
622
623 // check if an element is in a (or is an) XML document
624 isXMLDoc: function( elem ) {
625 return elem.documentElement && !elem.body ||
626 elem.tagName && elem.ownerDocument && !elem.ownerDocument.body;
627 },
628
629 // Evalulates a script in a global context
630 globalEval: function( data ) {
631 data = jQuery.trim( data );
632
633 if ( data ) {
634 // Inspired by code by Andrea Giammarchi
635 // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
636 var head = document.getElementsByTagName("head")[0] || document.documentElement,
637 script = document.createElement("script");
638
639 script.type = "text/javascript";
640 if ( jQuery.browser.msie )
641 script.text = data;
642 else
643 script.appendChild( document.createTextNode( data ) );
644
645 // Use insertBefore instead of appendChild to circumvent an IE6 bug.
646 // This arises when a base node is used (#2709).
647 head.insertBefore( script, head.firstChild );
648 head.removeChild( script );
649 }
650 },
651
652 nodeName: function( elem, name ) {
653 return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase();
654 },
655
656 cache: {},
657
658 data: function( elem, name, data ) {
659 elem = elem == window ?
660 windowData :
661 elem;
662
663 var id = elem[ expando ];
664
665 // Compute a unique ID for the element
666 if ( !id )
667 id = elem[ expando ] = ++uuid;
668
669 // Only generate the data cache if we're
670 // trying to access or manipulate it
671 if ( name && !jQuery.cache[ id ] )
672 jQuery.cache[ id ] = {};
673
674 // Prevent overriding the named cache with undefined values
675 if ( data !== undefined )
676 jQuery.cache[ id ][ name ] = data;
677
678 // Return the named cache data, or the ID for the element
679 return name ?
680 jQuery.cache[ id ][ name ] :
681 id;
682 },
683
684 removeData: function( elem, name ) {
685 elem = elem == window ?
686 windowData :
687 elem;
688
689 var id = elem[ expando ];
690
691 // If we want to remove a specific section of the element's data
692 if ( name ) {
693 if ( jQuery.cache[ id ] ) {
694 // Remove the section of cache data
695 delete jQuery.cache[ id ][ name ];
696
697 // If we've removed all the data, remove the element's cache
698 name = "";
699
700 for ( name in jQuery.cache[ id ] )
701 break;
702
703 if ( !name )
704 jQuery.removeData( elem );
705 }
706
707 // Otherwise, we want to remove all of the element's data
708 } else {
709 // Clean up the element expando
710 try {
711 delete elem[ expando ];
712 } catch(e){
713 // IE has trouble directly removing the expando
714 // but it's ok with using removeAttribute
715 if ( elem.removeAttribute )
716 elem.removeAttribute( expando );
717 }
718
719 // Completely remove the data cache
720 delete jQuery.cache[ id ];
721 }
722 },
723
724 // args is for internal usage only
725 each: function( object, callback, args ) {
726 var name, i = 0, length = object.length;
727
728 if ( args ) {
729 if ( length == undefined ) {
730 for ( name in object )
731 if ( callback.apply( object[ name ], args ) === false )
732 break;
733 } else
734 for ( ; i < length; )
735 if ( callback.apply( object[ i++ ], args ) === false )
736 break;
737
738 // A special, fast, case for the most common use of each
739 } else {
740 if ( length == undefined ) {
741 for ( name in object )
742 if ( callback.call( object[ name ], name, object[ name ] ) === false )
743 break;
744 } else
745 for ( var value = object[0];
746 i < length && callback.call( value, i, value ) !== false; value = object[++i] ){}
747 }
748
749 return object;
750 },
751
752 prop: function( elem, value, type, i, name ) {
753 // Handle executable functions
754 if ( jQuery.isFunction( value ) )
755 value = value.call( elem, i );
756
757 // Handle passing in a number to a CSS property
758 return value && value.constructor == Number && type == "curCSS" && !exclude.test( name ) ?
759 value + "px" :
760 value;
761 },
762
763 className: {
764 // internal only, use addClass("class")
765 add: function( elem, classNames ) {
766 jQuery.each((classNames || "").split(/\s+/), function(i, className){
767 if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) )
768 elem.className += (elem.className ? " " : "") + className;
769 });
770 },
771
772 // internal only, use removeClass("class")
773 remove: function( elem, classNames ) {
774 if (elem.nodeType == 1)
775 elem.className = classNames != undefined ?
776 jQuery.grep(elem.className.split(/\s+/), function(className){
777 return !jQuery.className.has( classNames, className );
778 }).join(" ") :
779 "";
780 },
781
782 // internal only, use hasClass("class")
783 has: function( elem, className ) {
784 return jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1;
785 }
786 },
787
788 // A method for quickly swapping in/out CSS properties to get correct calculations
789 swap: function( elem, options, callback ) {
790 var old = {};
791 // Remember the old values, and insert the new ones
792 for ( var name in options ) {
793 old[ name ] = elem.style[ name ];
794 elem.style[ name ] = options[ name ];
795 }
796
797 callback.call( elem );
798
799 // Revert the old values
800 for ( var name in options )
801 elem.style[ name ] = old[ name ];
802 },
803
804 css: function( elem, name, force ) {
805 if ( name == "width" || name == "height" ) {
806 var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ];
807
808 function getWH() {
809 val = name == "width" ? elem.offsetWidth : elem.offsetHeight;
810 var padding = 0, border = 0;
811 jQuery.each( which, function() {
812 padding += parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0;
813 border += parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0;
814 });
815 val -= Math.round(padding + border);
816 }
817
818 if ( jQuery(elem).is(":visible") )
819 getWH();
820 else
821 jQuery.swap( elem, props, getWH );
822
823 return Math.max(0, val);
824 }
825
826 return jQuery.curCSS( elem, name, force );
827 },
828
829 curCSS: function( elem, name, force ) {
830 var ret, style = elem.style;
831
832 // A helper method for determining if an element's values are broken
833 function color( elem ) {
834 if ( !jQuery.browser.safari )
835 return false;
836
837 // defaultView is cached
838 var ret = defaultView.getComputedStyle( elem, null );
839 return !ret || ret.getPropertyValue("color") == "";
840 }
841
842 // We need to handle opacity special in IE
843 if ( name == "opacity" && jQuery.browser.msie ) {
844 ret = jQuery.attr( style, "opacity" );
845
846 return ret == "" ?
847 "1" :
848 ret;
849 }
850 // Opera sometimes will give the wrong display answer, this fixes it, see #2037
851 if ( jQuery.browser.opera && name == "display" ) {
852 var save = style.outline;
853 style.outline = "0 solid black";
854 style.outline = save;
855 }
856
857 // Make sure we're using the right name for getting the float value
858 if ( name.match( /float/i ) )
859 name = styleFloat;
860
861 if ( !force && style && style[ name ] )
862 ret = style[ name ];
863
864 else if ( defaultView.getComputedStyle ) {
865
866 // Only "float" is needed here
867 if ( name.match( /float/i ) )
868 name = "float";
869
870 name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase();
871
872 var computedStyle = defaultView.getComputedStyle( elem, null );
873
874 if ( computedStyle && !color( elem ) )
875 ret = computedStyle.getPropertyValue( name );
876
877 // If the element isn't reporting its values properly in Safari
878 // then some display: none elements are involved
879 else {
880 var swap = [], stack = [], a = elem, i = 0;
881
882 // Locate all of the parent display: none elements
883 for ( ; a && color(a); a = a.parentNode )
884 stack.unshift(a);
885
886 // Go through and make them visible, but in reverse
887 // (It would be better if we knew the exact display type that they had)
888 for ( ; i < stack.length; i++ )
889 if ( color( stack[ i ] ) ) {
890 swap[ i ] = stack[ i ].style.display;
891 stack[ i ].style.display = "block";
892 }
893
894 // Since we flip the display style, we have to handle that
895 // one special, otherwise get the value
896 ret = name == "display" && swap[ stack.length - 1 ] != null ?
897 "none" :
898 ( computedStyle && computedStyle.getPropertyValue( name ) ) || "";
899
900 // Finally, revert the display styles back
901 for ( i = 0; i < swap.length; i++ )
902 if ( swap[ i ] != null )
903 stack[ i ].style.display = swap[ i ];
904 }
905
906 // We should always get a number back from opacity
907 if ( name == "opacity" && ret == "" )
908 ret = "1";
909
910 } else if ( elem.currentStyle ) {
911 var camelCase = name.replace(/\-(\w)/g, function(all, letter){
912 return letter.toUpperCase();
913 });
914
915 ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ];
916
917 // From the awesome hack by Dean Edwards
918 // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
919
920 // If we're not dealing with a regular pixel number
921 // but a number that has a weird ending, we need to convert it to pixels
922 if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) {
923 // Remember the original values
924 var left = style.left, rsLeft = elem.runtimeStyle.left;
925
926 // Put in the new values to get a computed value out
927 elem.runtimeStyle.left = elem.currentStyle.left;
928 style.left = ret || 0;
929 ret = style.pixelLeft + "px";
930
931 // Revert the changed values
932 style.left = left;
933 elem.runtimeStyle.left = rsLeft;
934 }
935 }
936
937 return ret;
938 },
939
940 clean: function( elems, context ) {
941 var ret = [];
942 context = context || document;
943 // !context.createElement fails in IE with an error but returns typeof 'object'
944 if (typeof context.createElement == 'undefined')
945 context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
946
947 jQuery.each(elems, function(i, elem){
948 if ( !elem )
949 return;
950
951 if ( elem.constructor == Number )
952 elem += '';
953
954 // Convert html string into DOM nodes
955 if ( typeof elem == "string" ) {
956 // Fix "XHTML"-style tags in all browsers
957 elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){
958 return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ?
959 all :
960 front + "></" + tag + ">";
961 });
962
963 // Trim whitespace, otherwise indexOf won't work as expected
964 var tags = jQuery.trim( elem ).toLowerCase(), div = context.createElement("div");
965
966 var wrap =
967 // option or optgroup
968 !tags.indexOf("<opt") &&
969 [ 1, "<select multiple='multiple'>", "</select>" ] ||
970
971 !tags.indexOf("<leg") &&
972 [ 1, "<fieldset>", "</fieldset>" ] ||
973
974 tags.match(/^<(thead|tbody|tfoot|colg|cap)/) &&
975 [ 1, "<table>", "</table>" ] ||
976
977 !tags.indexOf("<tr") &&
978 [ 2, "<table><tbody>", "</tbody></table>" ] ||
979
980 // <thead> matched above
981 (!tags.indexOf("<td") || !tags.indexOf("<th")) &&
982 [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ] ||
983
984 !tags.indexOf("<col") &&
985 [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ] ||
986
987 // IE can't serialize <link> and <script> tags normally
988 jQuery.browser.msie &&
989 [ 1, "div<div>", "</div>" ] ||
990
991 [ 0, "", "" ];
992
993 // Go to html and back, then peel off extra wrappers
994 div.innerHTML = wrap[1] + elem + wrap[2];
995
996 // Move to the right depth
997 while ( wrap[0]-- )
998 div = div.lastChild;
999
1000 // Remove IE's autoinserted <tbody> from table fragments
1001 if ( jQuery.browser.msie ) {
1002
1003 // String was a <table>, *may* have spurious <tbody>
1004 var tbody = !tags.indexOf("<table") && tags.indexOf("<tbody") < 0 ?
1005 div.firstChild && div.firstChild.childNodes :
1006
1007 // String was a bare <thead> or <tfoot>
1008 wrap[1] == "<table>" && tags.indexOf("<tbody") < 0 ?
1009 div.childNodes :
1010 [];
1011
1012 for ( var j = tbody.length - 1; j >= 0 ; --j )
1013 if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length )
1014 tbody[ j ].parentNode.removeChild( tbody[ j ] );
1015
1016 // IE completely kills leading whitespace when innerHTML is used
1017 if ( /^\s/.test( elem ) )
1018 div.insertBefore( context.createTextNode( elem.match(/^\s*/)[0] ), div.firstChild );
1019
1020 }
1021
1022 elem = jQuery.makeArray( div.childNodes );
1023 }
1024
1025 if ( elem.length === 0 && (!jQuery.nodeName( elem, "form" ) && !jQuery.nodeName( elem, "select" )) )
1026 return;
1027
1028 if ( elem[0] == undefined || jQuery.nodeName( elem, "form" ) || elem.options )
1029 ret.push( elem );
1030
1031 else
1032 ret = jQuery.merge( ret, elem );
1033
1034 });
1035
1036 return ret;
1037 },
1038
1039 attr: function( elem, name, value ) {
1040 // don't set attributes on text and comment nodes
1041 if (!elem || elem.nodeType == 3 || elem.nodeType == 8)
1042 return undefined;
1043
1044 var notxml = !jQuery.isXMLDoc( elem ),
1045 // Whether we are setting (or getting)
1046 set = value !== undefined,
1047 msie = jQuery.browser.msie;
1048
1049 // Try to normalize/fix the name
1050 name = notxml && jQuery.props[ name ] || name;
1051
1052 // Only do all the following if this is a node (faster for style)
1053 // IE elem.getAttribute passes even for style
1054 if ( elem.tagName ) {
1055
1056 // These attributes require special treatment
1057 var special = /href|src|style/.test( name );
1058
1059 // Safari mis-reports the default selected property of a hidden option
1060 // Accessing the parent's selectedIndex property fixes it
1061 if ( name == "selected" && jQuery.browser.safari )
1062 elem.parentNode.selectedIndex;
1063
1064 // If applicable, access the attribute via the DOM 0 way
1065 if ( name in elem && notxml && !special ) {
1066 if ( set ){
1067 // We can't allow the type property to be changed (since it causes problems in IE)
1068 if ( name == "type" && jQuery.nodeName( elem, "input" ) && elem.parentNode )
1069 throw "type property can't be changed";
1070
1071 elem[ name ] = value;
1072 }
1073
1074 // browsers index elements by id/name on forms, give priority to attributes.
1075 if( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) )
1076 return elem.getAttributeNode( name ).nodeValue;
1077
1078 return elem[ name ];
1079 }
1080
1081 if ( msie && notxml && name == "style" )
1082 return jQuery.attr( elem.style, "cssText", value );
1083
1084 if ( set )
1085 // convert the value to a string (all browsers do this but IE) see #1070
1086 elem.setAttribute( name, "" + value );
1087
1088 var attr = msie && notxml && special
1089 // Some attributes require a special call on IE
1090 ? elem.getAttribute( name, 2 )
1091 : elem.getAttribute( name );
1092
1093 // Non-existent attributes return null, we normalize to undefined
1094 return attr === null ? undefined : attr;
1095 }
1096
1097 // elem is actually elem.style ... set the style
1098
1099 // IE uses filters for opacity
1100 if ( msie && name == "opacity" ) {
1101 if ( set ) {
1102 // IE has trouble with opacity if it does not have layout
1103 // Force it by setting the zoom level
1104 elem.zoom = 1;
1105
1106 // Set the alpha filter to set the opacity
1107 elem.filter = (elem.filter || "").replace( /alpha\([^)]*\)/, "" ) +
1108 (parseInt( value ) + '' == "NaN" ? "" : "alpha(opacity=" + value * 100 + ")");
1109 }
1110
1111 return elem.filter && elem.filter.indexOf("opacity=") >= 0 ?
1112 (parseFloat( elem.filter.match(/opacity=([^)]*)/)[1] ) / 100) + '':
1113 "";
1114 }
1115
1116 name = name.replace(/-([a-z])/ig, function(all, letter){
1117 return letter.toUpperCase();
1118 });
1119
1120 if ( set )
1121 elem[ name ] = value;
1122
1123 return elem[ name ];
1124 },
1125
1126 trim: function( text ) {
1127 return (text || "").replace( /^\s+|\s+$/g, "" );
1128 },
1129
1130 makeArray: function( array ) {
1131 var ret = [];
1132
1133 if( array != null ){
1134 var i = array.length;
1135 //the window, strings and functions also have 'length'
1136 if( i == null || array.split || array.setInterval || array.call )
1137 ret[0] = array;
1138 else
1139 while( i )
1140 ret[--i] = array[i];
1141 }
1142
1143 return ret;
1144 },
1145
1146 inArray: function( elem, array ) {
1147 for ( var i = 0, length = array.length; i < length; i++ )
1148 // Use === because on IE, window == document
1149 if ( array[ i ] === elem )
1150 return i;
1151
1152 return -1;
1153 },
1154
1155 merge: function( first, second ) {
1156 // We have to loop this way because IE & Opera overwrite the length
1157 // expando of getElementsByTagName
1158 var i = 0, elem, pos = first.length;
1159 // Also, we need to make sure that the correct elements are being returned
1160 // (IE returns comment nodes in a '*' query)
1161 if ( jQuery.browser.msie ) {
1162 while ( elem = second[ i++ ] )
1163 if ( elem.nodeType != 8 )
1164 first[ pos++ ] = elem;
1165
1166 } else
1167 while ( elem = second[ i++ ] )
1168 first[ pos++ ] = elem;
1169
1170 return first;
1171 },
1172
1173 unique: function( array ) {
1174 var ret = [], done = {};
1175
1176 try {
1177
1178 for ( var i = 0, length = array.length; i < length; i++ ) {
1179 var id = jQuery.data( array[ i ] );
1180
1181 if ( !done[ id ] ) {
1182 done[ id ] = true;
1183 ret.push( array[ i ] );
1184 }
1185 }
1186
1187 } catch( e ) {
1188 ret = array;
1189 }
1190
1191 return ret;
1192 },
1193
1194 grep: function( elems, callback, inv ) {
1195 var ret = [];
1196
1197 // Go through the array, only saving the items
1198 // that pass the validator function
1199 for ( var i = 0, length = elems.length; i < length; i++ )
1200 if ( !inv != !callback( elems[ i ], i ) )
1201 ret.push( elems[ i ] );
1202
1203 return ret;
1204 },
1205
1206 map: function( elems, callback ) {
1207 var ret = [];
1208
1209 // Go through the array, translating each of the items to their
1210 // new value (or values).
1211 for ( var i = 0, length = elems.length; i < length; i++ ) {
1212 var value = callback( elems[ i ], i );
1213
1214 if ( value != null )
1215 ret[ ret.length ] = value;
1216 }
1217
1218 return ret.concat.apply( [], ret );
1219 }
1220 });
1221
1222 var userAgent = navigator.userAgent.toLowerCase();
1223
1224 // Figure out what browser is being used
1225 jQuery.browser = {
1226 version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [])[1],
1227 safari: /webkit/.test( userAgent ),
1228 opera: /opera/.test( userAgent ),
1229 msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ),
1230 mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent )
1231 };
1232
1233 var styleFloat = jQuery.browser.msie ?
1234 "styleFloat" :
1235 "cssFloat";
1236
1237 jQuery.extend({
1238 // Check to see if the W3C box model is being used
1239 boxModel: !jQuery.browser.msie || document.compatMode == "CSS1Compat",
1240
1241 props: {
1242 "for": "htmlFor",
1243 "class": "className",
1244 "float": styleFloat,
1245 cssFloat: styleFloat,
1246 styleFloat: styleFloat,
1247 readonly: "readOnly",
1248 maxlength: "maxLength",
1249 cellspacing: "cellSpacing"
1250 }
1251 });
1252
1253 jQuery.each({
1254 parent: function(elem){return elem.parentNode;},
1255 parents: function(elem){return jQuery.dir(elem,"parentNode");},
1256 next: function(elem){return jQuery.nth(elem,2,"nextSibling");},
1257 prev: function(elem){return jQuery.nth(elem,2,"previousSibling");},
1258 nextAll: function(elem){return jQuery.dir(elem,"nextSibling");},
1259 prevAll: function(elem){return jQuery.dir(elem,"previousSibling");},
1260 siblings: function(elem){return jQuery.sibling(elem.parentNode.firstChild,elem);},
1261 children: function(elem){return jQuery.sibling(elem.firstChild);},
1262 contents: function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes);}
1263 }, function(name, fn){
1264 jQuery.fn[ name ] = function( selector ) {
1265 var ret = jQuery.map( this, fn );
1266
1267 if ( selector && typeof selector == "string" )
1268 ret = jQuery.multiFilter( selector, ret );
1269
1270 return this.pushStack( jQuery.unique( ret ) );
1271 };
1272 });
1273
1274 jQuery.each({
1275 appendTo: "append",
1276 prependTo: "prepend",
1277 insertBefore: "before",
1278 insertAfter: "after",
1279 replaceAll: "replaceWith"
1280 }, function(name, original){
1281 jQuery.fn[ name ] = function() {
1282 var args = arguments;
1283
1284 return this.each(function(){
1285 for ( var i = 0, length = args.length; i < length; i++ )
1286 jQuery( args[ i ] )[ original ]( this );
1287 });
1288 };
1289 });
1290
1291 jQuery.each({
1292 removeAttr: function( name ) {
1293 jQuery.attr( this, name, "" );
1294 if (this.nodeType == 1)
1295 this.removeAttribute( name );
1296 },
1297
1298 addClass: function( classNames ) {
1299 jQuery.className.add( this, classNames );
1300 },
1301
1302 removeClass: function( classNames ) {
1303 jQuery.className.remove( this, classNames );
1304 },
1305
1306 toggleClass: function( classNames ) {
1307 jQuery.className[ jQuery.className.has( this, classNames ) ? "remove" : "add" ]( this, classNames );
1308 },
1309
1310 remove: function( selector ) {
1311 if ( !selector || jQuery.filter( selector, [ this ] ).r.length ) {
1312 // Prevent memory leaks
1313 jQuery( "*", this ).add(this).each(function(){
1314 jQuery.event.remove(this);
1315 jQuery.removeData(this);
1316 });
1317 if (this.parentNode)
1318 this.parentNode.removeChild( this );
1319 }
1320 },
1321
1322 empty: function() {
1323 // Remove element nodes and prevent memory leaks
1324 jQuery( ">*", this ).remove();
1325
1326 // Remove any remaining nodes
1327 while ( this.firstChild )
1328 this.removeChild( this.firstChild );
1329 }
1330 }, function(name, fn){
1331 jQuery.fn[ name ] = function(){
1332 return this.each( fn, arguments );
1333 };
1334 });
1335
1336 jQuery.each([ "Height", "Width" ], function(i, name){
1337 var type = name.toLowerCase();
1338
1339 jQuery.fn[ type ] = function( size ) {
1340 // Get window width or height
1341 return this[0] == window ?
1342 // Opera reports document.body.client[Width/Height] properly in both quirks and standards
1343 jQuery.browser.opera && document.body[ "client" + name ] ||
1344
1345 // Safari reports inner[Width/Height] just fine (Mozilla and Opera include scroll bar widths)
1346 jQuery.browser.safari && window[ "inner" + name ] ||
1347
1348 // Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
1349 document.compatMode == "CSS1Compat" && document.documentElement[ "client" + name ] || document.body[ "client" + name ] :
1350
1351 // Get document width or height
1352 this[0] == document ?
1353 // Either scroll[Width/Height] or offset[Width/Height], whichever is greater
1354 Math.max(
1355 Math.max(document.body["scroll" + name], document.documentElement["scroll" + name]),
1356 Math.max(document.body["offset" + name], document.documentElement["offset" + name])
1357 ) :
1358
1359 // Get or set width or height on the element
1360 size == undefined ?
1361 // Get width or height on the element
1362 (this.length ? jQuery.css( this[0], type ) : null) :
1363
1364 // Set the width or height on the element (default to pixels if value is unitless)
1365 this.css( type, size.constructor == String ? size : size + "px" );
1366 };
1367 });
1368
1369 // Helper function used by the dimensions and offset modules
1370 function num(elem, prop) {
1371 return elem[0] && parseInt( jQuery.curCSS(elem[0], prop, true), 10 ) || 0;
1372 }var chars = jQuery.browser.safari && parseInt(jQuery.browser.version) < 417 ?
1373 "(?:[\\w*_-]|\\\\.)" :
1374 "(?:[\\w\u0128-\uFFFF*_-]|\\\\.)",
1375 quickChild = new RegExp("^>\\s*(" + chars + "+)"),
1376 quickID = new RegExp("^(" + chars + "+)(#)(" + chars + "+)"),
1377 quickClass = new RegExp("^([#.]?)(" + chars + "*)");
1378
1379 jQuery.extend({
1380 expr: {
1381 "": function(a,i,m){return m[2]=="*"||jQuery.nodeName(a,m[2]);},
1382 "#": function(a,i,m){return a.getAttribute("id")==m[2];},
1383 ":": {
1384 // Position Checks
1385 lt: function(a,i,m){return i<m[3]-0;},
1386 gt: function(a,i,m){return i>m[3]-0;},
1387 nth: function(a,i,m){return m[3]-0==i;},
1388 eq: function(a,i,m){return m[3]-0==i;},
1389 first: function(a,i){return i==0;},
1390 last: function(a,i,m,r){return i==r.length-1;},
1391 even: function(a,i){return i%2==0;},
1392 odd: function(a,i){return i%2;},
1393
1394 // Child Checks
1395 "first-child": function(a){return a.parentNode.getElementsByTagName("*")[0]==a;},
1396 "last-child": function(a){return jQuery.nth(a.parentNode.lastChild,1,"previousSibling")==a;},
1397 "only-child": function(a){return !jQuery.nth(a.parentNode.lastChild,2,"previousSibling");},
1398
1399 // Parent Checks
1400 parent: function(a){return a.firstChild;},
1401 empty: function(a){return !a.firstChild;},
1402
1403 // Text Check
1404 contains: function(a,i,m){return (a.textContent||a.innerText||jQuery(a).text()||"").indexOf(m[3])>=0;},
1405
1406 // Visibility
1407 visible: function(a){return "hidden"!=a.type&&jQuery.css(a,"display")!="none"&&jQuery.css(a,"visibility")!="hidden";},
1408 hidden: function(a){return "hidden"==a.type||jQuery.css(a,"display")=="none"||jQuery.css(a,"visibility")=="hidden";},
1409
1410 // Form attributes
1411 enabled: function(a){return !a.disabled;},
1412 disabled: function(a){return a.disabled;},
1413 checked: function(a){return a.checked;},
1414 selected: function(a){return a.selected||jQuery.attr(a,"selected");},
1415
1416 // Form elements
1417 text: function(a){return "text"==a.type;},
1418 radio: function(a){return "radio"==a.type;},
1419 checkbox: function(a){return "checkbox"==a.type;},
1420 file: function(a){return "file"==a.type;},
1421 password: function(a){return "password"==a.type;},
1422 submit: function(a){return "submit"==a.type;},
1423 image: function(a){return "image"==a.type;},
1424 reset: function(a){return "reset"==a.type;},
1425 button: function(a){return "button"==a.type||jQuery.nodeName(a,"button");},
1426 input: function(a){return /input|select|textarea|button/i.test(a.nodeName);},
1427
1428 // :has()
1429 has: function(a,i,m){return jQuery.find(m[3],a).length;},
1430
1431 // :header
1432 header: function(a){return /h\d/i.test(a.nodeName);},
1433
1434 // :animated
1435 animated: function(a){return jQuery.grep(jQuery.timers,function(fn){return a==fn.elem;}).length;}
1436 }
1437 },
1438
1439 // The regular expressions that power the parsing engine
1440 parse: [
1441 // Match: [@value='test'], [@foo]
1442 /^(\[) *@?([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/,
1443
1444 // Match: :contains('foo')
1445 /^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/,
1446
1447 // Match: :even, :last-child, #id, .class
1448 new RegExp("^([:.#]*)(" + chars + "+)")
1449 ],
1450
1451 multiFilter: function( expr, elems, not ) {
1452 var old, cur = [];
1453
1454 while ( expr && expr != old ) {
1455 old = expr;
1456 var f = jQuery.filter( expr, elems, not );
1457 expr = f.t.replace(/^\s*,\s*/, "" );
1458 cur = not ? elems = f.r : jQuery.merge( cur, f.r );
1459 }
1460
1461 return cur;
1462 },
1463
1464 find: function( t, context ) {
1465 // Quickly handle non-string expressions
1466 if ( typeof t != "string" )
1467 return [ t ];
1468
1469 // check to make sure context is a DOM element or a document
1470 if ( context && context.nodeType != 1 && context.nodeType != 9)
1471 return [ ];
1472
1473 // Set the correct context (if none is provided)
1474 context = context || document;
1475
1476 // Initialize the search
1477 var ret = [context], done = [], last, nodeName;
1478
1479 // Continue while a selector expression exists, and while
1480 // we're no longer looping upon ourselves
1481 while ( t && last != t ) {
1482 var r = [];
1483 last = t;
1484
1485 t = jQuery.trim(t);
1486
1487 var foundToken = false,
1488
1489 // An attempt at speeding up child selectors that
1490 // point to a specific element tag
1491 re = quickChild,
1492
1493 m = re.exec(t);
1494
1495 if ( m ) {
1496 nodeName = m[1].toUpperCase();
1497
1498 // Perform our own iteration and filter
1499 for ( var i = 0; ret[i]; i++ )
1500 for ( var c = ret[i].firstChild; c; c = c.nextSibling )
1501 if ( c.nodeType == 1 && (nodeName == "*" || c.nodeName.toUpperCase() == nodeName) )
1502 r.push( c );
1503
1504 ret = r;
1505 t = t.replace( re, "" );
1506 if ( t.indexOf(" ") == 0 ) continue;
1507 foundToken = true;
1508 } else {
1509 re = /^([>+~])\s*(\w*)/i;
1510
1511 if ( (m = re.exec(t)) != null ) {
1512 r = [];
1513
1514 var merge = {};
1515 nodeName = m[2].toUpperCase();
1516 m = m[1];
1517
1518 for ( var j = 0, rl = ret.length; j < rl; j++ ) {
1519 var n = m == "~" || m == "+" ? ret[j].nextSibling : ret[j].firstChild;
1520 for ( ; n; n = n.nextSibling )
1521 if ( n.nodeType == 1 ) {
1522 var id = jQuery.data(n);
1523
1524 if ( m == "~" && merge[id] ) break;
1525
1526 if (!nodeName || n.nodeName.toUpperCase() == nodeName ) {
1527 if ( m == "~" ) merge[id] = true;
1528 r.push( n );
1529 }
1530
1531 if ( m == "+" ) break;
1532 }
1533 }
1534
1535 ret = r;
1536
1537 // And remove the token
1538 t = jQuery.trim( t.replace( re, "" ) );
1539 foundToken = true;
1540 }
1541 }
1542
1543 // See if there's still an expression, and that we haven't already
1544 // matched a token
1545 if ( t && !foundToken ) {
1546 // Handle multiple expressions
1547 if ( !t.indexOf(",") ) {
1548 // Clean the result set
1549 if ( context == ret[0] ) ret.shift();
1550
1551 // Merge the result sets
1552 done = jQuery.merge( done, ret );
1553
1554 // Reset the context
1555 r = ret = [context];
1556
1557 // Touch up the selector string
1558 t = " " + t.substr(1,t.length);
1559
1560 } else {
1561 // Optimize for the case nodeName#idName
1562 var re2 = quickID;
1563 var m = re2.exec(t);
1564
1565 // Re-organize the results, so that they're consistent
1566 if ( m ) {
1567 m = [ 0, m[2], m[3], m[1] ];
1568
1569 } else {
1570 // Otherwise, do a traditional filter check for
1571 // ID, class, and element selectors
1572 re2 = quickClass;
1573 m = re2.exec(t);
1574 }
1575
1576 m[2] = m[2].replace(/\\/g, "");
1577
1578 var elem = ret[ret.length-1];
1579
1580 // Try to do a global search by ID, where we can
1581 if ( m[1] == "#" && elem && elem.getElementById && !jQuery.isXMLDoc(elem) ) {
1582 // Optimization for HTML document case
1583 var oid = elem.getElementById(m[2]);
1584
1585 // Do a quick check for the existence of the actual ID attribute
1586 // to avoid selecting by the name attribute in IE
1587 // also check to insure id is a string to avoid selecting an element with the name of 'id' inside a form
1588 if ( (jQuery.browser.msie||jQuery.browser.opera) && oid && typeof oid.id == "string" && oid.id != m[2] )
1589 oid = jQuery('[@id="'+m[2]+'"]', elem)[0];
1590
1591 // Do a quick check for node name (where applicable) so
1592 // that div#foo searches will be really fast
1593 ret = r = oid && (!m[3] || jQuery.nodeName(oid, m[3])) ? [oid] : [];
1594 } else {
1595 // We need to find all descendant elements
1596 for ( var i = 0; ret[i]; i++ ) {
1597 // Grab the tag name being searched for
1598 var tag = m[1] == "#" && m[3] ? m[3] : m[1] != "" || m[0] == "" ? "*" : m[2];
1599
1600 // Handle IE7 being really dumb about <object>s
1601 if ( tag == "*" && ret[i].nodeName.toLowerCase() == "object" )
1602 tag = "param";
1603
1604 r = jQuery.merge( r, ret[i].getElementsByTagName( tag ));
1605 }
1606
1607 // It's faster to filter by class and be done with it
1608 if ( m[1] == "." )
1609 r = jQuery.classFilter( r, m[2] );
1610
1611 // Same with ID filtering
1612 if ( m[1] == "#" ) {
1613 var tmp = [];
1614
1615 // Try to find the element with the ID
1616 for ( var i = 0; r[i]; i++ )
1617 if ( r[i].getAttribute("id") == m[2] ) {
1618 tmp = [ r[i] ];
1619 break;
1620 }
1621
1622 r = tmp;
1623 }
1624
1625 ret = r;
1626 }
1627
1628 t = t.replace( re2, "" );
1629 }
1630
1631 }
1632
1633 // If a selector string still exists
1634 if ( t ) {
1635 // Attempt to filter it
1636 var val = jQuery.filter(t,r);
1637 ret = r = val.r;
1638 t = jQuery.trim(val.t);
1639 }
1640 }
1641
1642 // An error occurred with the selector;
1643 // just return an empty set instead
1644 if ( t )
1645 ret = [];
1646
1647 // Remove the root context
1648 if ( ret && context == ret[0] )
1649 ret.shift();
1650
1651 // And combine the results
1652 done = jQuery.merge( done, ret );
1653
1654 return done;
1655 },
1656
1657 classFilter: function(r,m,not){
1658 m = " " + m + " ";
1659 var tmp = [];
1660 for ( var i = 0; r[i]; i++ ) {
1661 var pass = (" " + r[i].className + " ").indexOf( m ) >= 0;
1662 if ( !not && pass || not && !pass )
1663 tmp.push( r[i] );
1664 }
1665 return tmp;
1666 },
1667
1668 filter: function(t,r,not) {
1669 var last;
1670
1671 // Look for common filter expressions
1672 while ( t && t != last ) {
1673 last = t;
1674
1675 var p = jQuery.parse, m;
1676
1677 for ( var i = 0; p[i]; i++ ) {
1678 m = p[i].exec( t );
1679
1680 if ( m ) {
1681 // Remove what we just matched
1682 t = t.substring( m[0].length );
1683
1684 m[2] = m[2].replace(/\\/g, "");
1685 break;
1686 }
1687 }
1688
1689 if ( !m )
1690 break;
1691
1692 // :not() is a special case that can be optimized by
1693 // keeping it out of the expression list
1694 if ( m[1] == ":" && m[2] == "not" )
1695 // optimize if only one selector found (most common case)
1696 r = isSimple.test( m[3] ) ?
1697 jQuery.filter(m[3], r, true).r :
1698 jQuery( r ).not( m[3] );
1699
1700 // We can get a big speed boost by filtering by class here
1701 else if ( m[1] == "." )
1702 r = jQuery.classFilter(r, m[2], not);
1703
1704 else if ( m[1] == "[" ) {
1705 var tmp = [], type = m[3];
1706
1707 for ( var i = 0, rl = r.length; i < rl; i++ ) {
1708 var a = r[i], z = a[ jQuery.props[m[2]] || m[2] ];
1709
1710 if ( z == null || /href|src|selected/.test(m[2]) )
1711 z = jQuery.attr(a,m[2]) || '';
1712
1713 if ( (type == "" && !!z ||
1714 type == "=" && z == m[5] ||
1715 type == "!=" && z != m[5] ||
1716 type == "^=" && z && !z.indexOf(m[5]) ||
1717 type == "$=" && z.substr(z.length - m[5].length) == m[5] ||
1718 (type == "*=" || type == "~=") && z.indexOf(m[5]) >= 0) ^ not )
1719 tmp.push( a );
1720 }
1721
1722 r = tmp;
1723
1724 // We can get a speed boost by handling nth-child here
1725 } else if ( m[1] == ":" && m[2] == "nth-child" ) {
1726 var merge = {}, tmp = [],
1727 // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
1728 test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
1729 m[3] == "even" && "2n" || m[3] == "odd" && "2n+1" ||
1730 !/\D/.test(m[3]) && "0n+" + m[3] || m[3]),
1731 // calculate the numbers (first)n+(last) including if they are negative
1732 first = (test[1] + (test[2] || 1)) - 0, last = test[3] - 0;
1733
1734 // loop through all the elements left in the jQuery object
1735 for ( var i = 0, rl = r.length; i < rl; i++ ) {
1736 var node = r[i], parentNode = node.parentNode, id = jQuery.data(parentNode);
1737
1738 if ( !merge[id] ) {
1739 var c = 1;
1740
1741 for ( var n = parentNode.firstChild; n; n = n.nextSibling )
1742 if ( n.nodeType == 1 )
1743 n.nodeIndex = c++;
1744
1745 merge[id] = true;
1746 }
1747
1748 var add = false;
1749
1750 if ( first == 0 ) {
1751 if ( node.nodeIndex == last )
1752 add = true;
1753 } else if ( (node.nodeIndex - last) % first == 0 && (node.nodeIndex - last) / first >= 0 )
1754 add = true;
1755
1756 if ( add ^ not )
1757 tmp.push( node );
1758 }
1759
1760 r = tmp;
1761
1762 // Otherwise, find the expression to execute
1763 } else {
1764 var fn = jQuery.expr[ m[1] ];
1765 if ( typeof fn == "object" )
1766 fn = fn[ m[2] ];
1767
1768 if ( typeof fn == "string" )
1769 fn = eval("false||function(a,i){return " + fn + ";}");
1770
1771 // Execute it against the current filter
1772 r = jQuery.grep( r, function(elem, i){
1773 return fn(elem, i, m, r);
1774 }, not );
1775 }
1776 }
1777
1778 // Return an array of filtered elements (r)
1779 // and the modified expression string (t)
1780 return { r: r, t: t };
1781 },
1782
1783 dir: function( elem, dir ){
1784 var matched = [],
1785 cur = elem[dir];
1786 while ( cur && cur != document ) {
1787 if ( cur.nodeType == 1 )
1788 matched.push( cur );
1789 cur = cur[dir];
1790 }
1791 return matched;
1792 },
1793
1794 nth: function(cur,result,dir,elem){
1795 result = result || 1;
1796 var num = 0;
1797
1798 for ( ; cur; cur = cur[dir] )
1799 if ( cur.nodeType == 1 && ++num == result )
1800 break;
1801
1802 return cur;
1803 },
1804
1805 sibling: function( n, elem ) {
1806 var r = [];
1807
1808 for ( ; n; n = n.nextSibling ) {
1809 if ( n.nodeType == 1 && n != elem )
1810 r.push( n );
1811 }
1812
1813 return r;
1814 }
1815 });
1816 /*
1817 * A number of helper functions used for managing events.
1818 * Many of the ideas behind this code orignated from
1819 * Dean Edwards' addEvent library.
1820 */
1821
1822 jQuery.event = {
1823
1824 // Bind an event to an element
1825 // Original by Dean Edwards
1826 add: function(elem, types, handler, data) {
1827 if ( elem.nodeType == 3 || elem.nodeType == 8 )
1828 return;
1829
1830 // For whatever reason, IE has trouble passing the window object
1831 // around, causing it to be cloned in the process
1832 if ( jQuery.browser.msie && elem.setInterval )
1833 elem = window;
1834
1835 // Make sure that the function being executed has a unique ID
1836 if ( !handler.guid )
1837 handler.guid = this.guid++;
1838
1839 // if data is passed, bind to handler
1840 if( data != undefined ) {
1841 // Create temporary function pointer to original handler
1842 var fn = handler;
1843
1844 // Create unique handler function, wrapped around original handler
1845 handler = this.proxy( fn, function() {
1846 // Pass arguments and context to original handler
1847 return fn.apply(this, arguments);
1848 });
1849
1850 // Store data in unique handler
1851 handler.data = data;
1852 }
1853
1854 // Init the element's event structure
1855 var events = jQuery.data(elem, "events") || jQuery.data(elem, "events", {}),
1856 handle = jQuery.data(elem, "handle") || jQuery.data(elem, "handle", function(){
1857 // Handle the second event of a trigger and when
1858 // an event is called after a page has unloaded
1859 if ( typeof jQuery != "undefined" && !jQuery.event.triggered )
1860 return jQuery.event.handle.apply(arguments.callee.elem, arguments);
1861 });
1862 // Add elem as a property of the handle function
1863 // This is to prevent a memory leak with non-native
1864 // event in IE.
1865 handle.elem = elem;
1866
1867 // Handle multiple events separated by a space
1868 // jQuery(...).bind("mouseover mouseout", fn);
1869 jQuery.each(types.split(/\s+/), function(index, type) {
1870 // Namespaced event handlers
1871 var parts = type.split(".");
1872 type = parts[0];
1873 handler.type = parts[1];
1874
1875 // Get the current list of functions bound to this event
1876 var handlers = events[type];
1877
1878 // Init the event handler queue
1879 if (!handlers) {
1880 handlers = events[type] = {};
1881
1882 // Check for a special event handler
1883 // Only use addEventListener/attachEvent if the special
1884 // events handler returns false
1885 if ( !jQuery.event.special[type] || jQuery.event.special[type].setup.call(elem) === false ) {
1886 // Bind the global event handler to the element
1887 if (elem.addEventListener)
1888 elem.addEventListener(type, handle, false);
1889 else if (elem.attachEvent)
1890 elem.attachEvent("on" + type, handle);
1891 }
1892 }
1893
1894 // Add the function to the element's handler list
1895 handlers[handler.guid] = handler;
1896
1897 // Keep track of which events have been used, for global triggering
1898 jQuery.event.global[type] = true;
1899 });
1900
1901 // Nullify elem to prevent memory leaks in IE
1902 elem = null;
1903 },
1904
1905 guid: 1,
1906 global: {},
1907
1908 // Detach an event or set of events from an element
1909 remove: function(elem, types, handler) {
1910 // don't do events on text and comment nodes
1911 if ( elem.nodeType == 3 || elem.nodeType == 8 )
1912 return;
1913
1914 var events = jQuery.data(elem, "events"), ret, index;
1915
1916 if ( events ) {
1917 // Unbind all events for the element
1918 if ( types == undefined || (typeof types == "string" && types.charAt(0) == ".") )
1919 for ( var type in events )
1920 this.remove( elem, type + (types || "") );
1921 else {
1922 // types is actually an event object here
1923 if ( types.type ) {
1924 handler = types.handler;
1925 types = types.type;
1926 }
1927
1928 // Handle multiple events seperated by a space
1929 // jQuery(...).unbind("mouseover mouseout", fn);
1930 jQuery.each(types.split(/\s+/), function(index, type){
1931 // Namespaced event handlers
1932 var parts = type.split(".");
1933 type = parts[0];
1934
1935 if ( events[type] ) {
1936 // remove the given handler for the given type
1937 if ( handler )
1938 delete events[type][handler.guid];
1939
1940 // remove all handlers for the given type
1941 else
1942 for ( handler in events[type] )
1943 // Handle the removal of namespaced events
1944 if ( !parts[1] || events[type][handler].type == parts[1] )
1945 delete events[type][handler];
1946
1947 // remove generic event handler if no more handlers exist
1948 for ( ret in events[type] ) break;
1949 if ( !ret ) {
1950 if ( !jQuery.event.special[type] || jQuery.event.special[type].teardown.call(elem) === false ) {
1951 if (elem.removeEventListener)
1952 elem.removeEventListener(type, jQuery.data(elem, "handle"), false);
1953 else if (elem.detachEvent)
1954 elem.detachEvent("on" + type, jQuery.data(elem, "handle"));
1955 }
1956 ret = null;
1957 delete events[type];
1958 }
1959 }
1960 });
1961 }
1962
1963 // Remove the expando if it's no longer used
1964 for ( ret in events ) break;
1965 if ( !ret ) {
1966 var handle = jQuery.data( elem, "handle" );
1967 if ( handle ) handle.elem = null;
1968 jQuery.removeData( elem, "events" );
1969 jQuery.removeData( elem, "handle" );
1970 }
1971 }
1972 },
1973
1974 trigger: function(type, data, elem, donative, extra) {
1975 // Clone the incoming data, if any
1976 data = jQuery.makeArray(data);
1977
1978 if ( type.indexOf("!") >= 0 ) {
1979 type = type.slice(0, -1);
1980 var exclusive = true;
1981 }
1982
1983 // Handle a global trigger
1984 if ( !elem ) {
1985 // Only trigger if we've ever bound an event for it
1986 if ( this.global[type] )
1987 jQuery("*").add([window, document]).trigger(type, data);
1988
1989 // Handle triggering a single element
1990 } else {
1991 // don't do events on text and comment nodes
1992 if ( elem.nodeType == 3 || elem.nodeType == 8 )
1993 return undefined;
1994
1995 var val, ret, fn = jQuery.isFunction( elem[ type ] || null ),
1996 // Check to see if we need to provide a fake event, or not
1997 event = !data[0] || !data[0].preventDefault;
1998
1999 // Pass along a fake event
2000 if ( event ) {
2001 data.unshift({
2002 type: type,
2003 target: elem,
2004 preventDefault: function(){},
2005 stopPropagation: function(){},
2006 timeStamp: now()
2007 });
2008 data[0][expando] = true; // no need to fix fake event
2009 }
2010
2011 // Enforce the right trigger type
2012 data[0].type = type;
2013 if ( exclusive )
2014 data[0].exclusive = true;
2015
2016 // Trigger the event, it is assumed that "handle" is a function
2017 var handle = jQuery.data(elem, "handle");
2018 if ( handle )
2019 val = handle.apply( elem, data );
2020
2021 // Handle triggering native .onfoo handlers (and on links since we don't call .click() for links)
2022 if ( (!fn || (jQuery.nodeName(elem, 'a') && type == "click")) && elem["on"+type] && elem["on"+type].apply( elem, data ) === false )
2023 val = false;
2024
2025 // Extra functions don't get the custom event object
2026 if ( event )
2027 data.shift();
2028
2029 // Handle triggering of extra function
2030 if ( extra && jQuery.isFunction( extra ) ) {
2031 // call the extra function and tack the current return value on the end for possible inspection
2032 ret = extra.apply( elem, val == null ? data : data.concat( val ) );
2033 // if anything is returned, give it precedence and have it overwrite the previous value
2034 if (ret !== undefined)
2035 val = ret;
2036 }
2037
2038 // Trigger the native events (except for clicks on links)
2039 if ( fn && donative !== false && val !== false && !(jQuery.nodeName(elem, 'a') && type == "click") ) {
2040 this.triggered = true;
2041 try {
2042 elem[ type ]();
2043 // prevent IE from throwing an error for some hidden elements
2044 } catch (e) {}
2045 }
2046
2047 this.triggered = false;
2048 }
2049
2050 return val;
2051 },
2052
2053 handle: function(event) {
2054 // returned undefined or false
2055 var val, ret, namespace, all, handlers;
2056
2057 event = arguments[0] = jQuery.event.fix( event || window.event );
2058
2059 // Namespaced event handlers
2060 namespace = event.type.split(".");
2061 event.type = namespace[0];
2062 namespace = namespace[1];
2063 // Cache this now, all = true means, any handler
2064 all = !namespace && !event.exclusive;
2065
2066 handlers = ( jQuery.data(this, "events") || {} )[event.type];
2067
2068 for ( var j in handlers ) {
2069 var handler = handlers[j];
2070
2071 // Filter the functions by class
2072 if ( all || handler.type == namespace ) {
2073 // Pass in a reference to the handler function itself
2074 // So that we can later remove it
2075 event.handler = handler;
2076 event.data = handler.data;
2077
2078 ret = handler.apply( this, arguments );
2079
2080 if ( val !== false )
2081 val = ret;
2082
2083 if ( ret === false ) {
2084 event.preventDefault();
2085 event.stopPropagation();
2086 }
2087 }
2088 }
2089
2090 return val;
2091 },
2092
2093 fix: function(event) {
2094 if ( event[expando] == true )
2095 return event;
2096
2097 // store a copy of the original event object
2098 // and "clone" to set read-only properties
2099 var originalEvent = event;
2100 event = { originalEvent: originalEvent };
2101 var 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 timeStamp toElement type view wheelDelta which".split(" ");
2102 for ( var i=props.length; i; i-- )
2103 event[ props[i] ] = originalEvent[ props[i] ];
2104
2105 // Mark it as fixed
2106 event[expando] = true;
2107
2108 // add preventDefault and stopPropagation since
2109 // they will not work on the clone
2110 event.preventDefault = function() {
2111 // if preventDefault exists run it on the original event
2112 if (originalEvent.preventDefault)
2113 originalEvent.preventDefault();
2114 // otherwise set the returnValue property of the original event to false (IE)
2115 originalEvent.returnValue = false;
2116 };
2117 event.stopPropagation = function() {
2118 // if stopPropagation exists run it on the original event
2119 if (originalEvent.stopPropagation)
2120 originalEvent.stopPropagation();
2121 // otherwise set the cancelBubble property of the original event to true (IE)
2122 originalEvent.cancelBubble = true;
2123 };
2124
2125 // Fix timeStamp
2126 event.timeStamp = event.timeStamp || now();
2127
2128 // Fix target property, if necessary
2129 if ( !event.target )
2130 event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
2131
2132 // check if target is a textnode (safari)
2133 if ( event.target.nodeType == 3 )
2134 event.target = event.target.parentNode;
2135
2136 // Add relatedTarget, if necessary
2137 if ( !event.relatedTarget && event.fromElement )
2138 event.relatedTarget = event.fromElement == event.target ? event.toElement : event.fromElement;
2139
2140 // Calculate pageX/Y if missing and clientX/Y available
2141 if ( event.pageX == null && event.clientX != null ) {
2142 var doc = document.documentElement, body = document.body;
2143 event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc.clientLeft || 0);
2144 event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc.clientTop || 0);
2145 }
2146
2147 // Add which for key events
2148 if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) )
2149 event.which = event.charCode || event.keyCode;
2150
2151 // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
2152 if ( !event.metaKey && event.ctrlKey )
2153 event.metaKey = event.ctrlKey;
2154
2155 // Add which for click: 1 == left; 2 == middle; 3 == right
2156 // Note: button is not normalized, so don't use it
2157 if ( !event.which && event.button )
2158 event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
2159
2160 return event;
2161 },
2162
2163 proxy: function( fn, proxy ){
2164 // Set the guid of unique handler to the same of original handler, so it can be removed
2165 proxy.guid = fn.guid = fn.guid || proxy.guid || this.guid++;
2166 // So proxy can be declared as an argument
2167 return proxy;
2168 },
2169
2170 special: {
2171 ready: {
2172 setup: function() {
2173 // Make sure the ready event is setup
2174 bindReady();
2175 return;
2176 },
2177
2178 teardown: function() { return; }
2179 },
2180
2181 mouseenter: {
2182 setup: function() {
2183 if ( jQuery.browser.msie ) return false;
2184 jQuery(this).bind("mouseover", jQuery.event.special.mouseenter.handler);
2185 return true;
2186 },
2187
2188 teardown: function() {
2189 if ( jQuery.browser.msie ) return false;
2190 jQuery(this).unbind("mouseover", jQuery.event.special.mouseenter.handler);
2191 return true;
2192 },
2193
2194 handler: function(event) {
2195 // If we actually just moused on to a sub-element, ignore it
2196 if ( withinElement(event, this) ) return true;
2197 // Execute the right handlers by setting the event type to mouseenter
2198 event.type = "mouseenter";
2199 return jQuery.event.handle.apply(this, arguments);
2200 }
2201 },
2202
2203 mouseleave: {
2204 setup: function() {
2205 if ( jQuery.browser.msie ) return false;
2206 jQuery(this).bind("mouseout", jQuery.event.special.mouseleave.handler);
2207 return true;
2208 },
2209
2210 teardown: function() {
2211 if ( jQuery.browser.msie ) return false;
2212 jQuery(this).unbind("mouseout", jQuery.event.special.mouseleave.handler);
2213 return true;
2214 },
2215
2216 handler: function(event) {
2217 // If we actually just moused on to a sub-element, ignore it
2218 if ( withinElement(event, this) ) return true;
2219 // Execute the right handlers by setting the event type to mouseleave
2220 event.type = "mouseleave";
2221 return jQuery.event.handle.apply(this, arguments);
2222 }
2223 }
2224 }
2225 };
2226
2227 jQuery.fn.extend({
2228 bind: function( type, data, fn ) {
2229 return type == "unload" ? this.one(type, data, fn) : this.each(function(){
2230 jQuery.event.add( this, type, fn || data, fn && data );
2231 });
2232 },
2233
2234 one: function( type, data, fn ) {
2235 var one = jQuery.event.proxy( fn || data, function(event) {
2236 jQuery(this).unbind(event, one);
2237 return (fn || data).apply( this, arguments );
2238 });
2239 return this.each(function(){
2240 jQuery.event.add( this, type, one, fn && data);
2241 });
2242 },
2243
2244 unbind: function( type, fn ) {
2245 return this.each(function(){
2246 jQuery.event.remove( this, type, fn );
2247 });
2248 },
2249
2250 trigger: function( type, data, fn ) {
2251 return this.each(function(){
2252 jQuery.event.trigger( type, data, this, true, fn );
2253 });
2254 },
2255
2256 triggerHandler: function( type, data, fn ) {
2257 return this[0] && jQuery.event.trigger( type, data, this[0], false, fn );
2258 },
2259
2260 toggle: function( fn ) {
2261 // Save reference to arguments for access in closure
2262 var args = arguments, i = 1;
2263
2264 // link all the functions, so any of them can unbind this click handler
2265 while( i < args.length )
2266 jQuery.event.proxy( fn, args[i++] );
2267
2268 return this.click( jQuery.event.proxy( fn, function(event) {
2269 // Figure out which function to execute
2270 this.lastToggle = ( this.lastToggle || 0 ) % i;
2271
2272 // Make sure that clicks stop
2273 event.preventDefault();
2274
2275 // and execute the function
2276 return args[ this.lastToggle++ ].apply( this, arguments ) || false;
2277 }));
2278 },
2279
2280 hover: function(fnOver, fnOut) {
2281 return this.bind('mouseenter', fnOver).bind('mouseleave', fnOut);
2282 },
2283
2284 ready: function(fn) {
2285 // Attach the listeners
2286 bindReady();
2287
2288 // If the DOM is already ready
2289 if ( jQuery.isReady )
2290 // Execute the function immediately
2291 fn.call( document, jQuery );
2292
2293 // Otherwise, remember the function for later
2294 else
2295 // Add the function to the wait list
2296 jQuery.readyList.push( function() { return fn.call(this, jQuery); } );
2297
2298 return this;
2299 }
2300 });
2301
2302 jQuery.extend({
2303 isReady: false,
2304 readyList: [],
2305 // Handle when the DOM is ready
2306 ready: function() {
2307 // Make sure that the DOM is not already loaded
2308 if ( !jQuery.isReady ) {
2309 // Remember that the DOM is ready
2310 jQuery.isReady = true;
2311
2312 // If there are functions bound, to execute
2313 if ( jQuery.readyList ) {
2314 // Execute all of them
2315 jQuery.each( jQuery.readyList, function(){
2316 this.call( document );
2317 });
2318
2319 // Reset the list of functions
2320 jQuery.readyList = null;
2321 }
2322
2323 // Trigger any bound ready events
2324 jQuery(document).triggerHandler("ready");
2325 }
2326 }
2327 });
2328
2329 var readyBound = false;
2330
2331 function bindReady(){
2332 if ( readyBound ) return;
2333 readyBound = true;
2334
2335 // Mozilla, Opera (see further below for it) and webkit nightlies currently support this event
2336 if ( document.addEventListener && !jQuery.browser.opera)
2337 // Use the handy event callback
2338 document.addEventListener( "DOMContentLoaded", jQuery.ready, false );
2339
2340 // If IE is used and is not in a frame
2341 // Continually check to see if the document is ready
2342 if ( jQuery.browser.msie && window == top ) (function(){
2343 if (jQuery.isReady) return;
2344 try {
2345 // If IE is used, use the trick by Diego Perini
2346 // http://javascript.nwbox.com/IEContentLoaded/
2347 document.documentElement.doScroll("left");
2348 } catch( error ) {
2349 setTimeout( arguments.callee, 0 );
2350 return;
2351 }
2352 // and execute any waiting functions
2353 jQuery.ready();
2354 })();
2355
2356 if ( jQuery.browser.opera )
2357 document.addEventListener( "DOMContentLoaded", function () {
2358 if (jQuery.isReady) return;
2359 for (var i = 0; i < document.styleSheets.length; i++)
2360 if (document.styleSheets[i].disabled) {
2361 setTimeout( arguments.callee, 0 );
2362 return;
2363 }
2364 // and execute any waiting functions
2365 jQuery.ready();
2366 }, false);
2367
2368 if ( jQuery.browser.safari ) {
2369 var numStyles;
2370 (function(){
2371 if (jQuery.isReady) return;
2372 if ( document.readyState != "loaded" && document.readyState != "complete" ) {
2373 setTimeout( arguments.callee, 0 );
2374 return;
2375 }
2376 if ( numStyles === undefined )
2377 numStyles = jQuery("style, link[rel=stylesheet]").length;
2378 if ( document.styleSheets.length != numStyles ) {
2379 setTimeout( arguments.callee, 0 );
2380 return;
2381 }
2382 // and execute any waiting functions
2383 jQuery.ready();
2384 })();
2385 }
2386
2387 // A fallback to window.onload, that will always work
2388 jQuery.event.add( window, "load", jQuery.ready );
2389 }
2390
2391 jQuery.each( ("blur,focus,load,resize,scroll,unload,click,dblclick," +
2392 "mousedown,mouseup,mousemove,mouseover,mouseout,change,select," +
2393 "submit,keydown,keypress,keyup,error").split(","), function(i, name){
2394
2395 // Handle event binding
2396 jQuery.fn[name] = function(fn){
2397 return fn ? this.bind(name, fn) : this.trigger(name);
2398 };
2399 });
2400
2401 // Checks if an event happened on an element within another element
2402 // Used in jQuery.event.special.mouseenter and mouseleave handlers
2403 var withinElement = function(event, elem) {
2404 // Check if mouse(over|out) are still within the same parent element
2405 var parent = event.relatedTarget;
2406 // Traverse up the tree
2407 while ( parent && parent != elem ) try { parent = parent.parentNode; } catch(error) { parent = elem; }
2408 // Return true if we actually just moused on to a sub-element
2409 return parent == elem;
2410 };
2411
2412 // Prevent memory leaks in IE
2413 // And prevent errors on refresh with events like mouseover in other browsers
2414 // Window isn't included so as not to unbind existing unload events
2415 jQuery(window).bind("unload", function() {
2416 jQuery("*").add(document).unbind();
2417 });
2418 jQuery.fn.extend({
2419 // Keep a copy of the old load
2420 _load: jQuery.fn.load,
2421
2422 load: function( url, params, callback ) {
2423 if ( typeof url != 'string' )
2424 return this._load( url );
2425
2426 var off = url.indexOf(" ");
2427 if ( off >= 0 ) {
2428 var selector = url.slice(off, url.length);
2429 url = url.slice(0, off);
2430 }
2431
2432 callback = callback || function(){};
2433
2434 // Default to a GET request
2435 var type = "GET";
2436
2437 // If the second parameter was provided
2438 if ( params )
2439 // If it's a function
2440 if ( jQuery.isFunction( params ) ) {
2441 // We assume that it's the callback
2442 callback = params;
2443 params = null;
2444
2445 // Otherwise, build a param string
2446 } else {
2447 params = jQuery.param( params );
2448 type = "POST";
2449 }
2450
2451 var self = this;
2452
2453 // Request the remote document
2454 jQuery.ajax({
2455 url: url,
2456 type: type,
2457 dataType: "html",
2458 data: params,
2459 complete: function(res, status){
2460 // If successful, inject the HTML into all the matched elements
2461 if ( status == "success" || status == "notmodified" )
2462 // See if a selector was specified
2463 self.html( selector ?
2464 // Create a dummy div to hold the results
2465 jQuery("<div/>")
2466 // inject the contents of the document in, removing the scripts
2467 // to avoid any 'Permission Denied' errors in IE
2468 .append(res.responseText.replace(/<script(.|\s)*?\/script>/g, ""))
2469
2470 // Locate the specified elements
2471 .find(selector) :
2472
2473 // If not, just inject the full result
2474 res.responseText );
2475
2476 self.each( callback, [res.responseText, status, res] );
2477 }
2478 });
2479 return this;
2480 },
2481
2482 serialize: function() {
2483 return jQuery.param(this.serializeArray());
2484 },
2485 serializeArray: function() {
2486 return this.map(function(){
2487 return jQuery.nodeName(this, "form") ?
2488 jQuery.makeArray(this.elements) : this;
2489 })
2490 .filter(function(){
2491 return this.name && !this.disabled &&
2492 (this.checked || /select|textarea/i.test(this.nodeName) ||
2493 /text|hidden|password/i.test(this.type));
2494 })
2495 .map(function(i, elem){
2496 var val = jQuery(this).val();
2497 return val == null ? null :
2498 val.constructor == Array ?
2499 jQuery.map( val, function(val, i){
2500 return {name: elem.name, value: val};
2501 }) :
2502 {name: elem.name, value: val};
2503 }).get();
2504 }
2505 });
2506
2507 // Attach a bunch of functions for handling common AJAX events
2508 jQuery.each( "ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","), function(i,o){
2509 jQuery.fn[o] = function(f){
2510 return this.bind(o, f);
2511 };
2512 });
2513
2514 var jsc = now();
2515
2516 jQuery.extend({
2517 get: function( url, data, callback, type ) {
2518 // shift arguments if data argument was ommited
2519 if ( jQuery.isFunction( data ) ) {
2520 callback = data;
2521 data = null;
2522 }
2523
2524 return jQuery.ajax({
2525 type: "GET",
2526 url: url,
2527 data: data,
2528 success: callback,
2529 dataType: type
2530 });
2531 },
2532
2533 getScript: function( url, callback ) {
2534 return jQuery.get(url, null, callback, "script");
2535 },
2536
2537 getJSON: function( url, data, callback ) {
2538 return jQuery.get(url, data, callback, "json");
2539 },
2540
2541 post: function( url, data, callback, type ) {
2542 if ( jQuery.isFunction( data ) ) {
2543 callback = data;
2544 data = {};
2545 }
2546
2547 return jQuery.ajax({
2548 type: "POST",
2549 url: url,
2550 data: data,
2551 success: callback,
2552 dataType: type
2553 });
2554 },
2555
2556 ajaxSetup: function( settings ) {
2557 jQuery.extend( jQuery.ajaxSettings, settings );
2558 },
2559
2560 ajaxSettings: {
2561 url: location.href,
2562 global: true,
2563 type: "GET",
2564 timeout: 0,
2565 contentType: "application/x-www-form-urlencoded",
2566 processData: true,
2567 async: true,
2568 data: null,
2569 username: null,
2570 password: null,
2571 accepts: {
2572 xml: "application/xml, text/xml",
2573 html: "text/html",
2574 script: "text/javascript, application/javascript",
2575 json: "application/json, text/javascript",
2576 text: "text/plain",
2577 _default: "*/*"
2578 }
2579 },
2580
2581 // Last-Modified header cache for next request
2582 lastModified: {},
2583
2584 ajax: function( s ) {
2585 // Extend the settings, but re-extend 's' so that it can be
2586 // checked again later (in the test suite, specifically)
2587 s = jQuery.extend(true, s, jQuery.extend(true, {}, jQuery.ajaxSettings, s));
2588
2589 var jsonp, jsre = /=\?(&|$)/g, status, data,
2590 type = s.type.toUpperCase();
2591
2592 // convert data if not already a string
2593 if ( s.data && s.processData && typeof s.data != "string" )
2594 s.data = jQuery.param(s.data);
2595
2596 // Handle JSONP Parameter Callbacks
2597 if ( s.dataType == "jsonp" ) {
2598 if ( type == "GET" ) {
2599 if ( !s.url.match(jsre) )
2600 s.url += (s.url.match(/\?/) ? "&" : "?") + (s.jsonp || "callback") + "=?";
2601 } else if ( !s.data || !s.data.match(jsre) )
2602 s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
2603 s.dataType = "json";
2604 }
2605
2606 // Build temporary JSONP function
2607 if ( s.dataType == "json" && (s.data && s.data.match(jsre) || s.url.match(jsre)) ) {
2608 jsonp = "jsonp" + jsc++;
2609
2610 // Replace the =? sequence both in the query string and the data
2611 if ( s.data )
2612 s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");
2613 s.url = s.url.replace(jsre, "=" + jsonp + "$1");
2614
2615 // We need to make sure
2616 // that a JSONP style response is executed properly
2617 s.dataType = "script";
2618
2619 // Handle JSONP-style loading
2620 window[ jsonp ] = function(tmp){
2621 data = tmp;
2622 success();
2623 complete();
2624 // Garbage collect
2625 window[ jsonp ] = undefined;
2626 try{ delete window[ jsonp ]; } catch(e){}
2627 if ( head )
2628 head.removeChild( script );
2629 };
2630 }
2631
2632 if ( s.dataType == "script" && s.cache == null )
2633 s.cache = false;
2634
2635 if ( s.cache === false && type == "GET" ) {
2636 var ts = now();
2637 // try replacing _= if it is there
2638 var ret = s.url.replace(/(\?|&)_=.*?(&|$)/, "$1_=" + ts + "$2");
2639 // if nothing was replaced, add timestamp to the end
2640 s.url = ret + ((ret == s.url) ? (s.url.match(/\?/) ? "&" : "?") + "_=" + ts : "");
2641 }
2642
2643 // If data is available, append data to url for get requests
2644 if ( s.data && type == "GET" ) {
2645 s.url += (s.url.match(/\?/) ? "&" : "?") + s.data;
2646
2647 // IE likes to send both get and post data, prevent this
2648 s.data = null;
2649 }
2650
2651 // Watch for a new set of requests
2652 if ( s.global && ! jQuery.active++ )
2653 jQuery.event.trigger( "ajaxStart" );
2654
2655 // Matches an absolute URL, and saves the domain
2656 var remote = /^(?:\w+:)?\/\/([^\/?#]+)/;
2657
2658 // If we're requesting a remote document
2659 // and trying to load JSON or Script with a GET
2660 if ( s.dataType == "script" && type == "GET"
2661 && remote.test(s.url) && remote.exec(s.url)[1] != location.host ){
2662 var head = document.getElementsByTagName("head")[0];
2663 var script = document.createElement("script");
2664 script.src = s.url;
2665 if (s.scriptCharset)
2666 script.charset = s.scriptCharset;
2667
2668 // Handle Script loading
2669 if ( !jsonp ) {
2670 var done = false;
2671
2672 // Attach handlers for all browsers
2673 script.onload = script.onreadystatechange = function(){
2674 if ( !done && (!this.readyState ||
2675 this.readyState == "loaded" || this.readyState == "complete") ) {
2676 done = true;
2677 success();
2678 complete();
2679 head.removeChild( script );
2680 }
2681 };
2682 }
2683
2684 head.appendChild(script);
2685
2686 // We handle everything using the script element injection
2687 return undefined;
2688 }
2689
2690 var requestDone = false;
2691
2692 // Create the request object; Microsoft failed to properly
2693 // implement the XMLHttpRequest in IE7, so we use the ActiveXObject when it is available
2694 var xhr = window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
2695
2696 // Open the socket
2697 // Passing null username, generates a login popup on Opera (#2865)
2698 if( s.username )
2699 xhr.open(type, s.url, s.async, s.username, s.password);
2700 else
2701 xhr.open(type, s.url, s.async);
2702
2703 // Need an extra try/catch for cross domain requests in Firefox 3
2704 try {
2705 // Set the correct header, if data is being sent
2706 if ( s.data )
2707 xhr.setRequestHeader("Content-Type", s.contentType);
2708
2709 // Set the If-Modified-Since header, if ifModified mode.
2710 if ( s.ifModified )
2711 xhr.setRequestHeader("If-Modified-Since",
2712 jQuery.lastModified[s.url] || "Thu, 01 Jan 1970 00:00:00 GMT" );
2713
2714 // Set header so the called script knows that it's an XMLHttpRequest
2715 xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
2716
2717 // Set the Accepts header for the server, depending on the dataType
2718 xhr.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ?
2719 s.accepts[ s.dataType ] + ", */*" :
2720 s.accepts._default );
2721 } catch(e){}
2722
2723 // Allow custom headers/mimetypes
2724 if ( s.beforeSend && s.beforeSend(xhr, s) === false ) {
2725 // cleanup active request counter
2726 s.global && jQuery.active--;
2727 // close opended socket
2728 xhr.abort();
2729 return false;
2730 }
2731
2732 if ( s.global )
2733 jQuery.event.trigger("ajaxSend", [xhr, s]);
2734
2735 // Wait for a response to come back
2736 var onreadystatechange = function(isTimeout){
2737 // The transfer is complete and the data is available, or the request timed out
2738 if ( !requestDone && xhr && (xhr.readyState == 4 || isTimeout == "timeout") ) {
2739 requestDone = true;
2740
2741 // clear poll interval
2742 if (ival) {
2743 clearInterval(ival);
2744 ival = null;
2745 }
2746
2747 status = isTimeout == "timeout" && "timeout" ||
2748 !jQuery.httpSuccess( xhr ) && "error" ||
2749 s.ifModified && jQuery.httpNotModified( xhr, s.url ) && "notmodified" ||
2750 "success";
2751
2752 if ( status == "success" ) {
2753 // Watch for, and catch, XML document parse errors
2754 try {
2755 // process the data (runs the xml through httpData regardless of callback)
2756 data = jQuery.httpData( xhr, s.dataType, s.dataFilter );
2757 } catch(e) {
2758 status = "parsererror";
2759 }
2760 }
2761
2762 // Make sure that the request was successful or notmodified
2763 if ( status == "success" ) {
2764 // Cache Last-Modified header, if ifModified mode.
2765 var modRes;
2766 try {
2767 modRes = xhr.getResponseHeader("Last-Modified");
2768 } catch(e) {} // swallow exception thrown by FF if header is not available
2769
2770 if ( s.ifModified && modRes )
2771 jQuery.lastModified[s.url] = modRes;
2772
2773 // JSONP handles its own success callback
2774 if ( !jsonp )
2775 success();
2776 } else
2777 jQuery.handleError(s, xhr, status);
2778
2779 // Fire the complete handlers
2780 complete();
2781
2782 // Stop memory leaks
2783 if ( s.async )
2784 xhr = null;
2785 }
2786 };
2787
2788 if ( s.async ) {
2789 // don't attach the handler to the request, just poll it instead
2790 var ival = setInterval(onreadystatechange, 13);
2791
2792 // Timeout checker
2793 if ( s.timeout > 0 )
2794 setTimeout(function(){
2795 // Check to see if the request is still happening
2796 if ( xhr ) {
2797 // Cancel the request
2798 xhr.abort();
2799
2800 if( !requestDone )
2801 onreadystatechange( "timeout" );
2802 }
2803 }, s.timeout);
2804 }
2805
2806 // Send the data
2807 try {
2808 xhr.send(s.data);
2809 } catch(e) {
2810 jQuery.handleError(s, xhr, null, e);
2811 }
2812
2813 // firefox 1.5 doesn't fire statechange for sync requests
2814 if ( !s.async )
2815 onreadystatechange();
2816
2817 function success(){
2818 // If a local callback was specified, fire it and pass it the data
2819 if ( s.success )
2820 s.success( data, status );
2821
2822 // Fire the global callback
2823 if ( s.global )
2824 jQuery.event.trigger( "ajaxSuccess", [xhr, s] );
2825 }
2826
2827 function complete(){
2828 // Process result
2829 if ( s.complete )
2830 s.complete(xhr, status);
2831
2832 // The request was completed
2833 if ( s.global )
2834 jQuery.event.trigger( "ajaxComplete", [xhr, s] );
2835
2836 // Handle the global AJAX counter
2837 if ( s.global && ! --jQuery.active )
2838 jQuery.event.trigger( "ajaxStop" );
2839 }
2840
2841 // return XMLHttpRequest to allow aborting the request etc.
2842 return xhr;
2843 },
2844
2845 handleError: function( s, xhr, status, e ) {
2846 // If a local callback was specified, fire it
2847 if ( s.error ) s.error( xhr, status, e );
2848
2849 // Fire the global callback
2850 if ( s.global )
2851 jQuery.event.trigger( "ajaxError", [xhr, s, e] );
2852 },
2853
2854 // Counter for holding the number of active queries
2855 active: 0,
2856
2857 // Determines if an XMLHttpRequest was successful or not
2858 httpSuccess: function( xhr ) {
2859 try {
2860 // IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450
2861 return !xhr.status && location.protocol == "file:" ||
2862 ( xhr.status >= 200 && xhr.status < 300 ) || xhr.status == 304 || xhr.status == 1223 ||
2863 jQuery.browser.safari && xhr.status == undefined;
2864 } catch(e){}
2865 return false;
2866 },
2867
2868 // Determines if an XMLHttpRequest returns NotModified
2869 httpNotModified: function( xhr, url ) {
2870 try {
2871 var xhrRes = xhr.getResponseHeader("Last-Modified");
2872
2873 // Firefox always returns 200. check Last-Modified date
2874 return xhr.status == 304 || xhrRes == jQuery.lastModified[url] ||
2875 jQuery.browser.safari && xhr.status == undefined;
2876 } catch(e){}
2877 return false;
2878 },
2879
2880 httpData: function( xhr, type, filter ) {
2881 var ct = xhr.getResponseHeader("content-type"),
2882 xml = type == "xml" || !type && ct && ct.indexOf("xml") >= 0,
2883 data = xml ? xhr.responseXML : xhr.responseText;
2884
2885 if ( xml && data.documentElement.tagName == "parsererror" )
2886 throw "parsererror";
2887
2888 // Allow a pre-filtering function to sanitize the response
2889 if( filter )
2890 data = filter( data, type );
2891
2892 // If the type is "script", eval it in global context
2893 if ( type == "script" )
2894 jQuery.globalEval( data );
2895
2896 // Get the JavaScript object, if JSON is used.
2897 if ( type == "json" )
2898 data = eval("(" + data + ")");
2899
2900 return data;
2901 },
2902
2903 // Serialize an array of form elements or a set of
2904 // key/values into a query string
2905 param: function( a ) {
2906 var s = [];
2907
2908 // If an array was passed in, assume that it is an array
2909 // of form elements
2910 if ( a.constructor == Array || a.jquery )
2911 // Serialize the form elements
2912 jQuery.each( a, function(){
2913 s.push( encodeURIComponent(this.name) + "=" + encodeURIComponent( this.value ) );
2914 });
2915
2916 // Otherwise, assume that it's an object of key/value pairs
2917 else
2918 // Serialize the key/values
2919 for ( var j in a )
2920 // If the value is an array then the key names need to be repeated
2921 if ( a[j] && a[j].constructor == Array )
2922 jQuery.each( a[j], function(){
2923 s.push( encodeURIComponent(j) + "=" + encodeURIComponent( this ) );
2924 });
2925 else
2926 s.push( encodeURIComponent(j) + "=" + encodeURIComponent( jQuery.isFunction(a[j]) ? a[j]() : a[j] ) );
2927
2928 // Return the resulting serialization
2929 return s.join("&").replace(/%20/g, "+");
2930 }
2931
2932 });
2933 jQuery.fn.extend({
2934 show: function(speed,callback){
2935 return speed ?
2936 this.animate({
2937 height: "show", width: "show", opacity: "show"
2938 }, speed, callback) :
2939
2940 this.filter(":hidden").each(function(){
2941 this.style.display = this.oldblock || "";
2942 if ( jQuery.css(this,"display") == "none" ) {
2943 var elem = jQuery("<" + this.tagName + " />").appendTo("body");
2944 this.style.display = elem.css("display");
2945 // handle an edge condition where css is - div { display:none; } or similar
2946 if (this.style.display == "none")
2947 this.style.display = "block";
2948 elem.remove();
2949 }
2950 }).end();
2951 },
2952
2953 hide: function(speed,callback){
2954 return speed ?
2955 this.animate({
2956 height: "hide", width: "hide", opacity: "hide"
2957 }, speed, callback) :
2958
2959 this.filter(":visible").each(function(){
2960 this.oldblock = this.oldblock || jQuery.css(this,"display");
2961 this.style.display = "none";
2962 }).end();
2963 },
2964
2965 // Save the old toggle function
2966 _toggle: jQuery.fn.toggle,
2967
2968 toggle: function( fn, fn2 ){
2969 return jQuery.isFunction(fn) && jQuery.isFunction(fn2) ?
2970 this._toggle.apply( this, arguments ) :
2971 fn ?
2972 this.animate({
2973 height: "toggle", width: "toggle", opacity: "toggle"
2974 }, fn, fn2) :
2975 this.each(function(){
2976 jQuery(this)[ jQuery(this).is(":hidden") ? "show" : "hide" ]();
2977 });
2978 },
2979
2980 slideDown: function(speed,callback){
2981 return this.animate({height: "show"}, speed, callback);
2982 },
2983
2984 slideUp: function(speed,callback){
2985 return this.animate({height: "hide"}, speed, callback);
2986 },
2987
2988 slideToggle: function(speed, callback){
2989 return this.animate({height: "toggle"}, speed, callback);
2990 },
2991
2992 fadeIn: function(speed, callback){
2993 return this.animate({opacity: "show"}, speed, callback);
2994 },
2995
2996 fadeOut: function(speed, callback){
2997 return this.animate({opacity: "hide"}, speed, callback);
2998 },
2999
3000 fadeTo: function(speed,to,callback){
3001 return this.animate({opacity: to}, speed, callback);
3002 },
3003
3004 animate: function( prop, speed, easing, callback ) {
3005 var optall = jQuery.speed(speed, easing, callback);
3006
3007 return this[ optall.queue === false ? "each" : "queue" ](function(){
3008 if ( this.nodeType != 1)
3009 return false;
3010
3011 var opt = jQuery.extend({}, optall), p,
3012 hidden = jQuery(this).is(":hidden"), self = this;
3013
3014 for ( p in prop ) {
3015 if ( prop[p] == "hide" && hidden || prop[p] == "show" && !hidden )
3016 return opt.complete.call(this);
3017
3018 if ( p == "height" || p == "width" ) {
3019 // Store display property
3020 opt.display = jQuery.css(this, "display");
3021
3022 // Make sure that nothing sneaks out
3023 opt.overflow = this.style.overflow;
3024 }
3025 }
3026
3027 if ( opt.overflow != null )
3028 this.style.overflow = "hidden";
3029
3030 opt.curAnim = jQuery.extend({}, prop);
3031
3032 jQuery.each( prop, function(name, val){
3033 var e = new jQuery.fx( self, opt, name );
3034
3035 if ( /toggle|show|hide/.test(val) )
3036 e[ val == "toggle" ? hidden ? "show" : "hide" : val ]( prop );
3037 else {
3038 var parts = val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),
3039 start = e.cur(true) || 0;
3040
3041 if ( parts ) {
3042 var end = parseFloat(parts[2]),
3043 unit = parts[3] || "px";
3044
3045 // We need to compute starting value
3046 if ( unit != "px" ) {
3047 self.style[ name ] = (end || 1) + unit;
3048 start = ((end || 1) / e.cur(true)) * start;
3049 self.style[ name ] = start + unit;
3050 }
3051
3052 // If a +=/-= token was provided, we're doing a relative animation
3053 if ( parts[1] )
3054 end = ((parts[1] == "-=" ? -1 : 1) * end) + start;
3055
3056 e.custom( start, end, unit );
3057 } else
3058 e.custom( start, val, "" );
3059 }
3060 });
3061
3062 // For JS strict compliance
3063 return true;
3064 });
3065 },
3066
3067 queue: function(type, fn){
3068 if ( jQuery.isFunction(type) || ( type && type.constructor == Array )) {
3069 fn = type;
3070 type = "fx";
3071 }
3072
3073 if ( !type || (typeof type == "string" && !fn) )
3074 return queue( this[0], type );
3075
3076 return this.each(function(){
3077 if ( fn.constructor == Array )
3078 queue(this, type, fn);
3079 else {
3080 queue(this, type).push( fn );
3081
3082 if ( queue(this, type).length == 1 )
3083 fn.call(this);
3084 }
3085 });
3086 },
3087
3088 stop: function(clearQueue, gotoEnd){
3089 var timers = jQuery.timers;
3090
3091 if (clearQueue)
3092 this.queue([]);
3093
3094 this.each(function(){
3095 // go in reverse order so anything added to the queue during the loop is ignored
3096 for ( var i = timers.length - 1; i >= 0; i-- )
3097 if ( timers[i].elem == this ) {
3098 if (gotoEnd)
3099 // force the next step to be the last
3100 timers[i](true);
3101 timers.splice(i, 1);
3102 }
3103 });
3104
3105 // start the next in the queue if the last step wasn't forced
3106 if (!gotoEnd)
3107 this.dequeue();
3108
3109 return this;
3110 }
3111
3112 });
3113
3114 var queue = function( elem, type, array ) {
3115 if ( elem ){
3116
3117 type = type || "fx";
3118
3119 var q = jQuery.data( elem, type + "queue" );
3120
3121 if ( !q || array )
3122 q = jQuery.data( elem, type + "queue", jQuery.makeArray(array) );
3123
3124 }
3125 return q;
3126 };
3127
3128 jQuery.fn.dequeue = function(type){
3129 type = type || "fx";
3130
3131 return this.each(function(){
3132 var q = queue(this, type);
3133
3134 q.shift();
3135
3136 if ( q.length )
3137 q[0].call( this );
3138 });
3139 };
3140
3141 jQuery.extend({
3142
3143 speed: function(speed, easing, fn) {
3144 var opt = speed && speed.constructor == Object ? speed : {
3145 complete: fn || !fn && easing ||
3146 jQuery.isFunction( speed ) && speed,
3147 duration: speed,
3148 easing: fn && easing || easing && easing.constructor != Function && easing
3149 };
3150
3151 opt.duration = (opt.duration && opt.duration.constructor == Number ?
3152 opt.duration :
3153 jQuery.fx.speeds[opt.duration]) || jQuery.fx.speeds.def;
3154
3155 // Queueing
3156 opt.old = opt.complete;
3157 opt.complete = function(){
3158 if ( opt.queue !== false )
3159 jQuery(this).dequeue();
3160 if ( jQuery.isFunction( opt.old ) )
3161 opt.old.call( this );
3162 };
3163
3164 return opt;
3165 },
3166
3167 easing: {
3168 linear: function( p, n, firstNum, diff ) {
3169 return firstNum + diff * p;
3170 },
3171 swing: function( p, n, firstNum, diff ) {
3172 return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
3173 }
3174 },
3175
3176 timers: [],
3177 timerId: null,
3178
3179 fx: function( elem, options, prop ){
3180 this.options = options;
3181 this.elem = elem;
3182 this.prop = prop;
3183
3184 if ( !options.orig )
3185 options.orig = {};
3186 }
3187
3188 });
3189
3190 jQuery.fx.prototype = {
3191
3192 // Simple function for setting a style value
3193 update: function(){
3194 if ( this.options.step )
3195 this.options.step.call( this.elem, this.now, this );
3196
3197 (jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );
3198
3199 // Set display property to block for height/width animations
3200 if ( this.prop == "height" || this.prop == "width" )
3201 this.elem.style.display = "block";
3202 },
3203
3204 // Get the current size
3205 cur: function(force){
3206 if ( this.elem[this.prop] != null && this.elem.style[this.prop] == null )
3207 return this.elem[ this.prop ];
3208
3209 var r = parseFloat(jQuery.css(this.elem, this.prop, force));
3210 return r && r > -10000 ? r : parseFloat(jQuery.curCSS(this.elem, this.prop)) || 0;
3211 },
3212
3213 // Start an animation from one number to another
3214 custom: function(from, to, unit){
3215 this.startTime = now();
3216 this.start = from;
3217 this.end = to;
3218 this.unit = unit || this.unit || "px";
3219 this.now = this.start;
3220 this.pos = this.state = 0;
3221 this.update();
3222
3223 var self = this;
3224 function t(gotoEnd){
3225 return self.step(gotoEnd);
3226 }
3227
3228 t.elem = this.elem;
3229
3230 jQuery.timers.push(t);
3231
3232 if ( jQuery.timerId == null ) {
3233 jQuery.timerId = setInterval(function(){
3234 var timers = jQuery.timers;
3235
3236 for ( var i = 0; i < timers.length; i++ )
3237 if ( !timers[i]() )
3238 timers.splice(i--, 1);
3239
3240 if ( !timers.length ) {
3241 clearInterval( jQuery.timerId );
3242 jQuery.timerId = null;
3243 }
3244 }, 13);
3245 }
3246 },
3247
3248 // Simple 'show' function
3249 show: function(){
3250 // Remember where we started, so that we can go back to it later
3251 this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
3252 this.options.show = true;
3253