recherche intelligente de gens
[auf_rh_dae.git] / project / media / jquery-autocomplete / lib / jquery.js
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-27 21:17:26 +0200 (Di, 27 Mai 2008) $
10 * $Rev: 5700 $
11 */
12
13 // Map over jQuery in case of overwrite
14 var _jQuery = window.jQuery,
15 // Map over the $ in case of overwrite
16 _$ = window.$;
17
18 var jQuery = window.jQuery = window.$ = function( selector, context ) {
19 // The jQuery object is actually just the init constructor 'enhanced'
20 return new jQuery.fn.init( selector, context );
21 };
22
23 // A simple way to check for HTML strings or ID strings
24 // (both of which we optimize for)
25 var quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/,
26
27 // Is it a simple selector
28 isSimple = /^.[^:#\[\.]*$/,
29
30 // Will speed up references to undefined, and allows munging its name.
31 undefined;
32
33 jQuery.fn = jQuery.prototype = {
34 init: function( selector, context ) {
35 // Make sure that a selection was provided
36 selector = selector || document;
37
38 // Handle $(DOMElement)
39 if ( selector.nodeType ) {
40 this[0] = selector;
41 this.length = 1;
42 return this;
43 }
44 // Handle HTML strings
45 if ( typeof selector == "string" ) {
46 // Are we dealing with HTML string or an ID?
47 var match = quickExpr.exec( selector );
48
49 // Verify a match, and that no context was specified for #id
50 if ( match && (match[1] || !context) ) {
51
52 // HANDLE: $(html) -> $(array)
53 if ( match[1] )
54 selector = jQuery.clean( [ match[1] ], context );
55
56 // HANDLE: $("#id")
57 else {
58 var elem = document.getElementById( match[3] );
59
60 // Make sure an element was located
61 if ( elem ){
62 // Handle the case where IE and Opera return items
63 // by name instead of ID
64 if ( elem.id != match[3] )
65 return jQuery().find( selector );
66
67 // Otherwise, we inject the element directly into the jQuery object
68 return jQuery( elem );
69 }
70 selector = [];
71 }
72
73 // HANDLE: $(expr, [context])
74 // (which is just equivalent to: $(content).find(expr)
75 } else
76 return jQuery( context ).find( selector );
77
78 // HANDLE: $(function)
79 // Shortcut for document ready
80 } else if ( jQuery.isFunction( selector ) )
81 return jQuery( document )[ jQuery.fn.ready ? "ready" : "load" ]( selector );
82
83 return this.setArray(jQuery.makeArray(selector));
84 },
85
86 // The current version of jQuery being used
87 jquery: "1.2.6",
88
89 // The number of elements contained in the matched element set
90 size: function() {
91 return this.length;
92 },
93
94 // The number of elements contained in the matched element set
95 length: 0,
96
97 // Get the Nth element in the matched element set OR
98 // Get the whole matched element set as a clean array
99 get: function( num ) {
100 return num == undefined ?
101
102 // Return a 'clean' array
103 jQuery.makeArray( this ) :
104
105 // Return just the object
106 this[ num ];
107 },
108
109 // Take an array of elements and push it onto the stack
110 // (returning the new matched element set)
111 pushStack: function( elems ) {
112 // Build a new jQuery matched element set
113 var ret = jQuery( elems );
114
115 // Add the old object onto the stack (as a reference)
116 ret.prevObject = this;
117
118 // Return the newly-formed element set
119 return ret;
120 },
121
122 // Force the current matched set of elements to become
123 // the specified array of elements (destroying the stack in the process)
124 // You should use pushStack() in order to do this, but maintain the stack
125 setArray: function( elems ) {
126 // Resetting the length to 0, then using the native Array push
127 // is a super-fast way to populate an object with array-like properties
128 this.length = 0;
129 Array.prototype.push.apply( this, elems );
130
131 return this;
132 },
133
134 // Execute a callback for every element in the matched set.
135 // (You can seed the arguments with an array of args, but this is
136 // only used internally.)
137 each: function( callback, args ) {
138 return jQuery.each( this, callback, args );
139 },
140
141 // Determine the position of an element within
142 // the matched set of elements
143 index: function( elem ) {
144 var ret = -1;
145
146 // Locate the position of the desired element
147 return jQuery.inArray(
148 // If it receives a jQuery object, the first element is used
149 elem && elem.jquery ? elem[0] : elem
150 , this );
151 },
152
153 attr: function( name, value, type ) {
154 var options = name;
155
156 // Look for the case where we're accessing a style value
157 if ( name.constructor == String )
158 if ( value === undefined )
159 return this[0] && jQuery[ type || "attr" ]( this[0], name );
160
161 else {
162 options = {};
163 options[ name ] = value;
164 }
165
166 // Check to see if we're setting style values
167 return this.each(function(i){
168 // Set all the styles
169 for ( name in options )
170 jQuery.attr(
171 type ?
172 this.style :
173 this,
174 name, jQuery.prop( this, options[ name ], type, i, name )
175 );
176 });
177 },
178
179 css: function( key, value ) {
180 // ignore negative width and height values
181 if ( (key == 'width' || key == 'height') && parseFloat(value) < 0 )
182 value = undefined;
183 return this.attr( key, value, "curCSS" );
184 },
185
186 text: function( text ) {
187 if ( typeof text != "object" && text != null )
188 return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
189
190 var ret = "";
191
192 jQuery.each( text || this, function(){
193 jQuery.each( this.childNodes, function(){
194 if ( this.nodeType != 8 )
195 ret += this.nodeType != 1 ?
196 this.nodeValue :
197 jQuery.fn.text( [ this ] );
198 });
199 });
200
201 return ret;
202 },
203
204 wrapAll: function( html ) {
205 if ( this[0] )
206 // The elements to wrap the target around
207 jQuery( html, this[0].ownerDocument )
208 .clone()
209 .insertBefore( this[0] )
210 .map(function(){
211 var elem = this;
212
213 while ( elem.firstChild )
214 elem = elem.firstChild;
215
216 return elem;
217 })
218 .append(this);
219
220 return this;
221 },
222
223 wrapInner: function( html ) {
224 return this.each(function(){
225 jQuery( this ).contents().wrapAll( html );
226 });
227 },
228
229 wrap: function( html ) {
230 return this.each(function(){
231 jQuery( this ).wrapAll( html );
232 });
233 },
234
235 append: function() {
236 return this.domManip(arguments, true, false, function(elem){
237 if (this.nodeType == 1)
238 this.appendChild( elem );
239 });
240 },
241
242 prepend: function() {
243 return this.domManip(arguments, true, true, function(elem){
244 if (this.nodeType == 1)
245 this.insertBefore( elem, this.firstChild );
246 });
247 },
248
249 before: function() {
250 return this.domManip(arguments, false, false, function(elem){
251 this.parentNode.insertBefore( elem, this );
252 });
253 },
254
255 after: function() {
256 return this.domManip(arguments, false, true, function(elem){
257 this.parentNode.insertBefore( elem, this.nextSibling );
258 });
259 },
260
261 end: function() {
262 return this.prevObject || jQuery( [] );
263 },
264
265 find: function( selector ) {
266 var elems = jQuery.map(this, function(elem){
267 return jQuery.find( selector, elem );
268 });
269
270 return this.pushStack( /[^+>] [^+>]/.test( selector ) || selector.indexOf("..") > -1 ?
271 jQuery.unique( elems ) :
272 elems );
273 },
274
275 clone: function( events ) {
276 // Do the clone
277 var ret = this.map(function(){
278 if ( jQuery.browser.msie && !jQuery.isXMLDoc(this) ) {
279 // IE copies events bound via attachEvent when
280 // using cloneNode. Calling detachEvent on the
281 // clone will also remove the events from the orignal
282 // In order to get around this, we use innerHTML.
283 // Unfortunately, this means some modifications to
284 // attributes in IE that are actually only stored
285 // as properties will not be copied (such as the
286 // the name attribute on an input).
287 var clone = this.cloneNode(true),
288 container = document.createElement("div");
289 container.appendChild(clone);
290 return jQuery.clean([container.innerHTML])[0];
291 } else
292 return this.cloneNode(true);
293 });
294
295 // Need to set the expando to null on the cloned set if it exists
296 // removeData doesn't work here, IE removes it from the original as well
297 // this is primarily for IE but the data expando shouldn't be copied over in any browser
298 var clone = ret.find("*").andSelf().each(function(){
299 if ( this[ expando ] != undefined )
300 this[ expando ] = null;
301 });
302
303 // Copy the events from the original to the clone
304 if ( events === true )
305 this.find("*").andSelf().each(function(i){
306 if (this.nodeType == 3)
307 return;
308 var events = jQuery.data( this, "events" );
309
310 for ( var type in events )
311 for ( var handler in events[ type ] )
312 jQuery.event.add( clone[ i ], type, events[ type ][ handler ], events[ type ][ handler ].data );
313 });
314
315 // Return the cloned set
316 return ret;
317 },
318
319 filter: function( selector ) {
320 return this.pushStack(
321 jQuery.isFunction( selector ) &&
322 jQuery.grep(this, function(elem, i){
323 return selector.call( elem, i );
324 }) ||
325
326 jQuery.multiFilter( selector, this ) );
327 },
328
329 not: function( selector ) {
330 if ( selector.constructor == String )
331 // test special case where just one selector is passed in
332 if ( isSimple.test( selector ) )
333 return this.pushStack( jQuery.multiFilter( selector, this, true ) );
334 else
335 selector = jQuery.multiFilter( selector, this );
336
337 var isArrayLike = selector.length && selector[selector.length - 1] !== undefined && !selector.nodeType;
338 return this.filter(function() {
339 return isArrayLike ? jQuery.inArray( this, selector ) < 0 : this != selector;
340 });
341 },
342
343 add: function( selector ) {
344 return this.pushStack( jQuery.unique( jQuery.merge(
345 this.get(),
346 typeof selector == 'string' ?
347 jQuery( selector ) :
348 jQuery.makeArray( selector )
349 )));
350 },
351
352 is: function( selector ) {
353 return !!selector && jQuery.multiFilter( selector, this ).length > 0;
354 },
355
356 hasClass: function( selector ) {
357 return this.is( "." + selector );
358 },
359
360 val: function( value ) {
361 if ( value == undefined ) {
362
363 if ( this.length ) {
364 var elem = this[0];
365
366 // We need to handle select boxes special
367 if ( jQuery.nodeName( elem, "select" ) ) {
368 var index = elem.selectedIndex,
369 values = [],
370 options = elem.options,
371 one = elem.type == "select-one";
372
373 // Nothing was selected
374 if ( index < 0 )
375 return null;
376
377 // Loop through all the selected options
378 for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
379 var option = options[ i ];
380
381 if ( option.selected ) {
382 // Get the specifc value for the option
383 value = jQuery.browser.msie && !option.attributes.value.specified ? option.text : option.value;
384
385 // We don't need an array for one selects
386 if ( one )
387 return value;
388
389 // Multi-Selects return an array
390 values.push( value );
391 }
392 }
393
394 return values;
395
396 // Everything else, we just grab the value
397 } else
398 return (this[0].value || "").replace(/\r/g, "");
399
400 }
401
402 return undefined;
403 }
404
405 if( value.constructor == Number )
406 value += '';
407
408 return this.each(function(){
409 if ( this.nodeType != 1 )
410 return;
411
412 if ( value.constructor == Array && /radio|checkbox/.test( this.type ) )
413 this.checked = (jQuery.inArray(this.value, value) >= 0 ||
414 jQuery.inArray(this.name, value) >= 0);
415
416 else if ( jQuery.nodeName( this, "select" ) ) {
417 var values = jQuery.makeArray(value);
418
419 jQuery( "option", this ).each(function(){
420 this.selected = (jQuery.inArray( this.value, values ) >= 0 ||
421 jQuery.inArray( this.text, values ) >= 0);
422 });
423
424 if ( !values.length )
425 this.selectedIndex = -1;
426
427 } else
428 this.value = value;
429 });
430 },
431
432 html: function( value ) {
433 return value == undefined ?
434 (this[0] ?
435 this[0].innerHTML :
436 null) :
437 this.empty().append( value );
438 },
439
440 replaceWith: function( value ) {
441 return this.after( value ).remove();
442 },
443
444 eq: function( i ) {
445 return this.slice( i, i + 1 );
446 },
447
448 slice: function() {
449 return this.pushStack( Array.prototype.slice.apply( this, arguments ) );
450 },
451
452 map: function( callback ) {
453 return this.pushStack( jQuery.map(this, function(elem, i){
454 return callback.call( elem, i, elem );
455 }));
456 },
457
458 andSelf: function() {
459 return this.add( this.prevObject );
460 },
461
462 data: function( key, value ){
463 var parts = key.split(".");
464 parts[1] = parts[1] ? "." + parts[1] : "";
465
466 if ( value === undefined ) {
467 var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
468
469 if ( data === undefined && this.length )
470 data = jQuery.data( this[0], key );
471
472 return data === undefined && parts[1] ?
473 this.data( parts[0] ) :
474 data;
475 } else
476 return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function(){
477 jQuery.data( this, key, value );
478 });
479 },
480
481 removeData: function( key ){
482 return this.each(function(){
483 jQuery.removeData( this, key );
484 });
485 },
486
487 domManip: function( args, table, reverse, callback ) {
488 var clone = this.length > 1, elems;
489
490 return this.each(function(){
491 if ( !elems ) {
492 elems = jQuery.clean( args, this.ownerDocument );
493
494 if ( reverse )
495 elems.reverse();
496 }
497
498 var obj = this;
499
500 if ( table && jQuery.nodeName( this, "table" ) && jQuery.nodeName( elems[0], "tr" ) )
501 obj = this.getElementsByTagName("tbody")[0] || this.appendChild( this.ownerDocument.createElement("tbody") );
502
503 var scripts = jQuery( [] );
504
505 jQuery.each(elems, function(){
506 var elem = clone ?
507 jQuery( this ).clone( true )[0] :
508 this;
509
510 // execute all scripts after the elements have been injected
511 if ( jQuery.nodeName( elem, "script" ) )
512 scripts = scripts.add( elem );
513 else {
514 // Remove any inner scripts for later evaluation
515 if ( elem.nodeType == 1 )
516 scripts = scripts.add( jQuery( "script", elem ).remove() );
517
518 // Inject the elements into the document
519 callback.call( obj, elem );
520 }
521 });
522
523 scripts.each( evalScript );
524 });
525 }
526 };
527
528 // Give the init function the jQuery prototype for later instantiation
529 jQuery.fn.init.prototype = jQuery.fn;
530
531 function evalScript( i, elem ) {
532 if ( elem.src )
533 jQuery.ajax({
534 url: elem.src,
535 async: false,
536 dataType: "script"
537 });
538
539 else
540 jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
541
542 if ( elem.parentNode )
543 elem.parentNode.removeChild( elem );
544 }
545
546 function now(){
547 return +new Date;
548 }
549
550 jQuery.extend = jQuery.fn.extend = function() {
551 // copy reference to target object
552 var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;
553
554 // Handle a deep copy situation
555 if ( target.constructor == Boolean ) {
556 deep = target;
557 target = arguments[1] || {};
558 // skip the boolean and the target
559 i = 2;
560 }
561
562 // Handle case when target is a string or something (possible in deep copy)
563 if ( typeof target != "object" && typeof target != "function" )
564 target = {};
565
566 // extend jQuery itself if only one argument is passed
567 if ( length == i ) {
568 target = this;
569 --i;
570 }
571
572 for ( ; i < length; i++ )
573 // Only deal with non-null/undefined values
574 if ( (options = arguments[ i ]) != null )
575 // Extend the base object
576 for ( var name in options ) {
577 var src = target[ name ], copy = options[ name ];
578
579 // Prevent never-ending loop
580 if ( target === copy )
581 continue;
582
583 // Recurse if we're merging object values
584 if ( deep && copy && typeof copy == "object" && !copy.nodeType )
585 target[ name ] = jQuery.extend( deep,
586 // Never move original objects, clone them
587 src || ( copy.length != null ? [ ] : { } )
588 , copy );
589
590 // Don't bring in undefined values
591 else if ( copy !== undefined )
592 target[ name ] = copy;
593
594 }
595
596 // Return the modified object
597 return target;
598 };
599
600 var expando = "jQuery" + now(), uuid = 0, windowData = {},
601 // exclude the following css properties to add px
602 exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i,
603 // cache defaultView
604 defaultView = document.defaultView || {};
605
606 jQuery.extend({
607 noConflict: function( deep ) {
608 window.$ = _$;
609
610 if ( deep )
611 window.jQuery = _jQuery;
612
613 return jQuery;
614 },
615
616 // See test/unit/core.js for details concerning this function.
617 isFunction: function( fn ) {
618 return !!fn && typeof fn != "string" && !fn.nodeName &&
619 fn.constructor != Array && /^[\s[]?function/.test( fn + "" );
620 },
621
622 // check if an element is in a (or is an) XML document
623 isXMLDoc: function( elem ) {
624 return elem.documentElement && !elem.body ||
625 elem.tagName && elem.ownerDocument && !elem.ownerDocument.body;
626 },
627
628 // Evalulates a script in a global context
629 globalEval: function( data ) {
630 data = jQuery.trim( data );
631
632 if ( data ) {
633 // Inspired by code by Andrea Giammarchi
634 // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
635 var head = document.getElementsByTagName("head")[0] || document.documentElement,
636 script = document.createElement("script");
637
638 script.type = "text/javascript";
639 if ( jQuery.browser.msie )
640 script.text = data;
641 else
642 script.appendChild( document.createTextNode( data ) );
643
644 // Use insertBefore instead of appendChild to circumvent an IE6 bug.
645 // This arises when a base node is used (#2709).
646 head.insertBefore( script, head.firstChild );
647 head.removeChild( script );
648 }
649 },
650
651 nodeName: function( elem, name ) {
652 return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase();
653 },
654
655 cache: {},
656
657 data: function( elem, name, data ) {
658 elem = elem == window ?
659 windowData :
660 elem;
661
662 var id = elem[ expando ];
663
664 // Compute a unique ID for the element
665 if ( !id )
666 id = elem[ expando ] = ++uuid;
667
668 // Only generate the data cache if we're
669 // trying to access or manipulate it
670 if ( name && !jQuery.cache[ id ] )
671 jQuery.cache[ id ] = {};
672
673 // Prevent overriding the named cache with undefined values
674 if ( data !== undefined )
675 jQuery.cache[ id ][ name ] = data;
676
677 // Return the named cache data, or the ID for the element
678 return name ?
679 jQuery.cache[ id ][ name ] :
680 id;
681 },
682
683 removeData: function( elem, name ) {
684 elem = elem == window ?
685 windowData :
686 elem;
687
688 var id = elem[ expando ];
689
690 // If we want to remove a specific section of the element's data
691 if ( name ) {
692 if ( jQuery.cache[ id ] ) {
693 // Remove the section of cache data
694 delete jQuery.cache[ id ][ name ];
695
696 // If we've removed all the data, remove the element's cache
697 name = "";
698
699 for ( name in jQuery.cache[ id ] )
700 break;
701
702 if ( !name )
703 jQuery.removeData( elem );
704 }
705
706 // Otherwise, we want to remove all of the element's data
707 } else {
708 // Clean up the element expando
709 try {
710 delete elem[ expando ];
711 } catch(e){
712 // IE has trouble directly removing the expando
713 // but it's ok with using removeAttribute
714 if ( elem.removeAttribute )
715 elem.removeAttribute( expando );
716 }
717
718 // Completely remove the data cache
719 delete jQuery.cache[ id ];
720 }
721 },
722
723 // args is for internal usage only
724 each: function( object, callback, args ) {
725 var name, i = 0, length = object.length;
726
727 if ( args ) {
728 if ( length == undefined ) {
729 for ( name in object )
730 if ( callback.apply( object[ name ], args ) === false )
731 break;
732 } else
733 for ( ; i < length; )
734 if ( callback.apply( object[ i++ ], args ) === false )
735 break;
736
737 // A special, fast, case for the most common use of each
738 } else {
739 if ( length == undefined ) {
740 for ( name in object )
741 if ( callback.call( object[ name ], name, object[ name ] ) === false )
742 break;
743 } else
744 for ( var value = object[0];
745 i < length && callback.call( value, i, value ) !== false; value = object[++i] ){}
746 }
747
748 return object;
749 },
750
751 prop: function( elem, value, type, i, name ) {
752 // Handle executable functions
753 if ( jQuery.isFunction( value ) )
754 value = value.call( elem, i );
755
756 // Handle passing in a number to a CSS property
757 return value && value.constructor == Number && type == "curCSS" && !exclude.test( name ) ?
758 value + "px" :
759 value;
760 },
761
762 className: {
763 // internal only, use addClass("class")
764 add: function( elem, classNames ) {
765 jQuery.each((classNames || "").split(/\s+/), function(i, className){
766 if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) )
767 elem.className += (elem.className ? " " : "") + className;
768 });
769 },
770
771 // internal only, use removeClass("class")
772 remove: function( elem, classNames ) {
773 if (elem.nodeType == 1)
774 elem.className = classNames != undefined ?
775 jQuery.grep(elem.className.split(/\s+/), function(className){
776 return !jQuery.className.has( classNames, className );
777 }).join(" ") :
778 "";
779 },
780
781 // internal only, use hasClass("class")
782 has: function( elem, className ) {
783 return jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1;
784 }
785 },
786
787 // A method for quickly swapping in/out CSS properties to get correct calculations
788 swap: function( elem, options, callback ) {
789 var old = {};
790 // Remember the old values, and insert the new ones
791 for ( var name in options ) {
792 old[ name ] = elem.style[ name ];
793 elem.style[ name ] = options[ name ];
794 }
795
796 callback.call( elem );
797
798 // Revert the old values
799 for ( var name in options )
800 elem.style[ name ] = old[ name ];
801 },
802
803 css: function( elem, name, force ) {
804 if ( name == "width" || name == "height" ) {
805 var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ];
806
807 function getWH() {
808 val = name == "width" ? elem.offsetWidth : elem.offsetHeight;
809 var padding = 0, border = 0;
810 jQuery.each( which, function() {
811 padding += parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0;
812 border += parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0;
813 });
814 val -= Math.round(padding + border);
815 }
816
817 if ( jQuery(elem).is(":visible") )
818 getWH();
819 else
820 jQuery.swap( elem, props, getWH );
821
822 return Math.max(0, val);
823 }
824
825 return jQuery.curCSS( elem, name, force );
826 },
827
828 curCSS: function( elem, name, force ) {
829 var ret, style = elem.style;
830
831 // A helper method for determining if an element's values are broken
832 function color( elem ) {
833 if ( !jQuery.browser.safari )
834 return false;
835
836 // defaultView is cached
837 var ret = defaultView.getComputedStyle( elem, null );
838 return !ret || ret.getPropertyValue("color") == "";
839 }
840
841 // We need to handle opacity special in IE
842 if ( name == "opacity" && jQuery.browser.msie ) {
843 ret = jQuery.attr( style, "opacity" );
844
845 return ret == "" ?
846 "1" :
847 ret;
848 }
849 // Opera sometimes will give the wrong display answer, this fixes it, see #2037
850 if ( jQuery.browser.opera && name == "display" ) {
851 var save = style.outline;
852 style.outline = "0 solid black";
853 style.outline = save;
854 }
855
856 // Make sure we're using the right name for getting the float value
857 if ( name.match( /float/i ) )
858 name = styleFloat;
859
860 if ( !force && style && style[ name ] )
861 ret = style[ name ];
862
863 else if ( defaultView.getComputedStyle ) {
864
865 // Only "float" is needed here
866 if ( name.match( /float/i ) )
867 name = "float";
868
869 name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase();
870
871 var computedStyle = defaultView.getComputedStyle( elem, null );
872
873 if ( computedStyle && !color( elem ) )
874 ret = computedStyle.getPropertyValue( name );
875
876 // If the element isn't reporting its values properly in Safari
877 // then some display: none elements are involved
878 else {
879 var swap = [], stack = [], a = elem, i = 0;
880
881 // Locate all of the parent display: none elements
882 for ( ; a && color(a); a = a.parentNode )
883 stack.unshift(a);
884
885 // Go through and make them visible, but in reverse
886 // (It would be better if we knew the exact display type that they had)
887 for ( ; i < stack.length; i++ )
888 if ( color( stack[ i ] ) ) {
889 swap[ i ] = stack[ i ].style.display;
890 stack[ i ].style.display = "block";
891 }
892
893 // Since we flip the display style, we have to handle that
894 // one special, otherwise get the value
895 ret = name == "display" && swap[ stack.length - 1 ] != null ?
896 "none" :
897 ( computedStyle && computedStyle.getPropertyValue( name ) ) || "";
898
899 // Finally, revert the display styles back
900 for ( i = 0; i < swap.length; i++ )
901 if ( swap[ i ] != null )
902 stack[ i ].style.display = swap[ i ];
903 }
904
905 // We should always get a number back from opacity
906 if ( name == "opacity" && ret == "" )
907 ret = "1";
908
909 } else if ( elem.currentStyle ) {
910 var camelCase = name.replace(/\-(\w)/g, function(all, letter){
911 return letter.toUpperCase();
912 });
913
914 ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ];
915
916 // From the awesome hack by Dean Edwards
917 // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
918
919 // If we're not dealing with a regular pixel number
920 // but a number that has a weird ending, we need to convert it to pixels
921 if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) {
922 // Remember the original values
923 var left = style.left, rsLeft = elem.runtimeStyle.left;
924
925 // Put in the new values to get a computed value out
926 elem.runtimeStyle.left = elem.currentStyle.left;
927 style.left = ret || 0;
928 ret = style.pixelLeft + "px";
929
930 // Revert the changed values
931 style.left = left;
932 elem.runtimeStyle.left = rsLeft;
933 }
934 }
935
936 return ret;
937 },
938
939 clean: function( elems, context ) {
940 var ret = [];
941 context = context || document;
942 // !context.createElement fails in IE with an error but returns typeof 'object'
943 if (typeof context.createElement == 'undefined')
944 context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
945
946 jQuery.each(elems, function(i, elem){
947 if ( !elem )
948 return;
949
950 if ( elem.constructor == Number )
951 elem += '';
952
953 // Convert html string into DOM nodes
954 if ( typeof elem == "string" ) {
955 // Fix "XHTML"-style tags in all browsers
956 elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){
957 return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ?
958 all :
959 front + "></" + tag + ">";
960 });
961
962 // Trim whitespace, otherwise indexOf won't work as expected
963 var tags = jQuery.trim( elem ).toLowerCase(), div = context.createElement("div");
964
965 var wrap =
966 // option or optgroup
967 !tags.indexOf("<opt") &&
968 [ 1, "<select multiple='multiple'>", "</select>" ] ||
969
970 !tags.indexOf("<leg") &&
971 [ 1, "<fieldset>", "</fieldset>" ] ||
972
973 tags.match(/^<(thead|tbody|tfoot|colg|cap)/) &&
974 [ 1, "<table>", "</table>" ] ||
975
976 !tags.indexOf("<tr") &&
977 [ 2, "<table><tbody>", "</tbody></table>" ] ||
978
979 // <thead> matched above
980 (!tags.indexOf("<td") || !tags.indexOf("<th")) &&
981 [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ] ||
982
983 !tags.indexOf("<col") &&
984 [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ] ||
985
986 // IE can't serialize <link> and <script> tags normally
987 jQuery.browser.msie &&
988 [ 1, "div<div>", "</div>" ] ||
989
990 [ 0, "", "" ];
991
992 // Go to html and back, then peel off extra wrappers
993 div.innerHTML = wrap[1] + elem + wrap[2];
994
995 // Move to the right depth
996 while ( wrap[0]-- )
997 div = div.lastChild;
998
999 // Remove IE's autoinserted <tbody> from table fragments
1000 if ( jQuery.browser.msie ) {
1001
1002 // String was a <table>, *may* have spurious <tbody>
1003 var tbody = !tags.indexOf("<table") && tags.indexOf("<tbody") < 0 ?
1004 div.firstChild && div.firstChild.childNodes :
1005
1006 // String was a bare <thead> or <tfoot>
1007 wrap[1] == "<table>" && tags.indexOf("<tbody") < 0 ?
1008 div.childNodes :
1009 [];
1010
1011 for ( var j = tbody.length - 1; j >= 0 ; --j )
1012 if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length )
1013 tbody[ j ].parentNode.removeChild( tbody[ j ] );
1014
1015 // IE completely kills leading whitespace when innerHTML is used
1016 if ( /^\s/.test( elem ) )
1017 div.insertBefore( context.createTextNode( elem.match(/^\s*/)[0] ), div.firstChild );
1018
1019 }
1020
1021 elem = jQuery.makeArray( div.childNodes );
1022 }
1023
1024 if ( elem.length === 0 && (!jQuery.nodeName( elem, "form" ) && !jQuery.nodeName( elem, "select" )) )
1025 return;
1026
1027 if ( elem[0] == undefined || jQuery.nodeName( elem, "form" ) || elem.options )
1028 ret.push( elem );
1029
1030 else
1031 ret = jQuery.merge( ret, elem );
1032
1033 });
1034
1035 return ret;
1036 },
1037
1038 attr: function( elem, name, value ) {
1039 // don't set attributes on text and comment nodes
1040 if (!elem || elem.nodeType == 3 || elem.nodeType == 8)
1041 return undefined;
1042
1043 var notxml = !jQuery.isXMLDoc( elem ),
1044 // Whether we are setting (or getting)
1045 set = value !== undefined,
1046 msie = jQuery.browser.msie;
1047
1048 // Try to normalize/fix the name
1049 name = notxml && jQuery.props[ name ] || name;
1050
1051 // Only do all the following if this is a node (faster for style)
1052 // IE elem.getAttribute passes even for style
1053 if ( elem.tagName ) {
1054
1055 // These attributes require special treatment
1056 var special = /href|src|style/.test( name );
1057
1058 // Safari mis-reports the default selected property of a hidden option
1059 // Accessing the parent's selectedIndex property fixes it
1060 if ( name == "selected" && jQuery.browser.safari )
1061 elem.parentNode.selectedIndex;
1062
1063 // If applicable, access the attribute via the DOM 0 way
1064 if ( name in elem && notxml && !special ) {
1065 if ( set ){
1066 // We can't allow the type property to be changed (since it causes problems in IE)
1067 if ( name == "type" && jQuery.nodeName( elem, "input" ) && elem.parentNode )
1068 throw "type property can't be changed";
1069
1070 elem[ name ] = value;
1071 }
1072
1073 // browsers index elements by id/name on forms, give priority to attributes.
1074 if( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) )
1075 return elem.getAttributeNode( name ).nodeValue;
1076
1077 return elem[ name ];
1078 }
1079
1080 if ( msie && notxml && name == "style" )
1081 return jQuery.attr( elem.style, "cssText", value );
1082
1083 if ( set )
1084 // convert the value to a string (all browsers do this but IE) see #1070
1085 elem.setAttribute( name, "" + value );
1086
1087 var attr = msie && notxml && special
1088 // Some attributes require a special call on IE
1089 ? elem.getAttribute( name, 2 )
1090 : elem.getAttribute( name );
1091
1092 // Non-existent attributes return null, we normalize to undefined
1093 return attr === null ? undefined : attr;
1094 }
1095
1096 // elem is actually elem.style ... set the style
1097
1098 // IE uses filters for opacity
1099 if ( msie && name == "opacity" ) {
1100 if ( set ) {
1101 // IE has trouble with opacity if it does not have layout
1102 // Force it by setting the zoom level
1103 elem.zoom = 1;
1104
1105 // Set the alpha filter to set the opacity
1106 elem.filter = (elem.filter || "").replace( /alpha\([^)]*\)/, "" ) +
1107 (parseInt( value ) + '' == "NaN" ? "" : "alpha(opacity=" + value * 100 + ")");
1108 }
1109
1110 return elem.filter && elem.filter.indexOf("opacity=") >= 0 ?
1111 (parseFloat( elem.filter.match(/opacity=([^)]*)/)[1] ) / 100) + '':
1112 "";
1113 }
1114
1115 name = name.replace(/-([a-z])/ig, function(all, letter){
1116 return letter.toUpperCase();
1117 });
1118
1119 if ( set )
1120 elem[ name ] = value;
1121
1122 return elem[ name ];
1123 },
1124
1125 trim: function( text ) {
1126 return (text || "").replace( /^\s+|\s+$/g, "" );
1127 },
1128
1129 makeArray: function( array ) {
1130 var ret = [];
1131
1132 if( array != null ){
1133 var i = array.length;
1134 //the window, strings and functions also have 'length'
1135 if( i == null || array.split || array.setInterval || array.call )
1136 ret[0] = array;
1137 else
1138 while( i )
1139 ret[--i] = array[i];
1140 }
1141
1142 return ret;
1143 },
1144
1145 inArray: function( elem, array ) {
1146 for ( var i = 0, length = array.length; i < length; i++ )
1147 // Use === because on IE, window == document
1148 if ( array[ i ] === elem )
1149 return i;
1150
1151 return -1;
1152 },
1153
1154 merge: function( first, second ) {
1155 // We have to loop this way because IE & Opera overwrite the length
1156 // expando of getElementsByTagName
1157 var i = 0, elem, pos = first.length;
1158 // Also, we need to make sure that the correct elements are being returned
1159 // (IE returns comment nodes in a '*' query)
1160 if ( jQuery.browser.msie ) {
1161 while ( elem = second[ i++ ] )
1162 if ( elem.nodeType != 8 )
1163 first[ pos++ ] = elem;
1164
1165 } else
1166 while ( elem = second[ i++ ] )
1167 first[ pos++ ] = elem;
1168
1169 return first;
1170 },
1171
1172 unique: function( array ) {
1173 var ret = [], done = {};
1174
1175 try {
1176
1177 for ( var i = 0, length = array.length; i < length; i++ ) {
1178 var id = jQuery.data( array[ i ] );
1179
1180 if ( !done[ id ] ) {
1181 done[ id ] = true;
1182 ret.push( array[ i ] );
1183 }
1184 }
1185
1186 } catch( e ) {
1187 ret = array;
1188 }
1189
1190 return ret;
1191 },
1192
1193 grep: function( elems, callback, inv ) {
1194 var ret = [];
1195
1196 // Go through the array, only saving the items
1197 // that pass the validator function
1198 for ( var i = 0, length = elems.length; i < length; i++ )
1199 if ( !inv != !callback( elems[ i ], i ) )
1200 ret.push( elems[ i ] );
1201
1202 return ret;
1203 },
1204
1205 map: function( elems, callback ) {
1206 var ret = [];
1207
1208 // Go through the array, translating each of the items to their
1209 // new value (or values).
1210 for ( var i = 0, length = elems.length; i < length; i++ ) {
1211 var value = callback( elems[ i ], i );
1212
1213 if ( value != null )
1214 ret[ ret.length ] = value;
1215 }
1216
1217 return ret.concat.apply( [], ret );
1218 }
1219 });
1220
1221 var userAgent = navigator.userAgent.toLowerCase();
1222
1223 // Figure out what browser is being used
1224 jQuery.browser = {
1225 version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [])[1],
1226 safari: /webkit/.test( userAgent ),
1227 opera: /opera/.test( userAgent ),
1228 msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ),
1229 mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent )
1230 };
1231
1232 var styleFloat = jQuery.browser.msie ?
1233 "styleFloat" :
1234 "cssFloat";
1235
1236 jQuery.extend({
1237 // Check to see if the W3C box model is being used
1238 boxModel: !jQuery.browser.msie || document.compatMode == "CSS1Compat",
1239
1240 props: {
1241 "for": "htmlFor",
1242 "class": "className",
1243 "float": styleFloat,
1244 cssFloat: styleFloat,
1245 styleFloat: styleFloat,
1246 readonly: "readOnly",
1247 maxlength: "maxLength",
1248 cellspacing: "cellSpacing",
1249 rowspan: "rowSpan"
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 jQuery.event = {
1822
1823 // Bind an event to an element
1824 // Original by Dean Edwards
1825 add: function(elem, types, handler, data) {
1826 if ( elem.nodeType == 3 || elem.nodeType == 8 )
1827 return;
1828
1829 // For whatever reason, IE has trouble passing the window object
1830 // around, causing it to be cloned in the process
1831 if ( jQuery.browser.msie && elem.setInterval )
1832 elem = window;
1833
1834 // Make sure that the function being executed has a unique ID
1835 if ( !handler.guid )
1836 handler.guid = this.guid++;
1837
1838 // if data is passed, bind to handler
1839 if( data != undefined ) {
1840 // Create temporary function pointer to original handler
1841 var fn = handler;
1842
1843 // Create unique handler function, wrapped around original handler
1844 handler = this.proxy( fn, function() {
1845 // Pass arguments and context to original handler
1846 return fn.apply(this, arguments);
1847 });
1848
1849 // Store data in unique handler
1850 handler.data = data;
1851 }
1852
1853 // Init the element's event structure
1854 var events = jQuery.data(elem, "events") || jQuery.data(elem, "events", {}),
1855 handle = jQuery.data(elem, "handle") || jQuery.data(elem, "handle", function(){
1856 // Handle the second event of a trigger and when
1857 // an event is called after a page has unloaded
1858 if ( typeof jQuery != "undefined" && !jQuery.event.triggered )
1859 return jQuery.event.handle.apply(arguments.callee.elem, arguments);
1860 });
1861 // Add elem as a property of the handle function
1862 // This is to prevent a memory leak with non-native
1863 // event in IE.
1864 handle.elem = elem;
1865
1866 // Handle multiple events separated by a space
1867 // jQuery(...).bind("mouseover mouseout", fn);
1868 jQuery.each(types.split(/\s+/), function(index, type) {
1869 // Namespaced event handlers
1870 var parts = type.split(".");
1871 type = parts[0];
1872 handler.type = parts[1];
1873
1874 // Get the current list of functions bound to this event
1875 var handlers = events[type];
1876
1877 // Init the event handler queue
1878 if (!handlers) {
1879 handlers = events[type] = {};
1880
1881 // Check for a special event handler
1882 // Only use addEventListener/attachEvent if the special
1883 // events handler returns false
1884 if ( !jQuery.event.special[type] || jQuery.event.special[type].setup.call(elem) === false ) {
1885 // Bind the global event handler to the element
1886 if (elem.addEventListener)
1887 elem.addEventListener(type, handle, false);
1888 else if (elem.attachEvent)
1889 elem.attachEvent("on" + type, handle);
1890 }
1891 }
1892
1893 // Add the function to the element's handler list
1894 handlers[handler.guid] = handler;
1895
1896 // Keep track of which events have been used, for global triggering
1897 jQuery.event.global[type] = true;
1898 });
1899
1900 // Nullify elem to prevent memory leaks in IE
1901 elem = null;
1902 },
1903
1904 guid: 1,
1905 global: {},
1906
1907 // Detach an event or set of events from an element
1908 remove: function(elem, types, handler) {
1909 // don't do events on text and comment nodes
1910 if ( elem.nodeType == 3 || elem.nodeType == 8 )
1911 return;
1912
1913 var events = jQuery.data(elem, "events"), ret, index;
1914
1915 if ( events ) {
1916 // Unbind all events for the element
1917 if ( types == undefined || (typeof types == "string" && types.charAt(0) == ".") )
1918 for ( var type in events )
1919 this.remove( elem, type + (types || "") );
1920 else {
1921 // types is actually an event object here
1922 if ( types.type ) {
1923 handler = types.handler;
1924 types = types.type;
1925 }
1926
1927 // Handle multiple events seperated by a space
1928 // jQuery(...).unbind("mouseover mouseout", fn);
1929 jQuery.each(types.split(/\s+/), function(index, type){
1930 // Namespaced event handlers
1931 var parts = type.split(".");
1932 type = parts[0];
1933
1934 if ( events[type] ) {
1935 // remove the given handler for the given type
1936 if ( handler )
1937 delete events[type][handler.guid];
1938
1939 // remove all handlers for the given type
1940 else
1941 for ( handler in events[type] )
1942 // Handle the removal of namespaced events
1943 if ( !parts[1] || events[type][handler].type == parts[1] )
1944 delete events[type][handler];
1945
1946 // remove generic event handler if no more handlers exist
1947 for ( ret in events[type] ) break;
1948 if ( !ret ) {
1949 if ( !jQuery.event.special[type] || jQuery.event.special[type].teardown.call(elem) === false ) {
1950 if (elem.removeEventListener)
1951 elem.removeEventListener(type, jQuery.data(elem, "handle"), false);
1952 else if (elem.detachEvent)
1953 elem.detachEvent("on" + type, jQuery.data(elem, "handle"));
1954 }
1955 ret = null;
1956 delete events[type];
1957 }
1958 }
1959 });
1960 }
1961
1962 // Remove the expando if it's no longer used
1963 for ( ret in events ) break;
1964 if ( !ret ) {
1965 var handle = jQuery.data( elem, "handle" );
1966 if ( handle ) handle.elem = null;
1967 jQuery.removeData( elem, "events" );
1968 jQuery.removeData( elem, "handle" );
1969 }
1970 }
1971 },
1972
1973 trigger: function(type, data, elem, donative, extra) {
1974 // Clone the incoming data, if any
1975 data = jQuery.makeArray(data);
1976
1977 if ( type.indexOf("!") >= 0 ) {
1978 type = type.slice(0, -1);
1979 var exclusive = true;
1980 }
1981
1982 // Handle a global trigger
1983 if ( !elem ) {
1984 // Only trigger if we've ever bound an event for it
1985 if ( this.global[type] )
1986 jQuery("*").add([window, document]).trigger(type, data);
1987
1988 // Handle triggering a single element
1989 } else {
1990 // don't do events on text and comment nodes
1991 if ( elem.nodeType == 3 || elem.nodeType == 8 )
1992 return undefined;
1993
1994 var val, ret, fn = jQuery.isFunction( elem[ type ] || null ),
1995 // Check to see if we need to provide a fake event, or not
1996 event = !data[0] || !data[0].preventDefault;
1997
1998 // Pass along a fake event
1999 if ( event ) {
2000 data.unshift({
2001 type: type,
2002 target: elem,
2003 preventDefault: function(){},
2004 stopPropagation: function(){},
2005 timeStamp: now()
2006 });
2007 data[0][expando] = true; // no need to fix fake event
2008 }
2009
2010 // Enforce the right trigger type
2011 data[0].type = type;
2012 if ( exclusive )
2013 data[0].exclusive = true;
2014
2015 // Trigger the event, it is assumed that "handle" is a function
2016 var handle = jQuery.data(elem, "handle");
2017 if ( handle )
2018 val = handle.apply( elem, data );
2019
2020 // Handle triggering native .onfoo handlers (and on links since we don't call .click() for links)
2021 if ( (!fn || (jQuery.nodeName(elem, 'a') && type == "click")) && elem["on"+type] && elem["on"+type].apply( elem, data ) === false )
2022 val = false;
2023
2024 // Extra functions don't get the custom event object
2025 if ( event )
2026 data.shift();
2027
2028 // Handle triggering of extra function
2029 if ( extra && jQuery.isFunction( extra ) ) {
2030 // call the extra function and tack the current return value on the end for possible inspection
2031 ret = extra.apply( elem, val == null ? data : data.concat( val ) );
2032 // if anything is returned, give it precedence and have it overwrite the previous value
2033 if (ret !== undefined)
2034 val = ret;
2035 }
2036
2037 // Trigger the native events (except for clicks on links)
2038 if ( fn && donative !== false && val !== false && !(jQuery.nodeName(elem, 'a') && type == "click") ) {
2039 this.triggered = true;
2040 try {
2041 elem[ type ]();
2042 // prevent IE from throwing an error for some hidden elements
2043 } catch (e) {}
2044 }
2045
2046 this.triggered = false;
2047 }
2048
2049 return val;
2050 },
2051
2052 handle: function(event) {
2053 // returned undefined or false
2054 var val, ret, namespace, all, handlers;
2055
2056 event = arguments[0] = jQuery.event.fix( event || window.event );
2057
2058 // Namespaced event handlers
2059 namespace = event.type.split(".");
2060 event.type = namespace[0];
2061 namespace = namespace[1];
2062 // Cache this now, all = true means, any handler
2063 all = !namespace && !event.exclusive;
2064
2065 handlers = ( jQuery.data(this, "events") || {} )[event.type];
2066
2067 for ( var j in handlers ) {
2068 var handler = handlers[j];
2069
2070 // Filter the functions by class
2071 if ( all || handler.type == namespace ) {
2072 // Pass in a reference to the handler function itself
2073 // So that we can later remove it
2074 event.handler = handler;
2075 event.data = handler.data;
2076
2077 ret = handler.apply( this, arguments );
2078
2079 if ( val !== false )
2080 val = ret;
2081
2082 if ( ret === false ) {
2083 event.preventDefault();
2084 event.stopPropagation();
2085 }
2086 }
2087 }
2088
2089 return val;
2090 },
2091
2092 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(" "),
2093
2094 fix: function(event) {
2095 if ( event[expando] == true )
2096 return event;
2097
2098 // store a copy of the original event object
2099 // and "clone" to set read-only properties
2100 var originalEvent = event;
2101 event = { originalEvent: originalEvent };
2102
2103 for ( var i = this.props.length, prop; i; ){
2104 prop = this.props[ --i ];
2105 event[ prop ] = originalEvent[ prop ];
2106 }
2107
2108 // Mark it as fixed
2109 event[expando] = true;
2110
2111 // add preventDefault and stopPropagation since
2112 // they will not work on the clone
2113 event.preventDefault = function() {
2114 // if preventDefault exists run it on the original event
2115 if (originalEvent.preventDefault)
2116 originalEvent.preventDefault();
2117 // otherwise set the returnValue property of the original event to false (IE)
2118 originalEvent.returnValue = false;
2119 };
2120 event.stopPropagation = function() {
2121 // if stopPropagation exists run it on the original event
2122 if (originalEvent.stopPropagation)
2123 originalEvent.stopPropagation();
2124 // otherwise set the cancelBubble property of the original event to true (IE)
2125 originalEvent.cancelBubble = true;
2126 };
2127
2128 // Fix timeStamp
2129 event.timeStamp = event.timeStamp || now();
2130
2131 // Fix target property, if necessary
2132 if ( !event.target )
2133 event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
2134
2135 // check if target is a textnode (safari)
2136 if ( event.target.nodeType == 3 )
2137 event.target = event.target.parentNode;
2138
2139 // Add relatedTarget, if necessary
2140 if ( !event.relatedTarget && event.fromElement )
2141 event.relatedTarget = event.fromElement == event.target ? event.toElement : event.fromElement;
2142
2143 // Calculate pageX/Y if missing and clientX/Y available
2144 if ( event.pageX == null && event.clientX != null ) {
2145 var doc = document.documentElement, body = document.body;
2146 event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc.clientLeft || 0);
2147 event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc.clientTop || 0);
2148 }
2149
2150 // Add which for key events
2151 if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) )
2152 event.which = event.charCode || event.keyCode;
2153
2154 // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
2155 if ( !event.metaKey && event.ctrlKey )
2156 event.metaKey = event.ctrlKey;
2157
2158 // Add which for click: 1 == left; 2 == middle; 3 == right
2159 // Note: button is not normalized, so don't use it
2160 if ( !event.which && event.button )
2161 event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
2162
2163 return event;
2164 },
2165
2166 proxy: function( fn, proxy ){
2167 // Set the guid of unique handler to the same of original handler, so it can be removed
2168 proxy.guid = fn.guid = fn.guid || proxy.guid || this.guid++;
2169 // So proxy can be declared as an argument
2170 return proxy;
2171 },
2172
2173 special: {
2174 ready: {
2175 setup: function() {
2176 // Make sure the ready event is setup
2177 bindReady();
2178 return;
2179 },
2180
2181 teardown: function() { return; }
2182 },
2183
2184 mouseenter: {
2185 setup: function() {
2186 if ( jQuery.browser.msie ) return false;
2187 jQuery(this).bind("mouseover", jQuery.event.special.mouseenter.handler);
2188 return true;
2189 },
2190
2191 teardown: function() {
2192 if ( jQuery.browser.msie ) return false;
2193 jQuery(this).unbind("mouseover", jQuery.event.special.mouseenter.handler);
2194 return true;
2195 },
2196
2197 handler: function(event) {
2198 // If we actually just moused on to a sub-element, ignore it
2199 if ( withinElement(event, this) ) return true;
2200 // Execute the right handlers by setting the event type to mouseenter
2201 event.type = "mouseenter";
2202 return jQuery.event.handle.apply(this, arguments);
2203 }
2204 },
2205
2206 mouseleave: {
2207 setup: function() {
2208 if ( jQuery.browser.msie ) return false;
2209 jQuery(this).bind("mouseout", jQuery.event.special.mouseleave.handler);
2210 return true;
2211 },
2212
2213 teardown: function() {
2214 if ( jQuery.browser.msie ) return false;
2215 jQuery(this).unbind("mouseout", jQuery.event.special.mouseleave.handler);
2216 return true;
2217 },
2218
2219 handler: function(event) {
2220 // If we actually just moused on to a sub-element, ignore it
2221 if ( withinElement(event, this) ) return true;
2222 // Execute the right handlers by setting the event type to mouseleave
2223 event.type = "mouseleave";
2224 return jQuery.event.handle.apply(this, arguments);
2225 }
2226 }
2227 }
2228 };
2229
2230 jQuery.fn.extend({
2231 bind: function( type, data, fn ) {
2232 return type == "unload" ? this.one(type, data, fn) : this.each(function(){
2233 jQuery.event.add( this, type, fn || data, fn && data );
2234 });
2235 },
2236
2237 one: function( type, data, fn ) {
2238 var one = jQuery.event.proxy( fn || data, function(event) {
2239 jQuery(this).unbind(event, one);
2240 return (fn || data).apply( this, arguments );
2241 });
2242 return this.each(function(){
2243 jQuery.event.add( this, type, one, fn && data);
2244 });
2245 },
2246
2247 unbind: function( type, fn ) {
2248 return this.each(function(){
2249 jQuery.event.remove( this, type, fn );
2250 });
2251 },
2252
2253 trigger: function( type, data, fn ) {
2254 return this.each(function(){
2255 jQuery.event.trigger( type, data, this, true, fn );
2256 });
2257 },
2258
2259 triggerHandler: function( type, data, fn ) {
2260 return this[0] && jQuery.event.trigger( type, data, this[0], false, fn );
2261 },
2262
2263 toggle: function( fn ) {
2264 // Save reference to arguments for access in closure
2265 var args = arguments, i = 1;
2266
2267 // link all the functions, so any of them can unbind this click handler
2268 while( i < args.length )
2269 jQuery.event.proxy( fn, args[i++] );
2270
2271 return this.click( jQuery.event.proxy( fn, function(event) {
2272 // Figure out which function to execute
2273 this.lastToggle = ( this.lastToggle || 0 ) % i;
2274
2275 // Make sure that clicks stop
2276 event.preventDefault();
2277
2278 // and execute the function
2279 return args[ this.lastToggle++ ].apply( this, arguments ) || false;
2280 }));
2281 },
2282
2283 hover: function(fnOver, fnOut) {
2284 return this.bind('mouseenter', fnOver).bind('mouseleave', fnOut);
2285 },
2286
2287 ready: function(fn) {
2288 // Attach the listeners
2289 bindReady();
2290
2291 // If the DOM is already ready
2292 if ( jQuery.isReady )
2293 // Execute the function immediately
2294 fn.call( document, jQuery );
2295
2296 // Otherwise, remember the function for later
2297 else
2298 // Add the function to the wait list
2299 jQuery.readyList.push( function() { return fn.call(this, jQuery); } );
2300
2301 return this;
2302 }
2303 });
2304
2305 jQuery.extend({
2306 isReady: false,
2307 readyList: [],
2308 // Handle when the DOM is ready
2309 ready: function() {
2310 // Make sure that the DOM is not already loaded
2311 if ( !jQuery.isReady ) {
2312 // Remember that the DOM is ready
2313 jQuery.isReady = true;
2314
2315 // If there are functions bound, to execute
2316 if ( jQuery.readyList ) {
2317 // Execute all of them
2318 jQuery.each( jQuery.readyList, function(){
2319 this.call( document );
2320 });
2321
2322 // Reset the list of functions
2323 jQuery.readyList = null;
2324 }
2325
2326 // Trigger any bound ready events
2327 jQuery(document).triggerHandler("ready");
2328 }
2329 }
2330 });
2331
2332 var readyBound = false;
2333
2334 function bindReady(){
2335 if ( readyBound ) return;
2336 readyBound = true;
2337
2338 // Mozilla, Opera (see further below for it) and webkit nightlies currently support this event
2339 if ( document.addEventListener && !jQuery.browser.opera)
2340 // Use the handy event callback
2341 document.addEventListener( "DOMContentLoaded", jQuery.ready, false );
2342
2343 // If IE is used and is not in a frame
2344 // Continually check to see if the document is ready
2345 if ( jQuery.browser.msie && window == top ) (function(){
2346 if (jQuery.isReady) return;
2347 try {
2348 // If IE is used, use the trick by Diego Perini
2349 // http://javascript.nwbox.com/IEContentLoaded/
2350 document.documentElement.doScroll("left");
2351 } catch( error ) {
2352 setTimeout( arguments.callee, 0 );
2353 return;
2354 }
2355 // and execute any waiting functions
2356 jQuery.ready();
2357 })();
2358
2359 if ( jQuery.browser.opera )
2360 document.addEventListener( "DOMContentLoaded", function () {
2361 if (jQuery.isReady) return;
2362 for (var i = 0; i < document.styleSheets.length; i++)
2363 if (document.styleSheets[i].disabled) {
2364 setTimeout( arguments.callee, 0 );
2365 return;
2366 }
2367 // and execute any waiting functions
2368 jQuery.ready();
2369 }, false);
2370
2371 if ( jQuery.browser.safari ) {
2372 var numStyles;
2373 (function(){
2374 if (jQuery.isReady) return;
2375 if ( document.readyState != "loaded" && document.readyState != "complete" ) {
2376 setTimeout( arguments.callee, 0 );
2377 return;
2378 }
2379 if ( numStyles === undefined )
2380 numStyles = jQuery("style, link[rel=stylesheet]").length;
2381 if ( document.styleSheets.length != numStyles ) {
2382 setTimeout( arguments.callee, 0 );
2383 return;
2384 }
2385 // and execute any waiting functions
2386 jQuery.ready();
2387 })();
2388 }
2389
2390 // A fallback to window.onload, that will always work
2391 jQuery.event.add( window, "load", jQuery.ready );
2392 }
2393
2394 jQuery.each( ("blur,focus,load,resize,scroll,unload,click,dblclick," +
2395 "mousedown,mouseup,mousemove,mouseover,mouseout,change,select," +
2396 "submit,keydown,keypress,keyup,error").split(","), function(i, name){
2397
2398 // Handle event binding
2399 jQuery.fn[name] = function(fn){
2400 return fn ? this.bind(name, fn) : this.trigger(name);
2401 };
2402 });
2403
2404 // Checks if an event happened on an element within another element
2405 // Used in jQuery.event.special.mouseenter and mouseleave handlers
2406 var withinElement = function(event, elem) {
2407 // Check if mouse(over|out) are still within the same parent element
2408 var parent = event.relatedTarget;
2409 // Traverse up the tree
2410 while ( parent && parent != elem ) try { parent = parent.parentNode; } catch(error) { parent = elem; }
2411 // Return true if we actually just moused on to a sub-element
2412 return parent == elem;
2413 };
2414
2415 // Prevent memory leaks in IE
2416 // And prevent errors on refresh with events like mouseover in other browsers
2417 // Window isn't included so as not to unbind existing unload events
2418 jQuery(window).bind("unload", function() {
2419 jQuery("*").add(document).unbind();
2420 });
2421 jQuery.fn.extend({
2422 // Keep a copy of the old load
2423 _load: jQuery.fn.load,
2424
2425 load: function( url, params, callback ) {
2426 if ( typeof url != 'string' )
2427 return this._load( url );
2428
2429 var off = url.indexOf(" ");
2430 if ( off >= 0 ) {
2431 var selector = url.slice(off, url.length);
2432 url = url.slice(0, off);
2433 }
2434
2435 callback = callback || function(){};
2436
2437 // Default to a GET request
2438 var type = "GET";
2439
2440 // If the second parameter was provided
2441 if ( params )
2442 // If it's a function
2443 if ( jQuery.isFunction( params ) ) {
2444 // We assume that it's the callback
2445 callback = params;
2446 params = null;
2447
2448 // Otherwise, build a param string
2449 } else if( typeof params == 'object' ) {
2450 params = jQuery.param( params );
2451 type = "POST";
2452 }
2453
2454 var self = this;
2455
2456 // Request the remote document
2457 jQuery.ajax({
2458 url: url,
2459 type: type,
2460 dataType: "html",
2461 data: params,
2462 complete: function(res, status){
2463 // If successful, inject the HTML into all the matched elements
2464 if ( status == "success" || status == "notmodified" )
2465 // See if a selector was specified
2466 self.html( selector ?
2467 // Create a dummy div to hold the results
2468 jQuery("<div/>")
2469 // inject the contents of the document in, removing the scripts
2470 // to avoid any 'Permission Denied' errors in IE
2471 .append(res.responseText.replace(/<script(.|\s)*?\/script>/g, ""))
2472
2473 // Locate the specified elements
2474 .find(selector) :
2475
2476 // If not, just inject the full result
2477 res.responseText );
2478
2479 self.each( callback, [res.responseText, status, res] );
2480 }
2481 });
2482 return this;
2483 },
2484
2485 serialize: function() {
2486 return jQuery.param(this.serializeArray());
2487 },
2488 serializeArray: function() {
2489 return this.map(function(){
2490 return jQuery.nodeName(this, "form") ?
2491 jQuery.makeArray(this.elements) : this;
2492 })
2493 .filter(function(){
2494 return this.name && !this.disabled &&
2495 (this.checked || /select|textarea/i.test(this.nodeName) ||
2496 /text|hidden|password/i.test(this.type));
2497 })
2498 .map(function(i, elem){
2499 var val = jQuery(this).val();
2500 return val == null ? null :
2501 val.constructor == Array ?
2502 jQuery.map( val, function(val, i){
2503 return {name: elem.name, value: val};
2504 }) :
2505 {name: elem.name, value: val};
2506 }).get();
2507 }
2508 });
2509
2510 // Attach a bunch of functions for handling common AJAX events
2511 jQuery.each( "ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","), function(i,o){
2512 jQuery.fn[o] = function(f){
2513 return this.bind(o, f);
2514 };
2515 });
2516
2517 var jsc = now();
2518
2519 jQuery.extend({
2520 get: function( url, data, callback, type ) {
2521 // shift arguments if data argument was ommited
2522 if ( jQuery.isFunction( data ) ) {
2523 callback = data;
2524 data = null;
2525 }
2526
2527 return jQuery.ajax({
2528 type: "GET",
2529 url: url,
2530 data: data,
2531 success: callback,
2532 dataType: type
2533 });
2534 },
2535
2536 getScript: function( url, callback ) {
2537 return jQuery.get(url, null, callback, "script");
2538 },
2539
2540 getJSON: function( url, data, callback ) {
2541 return jQuery.get(url, data, callback, "json");
2542 },
2543
2544 post: function( url, data, callback, type ) {
2545 if ( jQuery.isFunction( data ) ) {
2546 callback = data;
2547 data = {};
2548 }
2549
2550 return jQuery.ajax({
2551 type: "POST",
2552 url: url,
2553 data: data,
2554 success: callback,
2555 dataType: type
2556 });
2557 },
2558
2559 ajaxSetup: function( settings ) {
2560 jQuery.extend( jQuery.ajaxSettings, settings );
2561 },
2562
2563 ajaxSettings: {
2564 url: location.href,
2565 global: true,
2566 type: "GET",
2567 timeout: 0,
2568 contentType: "application/x-www-form-urlencoded",
2569 processData: true,
2570 async: true,
2571 data: null,
2572 username: null,
2573 password: null,
2574 accepts: {
2575 xml: "application/xml, text/xml",
2576 html: "text/html",
2577 script: "text/javascript, application/javascript",
2578 json: "application/json, text/javascript",
2579 text: "text/plain",
2580 _default: "*/*"
2581 }
2582 },
2583
2584 // Last-Modified header cache for next request
2585 lastModified: {},
2586
2587 ajax: function( s ) {
2588 // Extend the settings, but re-extend 's' so that it can be
2589 // checked again later (in the test suite, specifically)
2590 s = jQuery.extend(true, s, jQuery.extend(true, {}, jQuery.ajaxSettings, s));
2591
2592 var jsonp, jsre = /=\?(&|$)/g, status, data,
2593 type = s.type.toUpperCase();
2594
2595 // convert data if not already a string
2596 if ( s.data && s.processData && typeof s.data != "string" )
2597 s.data = jQuery.param(s.data);
2598
2599 // Handle JSONP Parameter Callbacks
2600 if ( s.dataType == "jsonp" ) {
2601 if ( type == "GET" ) {
2602 if ( !s.url.match(jsre) )
2603 s.url += (s.url.match(/\?/) ? "&" : "?") + (s.jsonp || "callback") + "=?";
2604 } else if ( !s.data || !s.data.match(jsre) )
2605 s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
2606 s.dataType = "json";
2607 }
2608
2609 // Build temporary JSONP function
2610 if ( s.dataType == "json" && (s.data && s.data.match(jsre) || s.url.match(jsre)) ) {
2611 jsonp = "jsonp" + jsc++;
2612
2613 // Replace the =? sequence both in the query string and the data
2614 if ( s.data )
2615 s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");
2616 s.url = s.url.replace(jsre, "=" + jsonp + "$1");
2617
2618 // We need to make sure
2619 // that a JSONP style response is executed properly
2620 s.dataType = "script";
2621
2622 // Handle JSONP-style loading
2623 window[ jsonp ] = function(tmp){
2624 data = tmp;
2625 success();
2626 complete();
2627 // Garbage collect
2628 window[ jsonp ] = undefined;
2629 try{ delete window[ jsonp ]; } catch(e){}
2630 if ( head )
2631 head.removeChild( script );
2632 };
2633 }
2634
2635 if ( s.dataType == "script" && s.cache == null )
2636 s.cache = false;
2637
2638 if ( s.cache === false && type == "GET" ) {
2639 var ts = now();
2640 // try replacing _= if it is there
2641 var ret = s.url.replace(/(\?|&)_=.*?(&|$)/, "$1_=" + ts + "$2");
2642 // if nothing was replaced, add timestamp to the end
2643 s.url = ret + ((ret == s.url) ? (s.url.match(/\?/) ? "&" : "?") + "_=" + ts : "");
2644 }
2645
2646 // If data is available, append data to url for get requests
2647 if ( s.data && type == "GET" ) {
2648 s.url += (s.url.match(/\?/) ? "&" : "?") + s.data;
2649
2650 // IE likes to send both get and post data, prevent this
2651 s.data = null;
2652 }
2653
2654 // Watch for a new set of requests
2655 if ( s.global && ! jQuery.active++ )
2656 jQuery.event.trigger( "ajaxStart" );
2657
2658 // Matches an absolute URL, and saves the domain
2659 var remote = /^(?:\w+:)?\/\/([^\/?#]+)/;
2660
2661 // If we're requesting a remote document
2662 // and trying to load JSON or Script with a GET
2663 if ( s.dataType == "script" && type == "GET"
2664 && remote.test(s.url) && remote.exec(s.url)[1] != location.host ){
2665 var head = document.getElementsByTagName("head")[0];
2666 var script = document.createElement("script");
2667 script.src = s.url;
2668 if (s.scriptCharset)
2669 script.charset = s.scriptCharset;
2670
2671 // Handle Script loading
2672 if ( !jsonp ) {
2673 var done = false;
2674
2675 // Attach handlers for all browsers
2676 script.onload = script.onreadystatechange = function(){
2677 if ( !done && (!this.readyState ||
2678 this.readyState == "loaded" || this.readyState == "complete") ) {
2679 done = true;
2680 success();
2681 complete();
2682 head.removeChild( script );
2683 }
2684 };
2685 }
2686
2687 head.appendChild(script);
2688
2689 // We handle everything using the script element injection
2690 return undefined;
2691 }
2692
2693 var requestDone = false;
2694
2695 // Create the request object; Microsoft failed to properly
2696 // implement the XMLHttpRequest in IE7, so we use the ActiveXObject when it is available
2697 var xhr = window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
2698
2699 // Open the socket
2700 // Passing null username, generates a login popup on Opera (#2865)
2701 if( s.username )
2702 xhr.open(type, s.url, s.async, s.username, s.password);
2703 else
2704 xhr.open(type, s.url, s.async);
2705
2706 // Need an extra try/catch for cross domain requests in Firefox 3
2707 try {
2708 // Set the correct header, if data is being sent
2709 if ( s.data )
2710 xhr.setRequestHeader("Content-Type", s.contentType);
2711
2712 // Set the If-Modified-Since header, if ifModified mode.
2713 if ( s.ifModified )
2714 xhr.setRequestHeader("If-Modified-Since",
2715 jQuery.lastModified[s.url] || "Thu, 01 Jan 1970 00:00:00 GMT" );
2716
2717 // Set header so the called script knows that it's an XMLHttpRequest
2718 xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
2719
2720 // Set the Accepts header for the server, depending on the dataType
2721 xhr.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ?
2722 s.accepts[ s.dataType ] + ", */*" :
2723 s.accepts._default );
2724 } catch(e){}
2725
2726 // Allow custom headers/mimetypes
2727 if ( s.beforeSend && s.beforeSend(xhr, s) === false ) {
2728 // cleanup active request counter
2729 s.global && jQuery.active--;
2730 // close opended socket
2731 xhr.abort();
2732 return false;
2733 }
2734
2735 if ( s.global )
2736 jQuery.event.trigger("ajaxSend", [xhr, s]);
2737
2738 // Wait for a response to come back
2739 var onreadystatechange = function(isTimeout){
2740 // The transfer is complete and the data is available, or the request timed out
2741 if ( !requestDone && xhr && (xhr.readyState == 4 || isTimeout == "timeout") ) {
2742 requestDone = true;
2743
2744 // clear poll interval
2745 if (ival) {
2746 clearInterval(ival);
2747 ival = null;
2748 }
2749
2750 status = isTimeout == "timeout" ? "timeout" :
2751 !jQuery.httpSuccess( xhr ) ? "error" :
2752 s.ifModified && jQuery.httpNotModified( xhr, s.url ) ? "notmodified" :
2753 "success";
2754
2755 if ( status == "success" ) {
2756 // Watch for, and catch, XML document parse errors
2757 try {
2758 // process the data (runs the xml through httpData regardless of callback)
2759 data = jQuery.httpData( xhr, s.dataType, s.dataFilter );
2760 } catch(e) {
2761 status = "parsererror";
2762 }
2763 }
2764
2765 // Make sure that the request was successful or notmodified
2766 if ( status == "success" ) {
2767 // Cache Last-Modified header, if ifModified mode.
2768 var modRes;
2769 try {
2770 modRes = xhr.getResponseHeader("Last-Modified");
2771 } catch(e) {} // swallow exception thrown by FF if header is not available
2772
2773 if ( s.ifModified && modRes )
2774 jQuery.lastModified[s.url] = modRes;
2775
2776 // JSONP handles its own success callback
2777 if ( !jsonp )
2778 success();
2779 } else
2780 jQuery.handleError(s, xhr, status);
2781
2782 // Fire the complete handlers
2783 complete();
2784
2785 // Stop memory leaks
2786 if ( s.async )
2787 xhr = null;
2788 }
2789 };
2790
2791 if ( s.async ) {
2792 // don't attach the handler to the request, just poll it instead
2793 var ival = setInterval(onreadystatechange, 13);
2794
2795 // Timeout checker
2796 if ( s.timeout > 0 )
2797 setTimeout(function(){
2798 // Check to see if the request is still happening
2799 if ( xhr ) {
2800 // Cancel the request
2801 xhr.abort();
2802
2803 if( !requestDone )
2804 onreadystatechange( "timeout" );
2805 }
2806 }, s.timeout);
2807 }
2808
2809 // Send the data
2810 try {
2811 xhr.send(s.data);
2812 } catch(e) {
2813 jQuery.handleError(s, xhr, null, e);
2814 }
2815
2816 // firefox 1.5 doesn't fire statechange for sync requests
2817 if ( !s.async )
2818 onreadystatechange();
2819
2820 function success(){
2821 // If a local callback was specified, fire it and pass it the data
2822 if ( s.success )
2823 s.success( data, status );
2824
2825 // Fire the global callback
2826 if ( s.global )
2827 jQuery.event.trigger( "ajaxSuccess", [xhr, s] );
2828 }
2829
2830 function complete(){
2831 // Process result
2832 if ( s.complete )
2833 s.complete(xhr, status);
2834
2835 // The request was completed
2836 if ( s.global )
2837 jQuery.event.trigger( "ajaxComplete", [xhr, s] );
2838
2839 // Handle the global AJAX counter
2840 if ( s.global && ! --jQuery.active )
2841 jQuery.event.trigger( "ajaxStop" );
2842 }
2843
2844 // return XMLHttpRequest to allow aborting the request etc.
2845 return xhr;
2846 },
2847
2848 handleError: function( s, xhr, status, e ) {
2849 // If a local callback was specified, fire it
2850 if ( s.error ) s.error( xhr, status, e );
2851
2852 // Fire the global callback
2853 if ( s.global )
2854 jQuery.event.trigger( "ajaxError", [xhr, s, e] );
2855 },
2856
2857 // Counter for holding the number of active queries
2858 active: 0,
2859
2860 // Determines if an XMLHttpRequest was successful or not
2861 httpSuccess: function( xhr ) {
2862 try {
2863 // IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450
2864 return !xhr.status && location.protocol == "file:" ||
2865 ( xhr.status >= 200 && xhr.status < 300 ) || xhr.status == 304 || xhr.status == 1223 ||
2866 jQuery.browser.safari && xhr.status == undefined;
2867 } catch(e){}
2868 return false;
2869 },
2870
2871 // Determines if an XMLHttpRequest returns NotModified
2872 httpNotModified: function( xhr, url ) {
2873 try {
2874 var xhrRes = xhr.getResponseHeader("Last-Modified");
2875
2876 // Firefox always returns 200. check Last-Modified date
2877 return xhr.status == 304 || xhrRes == jQuery.lastModified[url] ||
2878 jQuery.browser.safari && xhr.status == undefined;
2879 } catch(e){}
2880 return false;
2881 },
2882
2883 httpData: function( xhr, type, filter ) {
2884 var ct = xhr.getResponseHeader("content-type"),
2885 xml = type == "xml" || !type && ct && ct.indexOf("xml") >= 0,
2886 data = xml ? xhr.responseXML : xhr.responseText;
2887
2888 if ( xml && data.documentElement.tagName == "parsererror" )
2889 throw "parsererror";
2890
2891 // Allow a pre-filtering function to sanitize the response
2892 if( filter )
2893 data = filter( data, type );
2894
2895 // If the type is "script", eval it in global context
2896 if ( type == "script" )
2897 jQuery.globalEval( data );
2898
2899 // Get the JavaScript object, if JSON is used.
2900 if ( type == "json" )
2901 data = eval("(" + data + ")");
2902
2903 return data;
2904 },
2905
2906 // Serialize an array of form elements or a set of
2907 // key/values into a query string
2908 param: function( a ) {
2909 var s = [ ];
2910
2911 function add( key, value ){
2912 s[ s.length ] = encodeURIComponent(key) + '=' + encodeURIComponent(value);
2913 };
2914
2915 // If an array was passed in, assume that it is an array
2916 // of form elements
2917 if ( a.constructor == Array || a.jquery )
2918 // Serialize the form elements
2919 jQuery.each( a, function(){
2920 add( this.name, this.value );
2921 });
2922
2923 // Otherwise, assume that it's an object of key/value pairs
2924 else
2925 // Serialize the key/values
2926 for ( var j in a )
2927 // If the value is an array then the key names need to be repeated
2928 if ( a[j] && a[j].constructor == Array )
2929 jQuery.each( a[j], function(){
2930 add( j, this );
2931 });
2932 else
2933 add( j, jQuery.isFunction(a[j]) ? a[j]() : a[j] );
2934
2935 // Return the resulting serialization
2936 return s.join("&").replace(/%20/g, "+");
2937 }
2938
2939 });
2940 jQuery.fn.extend({
2941 show: function(speed,callback){
2942 return speed ?
2943 this.animate({
2944 height: "show", width: "show", opacity: "show"
2945 }, speed, callback) :
2946
2947 this.filter(":hidden").each(function(){
2948 this.style.display = this.oldblock || "";
2949 if ( jQuery.css(this,"display") == "none" ) {
2950 var elem = jQuery("<" + this.tagName + " />").appendTo("body");
2951 this.style.display = elem.css("display");
2952 // handle an edge condition where css is - div { display:none; } or similar
2953 if (this.style.display == "none")
2954 this.style.display = "block";
2955 elem.remove();
2956 }
2957 }).end();
2958 },
2959
2960 hide: function(speed,callback){
2961 return speed ?
2962 this.animate({
2963 height: "hide", width: "hide", opacity: "hide"
2964 }, speed, callback) :
2965
2966 this.filter(":visible").each(function(){
2967 this.oldblock = this.oldblock || jQuery.css(this,"display");
2968 this.style.display = "none";
2969 }).end();
2970 },
2971
2972 // Save the old toggle function
2973 _toggle: jQuery.fn.toggle,
2974
2975 toggle: function( fn, fn2 ){
2976 return jQuery.isFunction(fn) && jQuery.isFunction(fn2) ?
2977 this._toggle.apply( this, arguments ) :
2978 fn ?
2979 this.animate({
2980 height: "toggle", width: "toggle", opacity: "toggle"
2981 }, fn, fn2) :
2982 this.each(function(){
2983 jQuery(this)[ jQuery(this).is(":hidden") ? "show" : "hide" ]();
2984 });
2985 },
2986
2987 slideDown: function(speed,callback){
2988 return this.animate({height: "show"}, speed, callback);
2989 },
2990
2991 slideUp: function(speed,callback){
2992 return this.animate({height: "hide"}, speed, callback);
2993 },
2994
2995 slideToggle: function(speed, callback){
2996 return this.animate({height: "toggle"}, speed, callback);
2997 },