Forgot to make sure that oldData actually had data in it before the copy attempt.
[jquery.git] / speed / jquery-basis.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-24 14:22:17 -0400 (Sat, 24 May 2008) $
10  * $Rev: 5685 $
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         }
1250 });
1251
1252 jQuery.each({
1253         parent: function(elem){return elem.parentNode;},
1254         parents: function(elem){return jQuery.dir(elem,"parentNode");},
1255         next: function(elem){return jQuery.nth(elem,2,"nextSibling");},
1256         prev: function(elem){return jQuery.nth(elem,2,"previousSibling");},
1257         nextAll: function(elem){return jQuery.dir(elem,"nextSibling");},
1258         prevAll: function(elem){return jQuery.dir(elem,"previousSibling");},
1259         siblings: function(elem){return jQuery.sibling(elem.parentNode.firstChild,elem);},
1260         children: function(elem){return jQuery.sibling(elem.firstChild);},
1261         contents: function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes);}
1262 }, function(name, fn){
1263         jQuery.fn[ name ] = function( selector ) {
1264                 var ret = jQuery.map( this, fn );
1265
1266                 if ( selector && typeof selector == "string" )
1267                         ret = jQuery.multiFilter( selector, ret );
1268
1269                 return this.pushStack( jQuery.unique( ret ) );
1270         };
1271 });
1272
1273 jQuery.each({
1274         appendTo: "append",
1275         prependTo: "prepend",
1276         insertBefore: "before",
1277         insertAfter: "after",
1278         replaceAll: "replaceWith"
1279 }, function(name, original){
1280         jQuery.fn[ name ] = function() {
1281                 var args = arguments;
1282
1283                 return this.each(function(){
1284                         for ( var i = 0, length = args.length; i < length; i++ )
1285                                 jQuery( args[ i ] )[ original ]( this );
1286                 });
1287         };
1288 });
1289
1290 jQuery.each({
1291         removeAttr: function( name ) {
1292                 jQuery.attr( this, name, "" );
1293                 if (this.nodeType == 1)
1294                         this.removeAttribute( name );
1295         },
1296
1297         addClass: function( classNames ) {
1298                 jQuery.className.add( this, classNames );
1299         },
1300
1301         removeClass: function( classNames ) {
1302                 jQuery.className.remove( this, classNames );
1303         },
1304
1305         toggleClass: function( classNames ) {
1306                 jQuery.className[ jQuery.className.has( this, classNames ) ? "remove" : "add" ]( this, classNames );
1307         },
1308
1309         remove: function( selector ) {
1310                 if ( !selector || jQuery.filter( selector, [ this ] ).r.length ) {
1311                         // Prevent memory leaks
1312                         jQuery( "*", this ).add(this).each(function(){
1313                                 jQuery.event.remove(this);
1314                                 jQuery.removeData(this);
1315                         });
1316                         if (this.parentNode)
1317                                 this.parentNode.removeChild( this );
1318                 }
1319         },
1320
1321         empty: function() {
1322                 // Remove element nodes and prevent memory leaks
1323                 jQuery( ">*", this ).remove();
1324
1325                 // Remove any remaining nodes
1326                 while ( this.firstChild )
1327                         this.removeChild( this.firstChild );
1328         }
1329 }, function(name, fn){
1330         jQuery.fn[ name ] = function(){
1331                 return this.each( fn, arguments );
1332         };
1333 });
1334
1335 jQuery.each([ "Height", "Width" ], function(i, name){
1336         var type = name.toLowerCase();
1337
1338         jQuery.fn[ type ] = function( size ) {
1339                 // Get window width or height
1340                 return this[0] == window ?
1341                         // Opera reports document.body.client[Width/Height] properly in both quirks and standards
1342                         jQuery.browser.opera && document.body[ "client" + name ] ||
1343
1344                         // Safari reports inner[Width/Height] just fine (Mozilla and Opera include scroll bar widths)
1345                         jQuery.browser.safari && window[ "inner" + name ] ||
1346
1347                         // Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
1348                         document.compatMode == "CSS1Compat" && document.documentElement[ "client" + name ] || document.body[ "client" + name ] :
1349
1350                         // Get document width or height
1351                         this[0] == document ?
1352                                 // Either scroll[Width/Height] or offset[Width/Height], whichever is greater
1353                                 Math.max(
1354                                         Math.max(document.body["scroll" + name], document.documentElement["scroll" + name]),
1355                                         Math.max(document.body["offset" + name], document.documentElement["offset" + name])
1356                                 ) :
1357
1358                                 // Get or set width or height on the element
1359                                 size == undefined ?
1360                                         // Get width or height on the element
1361                                         (this.length ? jQuery.css( this[0], type ) : null) :
1362
1363                                         // Set the width or height on the element (default to pixels if value is unitless)
1364                                         this.css( type, size.constructor == String ? size : size + "px" );
1365         };
1366 });
1367
1368 // Helper function used by the dimensions and offset modules
1369 function num(elem, prop) {
1370         return elem[0] && parseInt( jQuery.curCSS(elem[0], prop, true), 10 ) || 0;
1371 }var chars = jQuery.browser.safari && parseInt(jQuery.browser.version) < 417 ?
1372                 "(?:[\\w*_-]|\\\\.)" :
1373                 "(?:[\\w\u0128-\uFFFF*_-]|\\\\.)",
1374         quickChild = new RegExp("^>\\s*(" + chars + "+)"),
1375         quickID = new RegExp("^(" + chars + "+)(#)(" + chars + "+)"),
1376         quickClass = new RegExp("^([#.]?)(" + chars + "*)");
1377
1378 jQuery.extend({
1379         expr: {
1380                 "": function(a,i,m){return m[2]=="*"||jQuery.nodeName(a,m[2]);},
1381                 "#": function(a,i,m){return a.getAttribute("id")==m[2];},
1382                 ":": {
1383                         // Position Checks
1384                         lt: function(a,i,m){return i<m[3]-0;},
1385                         gt: function(a,i,m){return i>m[3]-0;},
1386                         nth: function(a,i,m){return m[3]-0==i;},
1387                         eq: function(a,i,m){return m[3]-0==i;},
1388                         first: function(a,i){return i==0;},
1389                         last: function(a,i,m,r){return i==r.length-1;},
1390                         even: function(a,i){return i%2==0;},
1391                         odd: function(a,i){return i%2;},
1392
1393                         // Child Checks
1394                         "first-child": function(a){return a.parentNode.getElementsByTagName("*")[0]==a;},
1395                         "last-child": function(a){return jQuery.nth(a.parentNode.lastChild,1,"previousSibling")==a;},
1396                         "only-child": function(a){return !jQuery.nth(a.parentNode.lastChild,2,"previousSibling");},
1397
1398                         // Parent Checks
1399                         parent: function(a){return a.firstChild;},
1400                         empty: function(a){return !a.firstChild;},
1401
1402                         // Text Check
1403                         contains: function(a,i,m){return (a.textContent||a.innerText||jQuery(a).text()||"").indexOf(m[3])>=0;},
1404
1405                         // Visibility
1406                         visible: function(a){return "hidden"!=a.type&&jQuery.css(a,"display")!="none"&&jQuery.css(a,"visibility")!="hidden";},
1407                         hidden: function(a){return "hidden"==a.type||jQuery.css(a,"display")=="none"||jQuery.css(a,"visibility")=="hidden";},
1408
1409                         // Form attributes
1410                         enabled: function(a){return !a.disabled;},
1411                         disabled: function(a){return a.disabled;},
1412                         checked: function(a){return a.checked;},
1413                         selected: function(a){return a.selected||jQuery.attr(a,"selected");},
1414
1415                         // Form elements
1416                         text: function(a){return "text"==a.type;},
1417                         radio: function(a){return "radio"==a.type;},
1418                         checkbox: function(a){return "checkbox"==a.type;},
1419                         file: function(a){return "file"==a.type;},
1420                         password: function(a){return "password"==a.type;},
1421                         submit: function(a){return "submit"==a.type;},
1422                         image: function(a){return "image"==a.type;},
1423                         reset: function(a){return "reset"==a.type;},
1424                         button: function(a){return "button"==a.type||jQuery.nodeName(a,"button");},
1425                         input: function(a){return /input|select|textarea|button/i.test(a.nodeName);},
1426
1427                         // :has()
1428                         has: function(a,i,m){return jQuery.find(m[3],a).length;},
1429
1430                         // :header
1431                         header: function(a){return /h\d/i.test(a.nodeName);},
1432
1433                         // :animated
1434                         animated: function(a){return jQuery.grep(jQuery.timers,function(fn){return a==fn.elem;}).length;}
1435                 }
1436         },
1437
1438         // The regular expressions that power the parsing engine
1439         parse: [
1440                 // Match: [@value='test'], [@foo]
1441                 /^(\[) *@?([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/,
1442
1443                 // Match: :contains('foo')
1444                 /^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/,
1445
1446                 // Match: :even, :last-child, #id, .class
1447                 new RegExp("^([:.#]*)(" + chars + "+)")
1448         ],
1449
1450         multiFilter: function( expr, elems, not ) {
1451                 var old, cur = [];
1452
1453                 while ( expr && expr != old ) {
1454                         old = expr;
1455                         var f = jQuery.filter( expr, elems, not );
1456                         expr = f.t.replace(/^\s*,\s*/, "" );
1457                         cur = not ? elems = f.r : jQuery.merge( cur, f.r );
1458                 }
1459
1460                 return cur;
1461         },
1462
1463         find: function( t, context ) {
1464                 // Quickly handle non-string expressions
1465                 if ( typeof t != "string" )
1466                         return [ t ];
1467
1468                 // check to make sure context is a DOM element or a document
1469                 if ( context && context.nodeType != 1 && context.nodeType != 9)
1470                         return [ ];
1471
1472                 // Set the correct context (if none is provided)
1473                 context = context || document;
1474
1475                 // Initialize the search
1476                 var ret = [context], done = [], last, nodeName;
1477
1478                 // Continue while a selector expression exists, and while
1479                 // we're no longer looping upon ourselves
1480                 while ( t && last != t ) {
1481                         var r = [];
1482                         last = t;
1483
1484                         t = jQuery.trim(t);
1485
1486                         var foundToken = false,
1487
1488                         // An attempt at speeding up child selectors that
1489                         // point to a specific element tag
1490                                 re = quickChild,
1491
1492                                 m = re.exec(t);
1493
1494                         if ( m ) {
1495                                 nodeName = m[1].toUpperCase();
1496
1497                                 // Perform our own iteration and filter
1498                                 for ( var i = 0; ret[i]; i++ )
1499                                         for ( var c = ret[i].firstChild; c; c = c.nextSibling )
1500                                                 if ( c.nodeType == 1 && (nodeName == "*" || c.nodeName.toUpperCase() == nodeName) )
1501                                                         r.push( c );
1502
1503                                 ret = r;
1504                                 t = t.replace( re, "" );
1505                                 if ( t.indexOf(" ") == 0 ) continue;
1506                                 foundToken = true;
1507                         } else {
1508                                 re = /^([>+~])\s*(\w*)/i;
1509
1510                                 if ( (m = re.exec(t)) != null ) {
1511                                         r = [];
1512
1513                                         var merge = {};
1514                                         nodeName = m[2].toUpperCase();
1515                                         m = m[1];
1516
1517                                         for ( var j = 0, rl = ret.length; j < rl; j++ ) {
1518                                                 var n = m == "~" || m == "+" ? ret[j].nextSibling : ret[j].firstChild;
1519                                                 for ( ; n; n = n.nextSibling )
1520                                                         if ( n.nodeType == 1 ) {
1521                                                                 var id = jQuery.data(n);
1522
1523                                                                 if ( m == "~" && merge[id] ) break;
1524
1525                                                                 if (!nodeName || n.nodeName.toUpperCase() == nodeName ) {
1526                                                                         if ( m == "~" ) merge[id] = true;
1527                                                                         r.push( n );
1528                                                                 }
1529
1530                                                                 if ( m == "+" ) break;
1531                                                         }
1532                                         }
1533
1534                                         ret = r;
1535
1536                                         // And remove the token
1537                                         t = jQuery.trim( t.replace( re, "" ) );
1538                                         foundToken = true;
1539                                 }
1540                         }
1541
1542                         // See if there's still an expression, and that we haven't already
1543                         // matched a token
1544                         if ( t && !foundToken ) {
1545                                 // Handle multiple expressions
1546                                 if ( !t.indexOf(",") ) {
1547                                         // Clean the result set
1548                                         if ( context == ret[0] ) ret.shift();
1549
1550                                         // Merge the result sets
1551                                         done = jQuery.merge( done, ret );
1552
1553                                         // Reset the context
1554                                         r = ret = [context];
1555
1556                                         // Touch up the selector string
1557                                         t = " " + t.substr(1,t.length);
1558
1559                                 } else {
1560                                         // Optimize for the case nodeName#idName
1561                                         var re2 = quickID;
1562                                         var m = re2.exec(t);
1563
1564                                         // Re-organize the results, so that they're consistent
1565                                         if ( m ) {
1566                                                 m = [ 0, m[2], m[3], m[1] ];
1567
1568                                         } else {
1569                                                 // Otherwise, do a traditional filter check for
1570                                                 // ID, class, and element selectors
1571                                                 re2 = quickClass;
1572                                                 m = re2.exec(t);
1573                                         }
1574
1575                                         m[2] = m[2].replace(/\\/g, "");
1576
1577                                         var elem = ret[ret.length-1];
1578
1579                                         // Try to do a global search by ID, where we can
1580                                         if ( m[1] == "#" && elem && elem.getElementById && !jQuery.isXMLDoc(elem) ) {
1581                                                 // Optimization for HTML document case
1582                                                 var oid = elem.getElementById(m[2]);
1583
1584                                                 // Do a quick check for the existence of the actual ID attribute
1585                                                 // to avoid selecting by the name attribute in IE
1586                                                 // also check to insure id is a string to avoid selecting an element with the name of 'id' inside a form
1587                                                 if ( (jQuery.browser.msie||jQuery.browser.opera) && oid && typeof oid.id == "string" && oid.id != m[2] )
1588                                                         oid = jQuery('[@id="'+m[2]+'"]', elem)[0];
1589
1590                                                 // Do a quick check for node name (where applicable) so
1591                                                 // that div#foo searches will be really fast
1592                                                 ret = r = oid && (!m[3] || jQuery.nodeName(oid, m[3])) ? [oid] : [];
1593                                         } else {
1594                                                 // We need to find all descendant elements
1595                                                 for ( var i = 0; ret[i]; i++ ) {
1596                                                         // Grab the tag name being searched for
1597                                                         var tag = m[1] == "#" && m[3] ? m[3] : m[1] != "" || m[0] == "" ? "*" : m[2];
1598
1599                                                         // Handle IE7 being really dumb about <object>s
1600                                                         if ( tag == "*" && ret[i].nodeName.toLowerCase() == "object" )
1601                                                                 tag = "param";
1602
1603                                                         r = jQuery.merge( r, ret[i].getElementsByTagName( tag ));
1604                                                 }
1605
1606                                                 // It's faster to filter by class and be done with it
1607                                                 if ( m[1] == "." )
1608                                                         r = jQuery.classFilter( r, m[2] );
1609
1610                                                 // Same with ID filtering
1611                                                 if ( m[1] == "#" ) {
1612                                                         var tmp = [];
1613
1614                                                         // Try to find the element with the ID
1615                                                         for ( var i = 0; r[i]; i++ )
1616                                                                 if ( r[i].getAttribute("id") == m[2] ) {
1617                                                                         tmp = [ r[i] ];
1618                                                                         break;
1619                                                                 }
1620
1621                                                         r = tmp;
1622                                                 }
1623
1624                                                 ret = r;
1625                                         }
1626
1627                                         t = t.replace( re2, "" );
1628                                 }
1629
1630                         }
1631
1632                         // If a selector string still exists
1633                         if ( t ) {
1634                                 // Attempt to filter it
1635                                 var val = jQuery.filter(t,r);
1636                                 ret = r = val.r;
1637                                 t = jQuery.trim(val.t);
1638                         }
1639                 }
1640
1641                 // An error occurred with the selector;
1642                 // just return an empty set instead
1643                 if ( t )
1644                         ret = [];
1645
1646                 // Remove the root context
1647                 if ( ret && context == ret[0] )
1648                         ret.shift();
1649
1650                 // And combine the results
1651                 done = jQuery.merge( done, ret );
1652
1653                 return done;
1654         },
1655
1656         classFilter: function(r,m,not){
1657                 m = " " + m + " ";
1658                 var tmp = [];
1659                 for ( var i = 0; r[i]; i++ ) {
1660                         var pass = (" " + r[i].className + " ").indexOf( m ) >= 0;
1661                         if ( !not && pass || not && !pass )
1662                                 tmp.push( r[i] );
1663                 }
1664                 return tmp;
1665         },
1666
1667         filter: function(t,r,not) {
1668                 var last;
1669
1670                 // Look for common filter expressions
1671                 while ( t && t != last ) {
1672                         last = t;
1673
1674                         var p = jQuery.parse, m;
1675
1676                         for ( var i = 0; p[i]; i++ ) {
1677                                 m = p[i].exec( t );
1678
1679                                 if ( m ) {
1680                                         // Remove what we just matched
1681                                         t = t.substring( m[0].length );
1682
1683                                         m[2] = m[2].replace(/\\/g, "");
1684                                         break;
1685                                 }
1686                         }
1687
1688                         if ( !m )
1689                                 break;
1690
1691                         // :not() is a special case that can be optimized by
1692                         // keeping it out of the expression list
1693                         if ( m[1] == ":" && m[2] == "not" )
1694                                 // optimize if only one selector found (most common case)
1695                                 r = isSimple.test( m[3] ) ?
1696                                         jQuery.filter(m[3], r, true).r :
1697                                         jQuery( r ).not( m[3] );
1698
1699                         // We can get a big speed boost by filtering by class here
1700                         else if ( m[1] == "." )
1701                                 r = jQuery.classFilter(r, m[2], not);
1702
1703                         else if ( m[1] == "[" ) {
1704                                 var tmp = [], type = m[3];
1705
1706                                 for ( var i = 0, rl = r.length; i < rl; i++ ) {
1707                                         var a = r[i], z = a[ jQuery.props[m[2]] || m[2] ];
1708
1709                                         if ( z == null || /href|src|selected/.test(m[2]) )
1710                                                 z = jQuery.attr(a,m[2]) || '';
1711
1712                                         if ( (type == "" && !!z ||
1713                                                  type == "=" && z == m[5] ||
1714                                                  type == "!=" && z != m[5] ||
1715                                                  type == "^=" && z && !z.indexOf(m[5]) ||
1716                                                  type == "$=" && z.substr(z.length - m[5].length) == m[5] ||
1717                                                  (type == "*=" || type == "~=") && z.indexOf(m[5]) >= 0) ^ not )
1718                                                         tmp.push( a );
1719                                 }
1720
1721                                 r = tmp;
1722
1723                         // We can get a speed boost by handling nth-child here
1724                         } else if ( m[1] == ":" && m[2] == "nth-child" ) {
1725                                 var merge = {}, tmp = [],
1726                                         // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
1727                                         test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
1728                                                 m[3] == "even" && "2n" || m[3] == "odd" && "2n+1" ||
1729                                                 !/\D/.test(m[3]) && "0n+" + m[3] || m[3]),
1730                                         // calculate the numbers (first)n+(last) including if they are negative
1731                                         first = (test[1] + (test[2] || 1)) - 0, last = test[3] - 0;
1732
1733                                 // loop through all the elements left in the jQuery object
1734                                 for ( var i = 0, rl = r.length; i < rl; i++ ) {
1735                                         var node = r[i], parentNode = node.parentNode, id = jQuery.data(parentNode);
1736
1737                                         if ( !merge[id] ) {
1738                                                 var c = 1;
1739
1740                                                 for ( var n = parentNode.firstChild; n; n = n.nextSibling )
1741                                                         if ( n.nodeType == 1 )
1742                                                                 n.nodeIndex = c++;
1743
1744                                                 merge[id] = true;
1745                                         }
1746
1747                                         var add = false;
1748
1749                                         if ( first == 0 ) {
1750                                                 if ( node.nodeIndex == last )
1751                                                         add = true;
1752                                         } else if ( (node.nodeIndex - last) % first == 0 && (node.nodeIndex - last) / first >= 0 )
1753                                                 add = true;
1754
1755                                         if ( add ^ not )
1756                                                 tmp.push( node );
1757                                 }
1758
1759                                 r = tmp;
1760
1761                         // Otherwise, find the expression to execute
1762                         } else {
1763                                 var fn = jQuery.expr[ m[1] ];
1764                                 if ( typeof fn == "object" )
1765                                         fn = fn[ m[2] ];
1766
1767                                 if ( typeof fn == "string" )
1768                                         fn = eval("false||function(a,i){return " + fn + ";}");
1769
1770                                 // Execute it against the current filter
1771                                 r = jQuery.grep( r, function(elem, i){
1772                                         return fn(elem, i, m, r);
1773                                 }, not );
1774                         }
1775                 }
1776
1777                 // Return an array of filtered elements (r)
1778                 // and the modified expression string (t)
1779                 return { r: r, t: t };
1780         },
1781
1782         dir: function( elem, dir ){
1783                 var matched = [],
1784                         cur = elem[dir];
1785                 while ( cur && cur != document ) {
1786                         if ( cur.nodeType == 1 )
1787                                 matched.push( cur );
1788                         cur = cur[dir];
1789                 }
1790                 return matched;
1791         },
1792
1793         nth: function(cur,result,dir,elem){
1794                 result = result || 1;
1795                 var num = 0;
1796
1797                 for ( ; cur; cur = cur[dir] )
1798                         if ( cur.nodeType == 1 && ++num == result )
1799                                 break;
1800
1801                 return cur;
1802         },
1803
1804         sibling: function( n, elem ) {
1805                 var r = [];
1806
1807                 for ( ; n; n = n.nextSibling ) {
1808                         if ( n.nodeType == 1 && n != elem )
1809                                 r.push( n );
1810                 }
1811
1812                 return r;
1813         }
1814 });
1815 /*
1816  * A number of helper functions used for managing events.
1817  * Many of the ideas behind this code orignated from
1818  * Dean Edwards' addEvent library.
1819  */
1820 jQuery.event = {
1821
1822         // Bind an event to an element
1823         // Original by Dean Edwards
1824         add: function(elem, types, handler, data) {
1825                 if ( elem.nodeType == 3 || elem.nodeType == 8 )
1826                         return;
1827
1828                 // For whatever reason, IE has trouble passing the window object
1829                 // around, causing it to be cloned in the process
1830                 if ( jQuery.browser.msie && elem.setInterval )
1831                         elem = window;
1832
1833                 // Make sure that the function being executed has a unique ID
1834                 if ( !handler.guid )
1835                         handler.guid = this.guid++;
1836
1837                 // if data is passed, bind to handler
1838                 if( data != undefined ) {
1839                         // Create temporary function pointer to original handler
1840                         var fn = handler;
1841
1842                         // Create unique handler function, wrapped around original handler
1843                         handler = this.proxy( fn, function() {
1844                                 // Pass arguments and context to original handler
1845                                 return fn.apply(this, arguments);
1846                         });
1847
1848                         // Store data in unique handler
1849                         handler.data = data;
1850                 }
1851
1852                 // Init the element's event structure
1853                 var events = jQuery.data(elem, "events") || jQuery.data(elem, "events", {}),
1854                         handle = jQuery.data(elem, "handle") || jQuery.data(elem, "handle", function(){
1855                                 // Handle the second event of a trigger and when
1856                                 // an event is called after a page has unloaded
1857                                 if ( typeof jQuery != "undefined" && !jQuery.event.triggered )
1858                                         return jQuery.event.handle.apply(arguments.callee.elem, arguments);
1859                         });
1860                 // Add elem as a property of the handle function
1861                 // This is to prevent a memory leak with non-native
1862                 // event in IE.
1863                 handle.elem = elem;
1864
1865                 // Handle multiple events separated by a space
1866                 // jQuery(...).bind("mouseover mouseout", fn);
1867                 jQuery.each(types.split(/\s+/), function(index, type) {
1868                         // Namespaced event handlers
1869                         var parts = type.split(".");
1870                         type = parts[0];
1871                         handler.type = parts[1];
1872
1873                         // Get the current list of functions bound to this event
1874                         var handlers = events[type];
1875
1876                         // Init the event handler queue
1877                         if (!handlers) {
1878                                 handlers = events[type] = {};
1879
1880                                 // Check for a special event handler
1881                                 // Only use addEventListener/attachEvent if the special
1882                                 // events handler returns false
1883                                 if ( !jQuery.event.special[type] || jQuery.event.special[type].setup.call(elem) === false ) {
1884                                         // Bind the global event handler to the element
1885                                         if (elem.addEventListener)
1886                                                 elem.addEventListener(type, handle, false);
1887                                         else if (elem.attachEvent)
1888                                                 elem.attachEvent("on" + type, handle);
1889                                 }
1890                         }
1891
1892                         // Add the function to the element's handler list
1893                         handlers[handler.guid] = handler;
1894
1895                         // Keep track of which events have been used, for global triggering
1896                         jQuery.event.global[type] = true;
1897                 });
1898
1899                 // Nullify elem to prevent memory leaks in IE
1900                 elem = null;
1901         },
1902
1903         guid: 1,
1904         global: {},
1905
1906         // Detach an event or set of events from an element
1907         remove: function(elem, types, handler) {
1908                 // don't do events on text and comment nodes
1909                 if ( elem.nodeType == 3 || elem.nodeType == 8 )
1910                         return;
1911
1912                 var events = jQuery.data(elem, "events"), ret, index;
1913
1914                 if ( events ) {
1915                         // Unbind all events for the element
1916                         if ( types == undefined || (typeof types == "string" && types.charAt(0) == ".") )
1917                                 for ( var type in events )
1918                                         this.remove( elem, type + (types || "") );
1919                         else {
1920                                 // types is actually an event object here
1921                                 if ( types.type ) {
1922                                         handler = types.handler;
1923                                         types = types.type;
1924                                 }
1925
1926                                 // Handle multiple events seperated by a space
1927                                 // jQuery(...).unbind("mouseover mouseout", fn);
1928                                 jQuery.each(types.split(/\s+/), function(index, type){
1929                                         // Namespaced event handlers
1930                                         var parts = type.split(".");
1931                                         type = parts[0];
1932
1933                                         if ( events[type] ) {
1934                                                 // remove the given handler for the given type
1935                                                 if ( handler )
1936                                                         delete events[type][handler.guid];
1937
1938                                                 // remove all handlers for the given type
1939                                                 else
1940                                                         for ( handler in events[type] )
1941                                                                 // Handle the removal of namespaced events
1942                                                                 if ( !parts[1] || events[type][handler].type == parts[1] )
1943                                                                         delete events[type][handler];
1944
1945                                                 // remove generic event handler if no more handlers exist
1946                                                 for ( ret in events[type] ) break;
1947                                                 if ( !ret ) {
1948                                                         if ( !jQuery.event.special[type] || jQuery.event.special[type].teardown.call(elem) === false ) {
1949                                                                 if (elem.removeEventListener)
1950                                                                         elem.removeEventListener(type, jQuery.data(elem, "handle"), false);
1951                                                                 else if (elem.detachEvent)
1952                                                                         elem.detachEvent("on" + type, jQuery.data(elem, "handle"));
1953                                                         }
1954                                                         ret = null;
1955                                                         delete events[type];
1956                                                 }
1957                                         }
1958                                 });
1959                         }
1960
1961                         // Remove the expando if it's no longer used
1962                         for ( ret in events ) break;
1963                         if ( !ret ) {
1964                                 var handle = jQuery.data( elem, "handle" );
1965                                 if ( handle ) handle.elem = null;
1966                                 jQuery.removeData( elem, "events" );
1967                                 jQuery.removeData( elem, "handle" );
1968                         }
1969                 }
1970         },
1971
1972         trigger: function(type, data, elem, donative, extra) {
1973                 // Clone the incoming data, if any
1974                 data = jQuery.makeArray(data);
1975
1976                 if ( type.indexOf("!") >= 0 ) {
1977                         type = type.slice(0, -1);
1978                         var exclusive = true;
1979                 }
1980
1981                 // Handle a global trigger
1982                 if ( !elem ) {
1983                         // Only trigger if we've ever bound an event for it
1984                         if ( this.global[type] )
1985                                 jQuery("*").add([window, document]).trigger(type, data);
1986
1987                 // Handle triggering a single element
1988                 } else {
1989                         // don't do events on text and comment nodes
1990                         if ( elem.nodeType == 3 || elem.nodeType == 8 )
1991                                 return undefined;
1992
1993                         var val, ret, fn = jQuery.isFunction( elem[ type ] || null ),
1994                                 // Check to see if we need to provide a fake event, or not
1995                                 event = !data[0] || !data[0].preventDefault;
1996
1997                         // Pass along a fake event
1998                         if ( event ) {
1999                                 data.unshift({
2000                                         type: type,
2001                                         target: elem,
2002                                         preventDefault: function(){},
2003                                         stopPropagation: function(){},
2004                                         timeStamp: now()
2005                                 });
2006                                 data[0][expando] = true; // no need to fix fake event
2007                         }
2008
2009                         // Enforce the right trigger type
2010                         data[0].type = type;
2011                         if ( exclusive )
2012                                 data[0].exclusive = true;
2013
2014                         // Trigger the event, it is assumed that "handle" is a function
2015                         var handle = jQuery.data(elem, "handle");
2016                         if ( handle )
2017                                 val = handle.apply( elem, data );
2018
2019                         // Handle triggering native .onfoo handlers (and on links since we don't call .click() for links)
2020                         if ( (!fn || (jQuery.nodeName(elem, 'a') && type == "click")) && elem["on"+type] && elem["on"+type].apply( elem, data ) === false )
2021                                 val = false;
2022
2023                         // Extra functions don't get the custom event object
2024                         if ( event )
2025                                 data.shift();
2026
2027                         // Handle triggering of extra function
2028                         if ( extra && jQuery.isFunction( extra ) ) {
2029                                 // call the extra function and tack the current return value on the end for possible inspection
2030                                 ret = extra.apply( elem, val == null ? data : data.concat( val ) );
2031                                 // if anything is returned, give it precedence and have it overwrite the previous value
2032                                 if (ret !== undefined)
2033                                         val = ret;
2034                         }
2035
2036                         // Trigger the native events (except for clicks on links)
2037                         if ( fn && donative !== false && val !== false && !(jQuery.nodeName(elem, 'a') && type == "click") ) {
2038                                 this.triggered = true;
2039                                 try {
2040                                         elem[ type ]();
2041                                 // prevent IE from throwing an error for some hidden elements
2042                                 } catch (e) {}
2043                         }
2044
2045                         this.triggered = false;
2046                 }
2047
2048                 return val;
2049         },
2050
2051         handle: function(event) {
2052                 // returned undefined or false
2053                 var val, ret, namespace, all, handlers;
2054
2055                 event = arguments[0] = jQuery.event.fix( event || window.event );
2056
2057                 // Namespaced event handlers
2058                 namespace = event.type.split(".");
2059                 event.type = namespace[0];
2060                 namespace = namespace[1];
2061                 // Cache this now, all = true means, any handler
2062                 all = !namespace && !event.exclusive;
2063
2064                 handlers = ( jQuery.data(this, "events") || {} )[event.type];
2065
2066                 for ( var j in handlers ) {
2067                         var handler = handlers[j];
2068
2069                         // Filter the functions by class
2070                         if ( all || handler.type == namespace ) {
2071                                 // Pass in a reference to the handler function itself
2072                                 // So that we can later remove it
2073                                 event.handler = handler;
2074                                 event.data = handler.data;
2075
2076                                 ret = handler.apply( this, arguments );
2077
2078                                 if ( val !== false )
2079                                         val = ret;
2080
2081                                 if ( ret === false ) {
2082                                         event.preventDefault();
2083                                         event.stopPropagation();
2084                                 }
2085                         }
2086                 }
2087
2088                 return val;
2089         },
2090
2091         fix: function(event) {
2092                 if ( event[expando] == true )
2093                         return event;
2094
2095                 // store a copy of the original event object
2096                 // and "clone" to set read-only properties
2097                 var originalEvent = event;
2098                 event = { originalEvent: originalEvent };
2099                 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(" ");
2100                 for ( var i=props.length; i; i-- )
2101                         event[ props[i] ] = originalEvent[ props[i] ];
2102
2103                 // Mark it as fixed
2104                 event[expando] = true;
2105
2106                 // add preventDefault and stopPropagation since
2107                 // they will not work on the clone
2108                 event.preventDefault = function() {
2109                         // if preventDefault exists run it on the original event
2110                         if (originalEvent.preventDefault)
2111                                 originalEvent.preventDefault();
2112                         // otherwise set the returnValue property of the original event to false (IE)
2113                         originalEvent.returnValue = false;
2114                 };
2115                 event.stopPropagation = function() {
2116                         // if stopPropagation exists run it on the original event
2117                         if (originalEvent.stopPropagation)
2118                                 originalEvent.stopPropagation();
2119                         // otherwise set the cancelBubble property of the original event to true (IE)
2120                         originalEvent.cancelBubble = true;
2121                 };
2122
2123                 // Fix timeStamp
2124                 event.timeStamp = event.timeStamp || now();
2125
2126                 // Fix target property, if necessary
2127                 if ( !event.target )
2128                         event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
2129
2130                 // check if target is a textnode (safari)
2131                 if ( event.target.nodeType == 3 )
2132                         event.target = event.target.parentNode;
2133
2134                 // Add relatedTarget, if necessary
2135                 if ( !event.relatedTarget && event.fromElement )
2136                         event.relatedTarget = event.fromElement == event.target ? event.toElement : event.fromElement;
2137
2138                 // Calculate pageX/Y if missing and clientX/Y available
2139                 if ( event.pageX == null && event.clientX != null ) {
2140                         var doc = document.documentElement, body = document.body;
2141                         event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc.clientLeft || 0);
2142                         event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc.clientTop || 0);
2143                 }
2144
2145                 // Add which for key events
2146                 if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) )
2147                         event.which = event.charCode || event.keyCode;
2148
2149                 // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
2150                 if ( !event.metaKey && event.ctrlKey )
2151                         event.metaKey = event.ctrlKey;
2152
2153                 // Add which for click: 1 == left; 2 == middle; 3 == right
2154                 // Note: button is not normalized, so don't use it
2155                 if ( !event.which && event.button )
2156                         event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
2157
2158                 return event;
2159         },
2160
2161         proxy: function( fn, proxy ){
2162                 // Set the guid of unique handler to the same of original handler, so it can be removed
2163                 proxy.guid = fn.guid = fn.guid || proxy.guid || this.guid++;
2164                 // So proxy can be declared as an argument
2165                 return proxy;
2166         },
2167
2168         special: {
2169                 ready: {
2170                         setup: function() {
2171                                 // Make sure the ready event is setup
2172                                 bindReady();
2173                                 return;
2174                         },
2175
2176                         teardown: function() { return; }
2177                 },
2178
2179                 mouseenter: {
2180                         setup: function() {
2181                                 if ( jQuery.browser.msie ) return false;
2182                                 jQuery(this).bind("mouseover", jQuery.event.special.mouseenter.handler);
2183                                 return true;
2184                         },
2185
2186                         teardown: function() {
2187                                 if ( jQuery.browser.msie ) return false;
2188                                 jQuery(this).unbind("mouseover", jQuery.event.special.mouseenter.handler);
2189                                 return true;
2190                         },
2191
2192                         handler: function(event) {
2193                                 // If we actually just moused on to a sub-element, ignore it
2194                                 if ( withinElement(event, this) ) return true;
2195                                 // Execute the right handlers by setting the event type to mouseenter
2196                                 event.type = "mouseenter";
2197                                 return jQuery.event.handle.apply(this, arguments);
2198                         }
2199                 },
2200
2201                 mouseleave: {
2202                         setup: function() {
2203                                 if ( jQuery.browser.msie ) return false;
2204                                 jQuery(this).bind("mouseout", jQuery.event.special.mouseleave.handler);
2205                                 return true;
2206                         },
2207
2208                         teardown: function() {
2209                                 if ( jQuery.browser.msie ) return false;
2210                                 jQuery(this).unbind("mouseout", jQuery.event.special.mouseleave.handler);
2211                                 return true;
2212                         },
2213
2214                         handler: function(event) {
2215                                 // If we actually just moused on to a sub-element, ignore it
2216                                 if ( withinElement(event, this) ) return true;
2217                                 // Execute the right handlers by setting the event type to mouseleave
2218                                 event.type = "mouseleave";
2219                                 return jQuery.event.handle.apply(this, arguments);
2220                         }
2221                 }
2222         }
2223 };
2224
2225 jQuery.fn.extend({
2226         bind: function( type, data, fn ) {
2227                 return type == "unload" ? this.one(type, data, fn) : this.each(function(){
2228                         jQuery.event.add( this, type, fn || data, fn && data );
2229                 });
2230         },
2231
2232         one: function( type, data, fn ) {
2233                 var one = jQuery.event.proxy( fn || data, function(event) {
2234                         jQuery(this).unbind(event, one);
2235                         return (fn || data).apply( this, arguments );
2236                 });
2237                 return this.each(function(){
2238                         jQuery.event.add( this, type, one, fn && data);
2239                 });
2240         },
2241
2242         unbind: function( type, fn ) {
2243                 return this.each(function(){
2244                         jQuery.event.remove( this, type, fn );
2245                 });
2246         },
2247
2248         trigger: function( type, data, fn ) {
2249                 return this.each(function(){
2250                         jQuery.event.trigger( type, data, this, true, fn );
2251                 });
2252         },
2253
2254         triggerHandler: function( type, data, fn ) {
2255                 return this[0] && jQuery.event.trigger( type, data, this[0], false, fn );
2256         },
2257
2258         toggle: function( fn ) {
2259                 // Save reference to arguments for access in closure
2260                 var args = arguments, i = 1;
2261
2262                 // link all the functions, so any of them can unbind this click handler
2263                 while( i < args.length )
2264                         jQuery.event.proxy( fn, args[i++] );
2265
2266                 return this.click( jQuery.event.proxy( fn, function(event) {
2267                         // Figure out which function to execute
2268                         this.lastToggle = ( this.lastToggle || 0 ) % i;
2269
2270                         // Make sure that clicks stop
2271                         event.preventDefault();
2272
2273                         // and execute the function
2274                         return args[ this.lastToggle++ ].apply( this, arguments ) || false;
2275                 }));
2276         },
2277
2278         hover: function(fnOver, fnOut) {
2279                 return this.bind('mouseenter', fnOver).bind('mouseleave', fnOut);
2280         },
2281
2282         ready: function(fn) {
2283                 // Attach the listeners
2284                 bindReady();
2285
2286                 // If the DOM is already ready
2287                 if ( jQuery.isReady )
2288                         // Execute the function immediately
2289                         fn.call( document, jQuery );
2290
2291                 // Otherwise, remember the function for later
2292                 else
2293                         // Add the function to the wait list
2294                         jQuery.readyList.push( function() { return fn.call(this, jQuery); } );
2295
2296                 return this;
2297         }
2298 });
2299
2300 jQuery.extend({
2301         isReady: false,
2302         readyList: [],
2303         // Handle when the DOM is ready
2304         ready: function() {
2305                 // Make sure that the DOM is not already loaded
2306                 if ( !jQuery.isReady ) {
2307                         // Remember that the DOM is ready
2308                         jQuery.isReady = true;
2309
2310                         // If there are functions bound, to execute
2311                         if ( jQuery.readyList ) {
2312                                 // Execute all of them
2313                                 jQuery.each( jQuery.readyList, function(){
2314                                         this.call( document );
2315                                 });
2316
2317                                 // Reset the list of functions
2318                                 jQuery.readyList = null;
2319                         }
2320
2321                         // Trigger any bound ready events
2322                         jQuery(document).triggerHandler("ready");
2323                 }
2324         }
2325 });
2326
2327 var readyBound = false;
2328
2329 function bindReady(){
2330         if ( readyBound ) return;
2331         readyBound = true;
2332
2333         // Mozilla, Opera (see further below for it) and webkit nightlies currently support this event
2334         if ( document.addEventListener && !jQuery.browser.opera)
2335                 // Use the handy event callback
2336                 document.addEventListener( "DOMContentLoaded", jQuery.ready, false );
2337
2338         // If IE is used and is not in a frame
2339         // Continually check to see if the document is ready
2340         if ( jQuery.browser.msie && window == top ) (function(){
2341                 if (jQuery.isReady) return;
2342                 try {
2343                         // If IE is used, use the trick by Diego Perini
2344                         // http://javascript.nwbox.com/IEContentLoaded/
2345                         document.documentElement.doScroll("left");
2346                 } catch( error ) {
2347                         setTimeout( arguments.callee, 0 );
2348                         return;
2349                 }
2350                 // and execute any waiting functions
2351                 jQuery.ready();
2352         })();
2353
2354         if ( jQuery.browser.opera )
2355                 document.addEventListener( "DOMContentLoaded", function () {
2356                         if (jQuery.isReady) return;
2357                         for (var i = 0; i < document.styleSheets.length; i++)
2358                                 if (document.styleSheets[i].disabled) {
2359                                         setTimeout( arguments.callee, 0 );
2360                                         return;
2361                                 }
2362                         // and execute any waiting functions
2363                         jQuery.ready();
2364                 }, false);
2365
2366         if ( jQuery.browser.safari ) {
2367                 var numStyles;
2368                 (function(){
2369                         if (jQuery.isReady) return;
2370                         if ( document.readyState != "loaded" && document.readyState != "complete" ) {
2371                                 setTimeout( arguments.callee, 0 );
2372                                 return;
2373                         }
2374                         if ( numStyles === undefined )
2375                                 numStyles = jQuery("style, link[rel=stylesheet]").length;
2376                         if ( document.styleSheets.length != numStyles ) {
2377                                 setTimeout( arguments.callee, 0 );
2378                                 return;
2379                         }
2380                         // and execute any waiting functions
2381                         jQuery.ready();
2382                 })();
2383         }
2384
2385         // A fallback to window.onload, that will always work
2386         jQuery.event.add( window, "load", jQuery.ready );
2387 }
2388
2389 jQuery.each( ("blur,focus,load,resize,scroll,unload,click,dblclick," +
2390         "mousedown,mouseup,mousemove,mouseover,mouseout,change,select," +
2391         "submit,keydown,keypress,keyup,error").split(","), function(i, name){
2392
2393         // Handle event binding
2394         jQuery.fn[name] = function(fn){
2395                 return fn ? this.bind(name, fn) : this.trigger(name);
2396         };
2397 });
2398
2399 // Checks if an event happened on an element within another element
2400 // Used in jQuery.event.special.mouseenter and mouseleave handlers
2401 var withinElement = function(event, elem) {
2402         // Check if mouse(over|out) are still within the same parent element
2403         var parent = event.relatedTarget;
2404         // Traverse up the tree
2405         while ( parent && parent != elem ) try { parent = parent.parentNode; } catch(error) { parent = elem; }
2406         // Return true if we actually just moused on to a sub-element
2407         return parent == elem;
2408 };
2409
2410 // Prevent memory leaks in IE
2411 // And prevent errors on refresh with events like mouseover in other browsers
2412 // Window isn't included so as not to unbind existing unload events
2413 jQuery(window).bind("unload", function() {
2414         jQuery("*").add(document).unbind();
2415 });
2416 jQuery.fn.extend({
2417         // Keep a copy of the old load
2418         _load: jQuery.fn.load,
2419
2420         load: function( url, params, callback ) {
2421                 if ( typeof url != 'string' )
2422                         return this._load( url );
2423
2424                 var off = url.indexOf(" ");
2425                 if ( off >= 0 ) {
2426                         var selector = url.slice(off, url.length);
2427                         url = url.slice(0, off);
2428                 }
2429
2430                 callback = callback || function(){};
2431
2432                 // Default to a GET request
2433                 var type = "GET";
2434
2435                 // If the second parameter was provided
2436                 if ( params )
2437                         // If it's a function
2438                         if ( jQuery.isFunction( params ) ) {
2439                                 // We assume that it's the callback
2440                                 callback = params;
2441                                 params = null;
2442
2443                         // Otherwise, build a param string
2444                         } else {
2445                                 params = jQuery.param( params );
2446                                 type = "POST";
2447                         }
2448
2449                 var self = this;
2450
2451                 // Request the remote document
2452                 jQuery.ajax({
2453                         url: url,
2454                         type: type,
2455                         dataType: "html",
2456                         data: params,
2457                         complete: function(res, status){
2458                                 // If successful, inject the HTML into all the matched elements
2459                                 if ( status == "success" || status == "notmodified" )
2460                                         // See if a selector was specified
2461                                         self.html( selector ?
2462                                                 // Create a dummy div to hold the results
2463                                                 jQuery("<div/>")
2464                                                         // inject the contents of the document in, removing the scripts
2465                                                         // to avoid any 'Permission Denied' errors in IE
2466                                                         .append(res.responseText.replace(/<script(.|\s)*?\/script>/g, ""))
2467
2468                                                         // Locate the specified elements
2469                                                         .find(selector) :
2470
2471                                                 // If not, just inject the full result
2472                                                 res.responseText );
2473
2474                                 self.each( callback, [res.responseText, status, res] );
2475                         }
2476                 });
2477                 return this;
2478         },
2479
2480         serialize: function() {
2481                 return jQuery.param(this.serializeArray());
2482         },
2483         serializeArray: function() {
2484                 return this.map(function(){
2485                         return jQuery.nodeName(this, "form") ?
2486                                 jQuery.makeArray(this.elements) : this;
2487                 })
2488                 .filter(function(){
2489                         return this.name && !this.disabled &&
2490                                 (this.checked || /select|textarea/i.test(this.nodeName) ||
2491                                         /text|hidden|password/i.test(this.type));
2492                 })
2493                 .map(function(i, elem){
2494                         var val = jQuery(this).val();
2495                         return val == null ? null :
2496                                 val.constructor == Array ?
2497                                         jQuery.map( val, function(val, i){
2498                                                 return {name: elem.name, value: val};
2499                                         }) :
2500                                         {name: elem.name, value: val};
2501                 }).get();
2502         }
2503 });
2504
2505 // Attach a bunch of functions for handling common AJAX events
2506 jQuery.each( "ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","), function(i,o){
2507         jQuery.fn[o] = function(f){
2508                 return this.bind(o, f);
2509         };
2510 });
2511
2512 var jsc = now();
2513
2514 jQuery.extend({
2515         get: function( url, data, callback, type ) {
2516                 // shift arguments if data argument was ommited
2517                 if ( jQuery.isFunction( data ) ) {
2518                         callback = data;
2519                         data = null;
2520                 }
2521
2522                 return jQuery.ajax({
2523                         type: "GET",
2524                         url: url,
2525                         data: data,
2526                         success: callback,
2527                         dataType: type
2528                 });
2529         },
2530
2531         getScript: function( url, callback ) {
2532                 return jQuery.get(url, null, callback, "script");
2533         },
2534
2535         getJSON: function( url, data, callback ) {
2536                 return jQuery.get(url, data, callback, "json");
2537         },
2538
2539         post: function( url, data, callback, type ) {
2540                 if ( jQuery.isFunction( data ) ) {
2541                         callback = data;
2542                         data = {};
2543                 }
2544
2545                 return jQuery.ajax({
2546                         type: "POST",
2547                         url: url,
2548                         data: data,
2549                         success: callback,
2550                         dataType: type
2551                 });
2552         },
2553
2554         ajaxSetup: function( settings ) {
2555                 jQuery.extend( jQuery.ajaxSettings, settings );
2556         },
2557
2558         ajaxSettings: {
2559                 url: location.href,
2560                 global: true,
2561                 type: "GET",
2562                 timeout: 0,
2563                 contentType: "application/x-www-form-urlencoded",
2564                 processData: true,
2565                 async: true,
2566                 data: null,
2567                 username: null,
2568                 password: null,
2569                 accepts: {
2570                         xml: "application/xml, text/xml",
2571                         html: "text/html",
2572                         script: "text/javascript, application/javascript",
2573                         json: "application/json, text/javascript",
2574                         text: "text/plain",
2575                         _default: "*/*"
2576                 }
2577         },
2578
2579         // Last-Modified header cache for next request
2580         lastModified: {},
2581
2582         ajax: function( s ) {
2583                 // Extend the settings, but re-extend 's' so that it can be
2584                 // checked again later (in the test suite, specifically)
2585                 s = jQuery.extend(true, s, jQuery.extend(true, {}, jQuery.ajaxSettings, s));
2586
2587                 var jsonp, jsre = /=\?(&|$)/g, status, data,
2588                         type = s.type.toUpperCase();
2589
2590                 // convert data if not already a string
2591                 if ( s.data && s.processData && typeof s.data != "string" )
2592                         s.data = jQuery.param(s.data);
2593
2594                 // Handle JSONP Parameter Callbacks
2595                 if ( s.dataType == "jsonp" ) {
2596                         if ( type == "GET" ) {
2597                                 if ( !s.url.match(jsre) )
2598                                         s.url += (s.url.match(/\?/) ? "&" : "?") + (s.jsonp || "callback") + "=?";
2599                         } else if ( !s.data || !s.data.match(jsre) )
2600                                 s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
2601                         s.dataType = "json";
2602                 }
2603
2604                 // Build temporary JSONP function
2605                 if ( s.dataType == "json" && (s.data && s.data.match(jsre) || s.url.match(jsre)) ) {
2606                         jsonp = "jsonp" + jsc++;
2607
2608                         // Replace the =? sequence both in the query string and the data
2609                         if ( s.data )
2610                                 s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");
2611                         s.url = s.url.replace(jsre, "=" + jsonp + "$1");
2612
2613                         // We need to make sure
2614                         // that a JSONP style response is executed properly
2615                         s.dataType = "script";
2616
2617                         // Handle JSONP-style loading
2618                         window[ jsonp ] = function(tmp){
2619                                 data = tmp;
2620                                 success();
2621                                 complete();
2622                                 // Garbage collect
2623                                 window[ jsonp ] = undefined;
2624                                 try{ delete window[ jsonp ]; } catch(e){}
2625                                 if ( head )
2626                                         head.removeChild( script );
2627                         };
2628                 }
2629
2630                 if ( s.dataType == "script" && s.cache == null )
2631                         s.cache = false;
2632
2633                 if ( s.cache === false && type == "GET" ) {
2634                         var ts = now();
2635                         // try replacing _= if it is there
2636                         var ret = s.url.replace(/(\?|&)_=.*?(&|$)/, "$1_=" + ts + "$2");
2637                         // if nothing was replaced, add timestamp to the end
2638                         s.url = ret + ((ret == s.url) ? (s.url.match(/\?/) ? "&" : "?") + "_=" + ts : "");
2639                 }
2640
2641                 // If data is available, append data to url for get requests
2642                 if ( s.data && type == "GET" ) {
2643                         s.url += (s.url.match(/\?/) ? "&" : "?") + s.data;
2644
2645                         // IE likes to send both get and post data, prevent this
2646                         s.data = null;
2647                 }
2648
2649                 // Watch for a new set of requests
2650                 if ( s.global && ! jQuery.active++ )
2651                         jQuery.event.trigger( "ajaxStart" );
2652
2653                 // Matches an absolute URL, and saves the domain
2654                 var remote = /^(?:\w+:)?\/\/([^\/?#]+)/;
2655
2656                 // If we're requesting a remote document
2657                 // and trying to load JSON or Script with a GET
2658                 if ( s.dataType == "script" && type == "GET"
2659                                 && remote.test(s.url) && remote.exec(s.url)[1] != location.host ){
2660                         var head = document.getElementsByTagName("head")[0];
2661                         var script = document.createElement("script");
2662                         script.src = s.url;
2663                         if (s.scriptCharset)
2664                                 script.charset = s.scriptCharset;
2665
2666                         // Handle Script loading
2667                         if ( !jsonp ) {
2668                                 var done = false;
2669
2670                                 // Attach handlers for all browsers
2671                                 script.onload = script.onreadystatechange = function(){
2672                                         if ( !done && (!this.readyState ||
2673                                                         this.readyState == "loaded" || this.readyState == "complete") ) {
2674                                                 done = true;
2675                                                 success();
2676                                                 complete();
2677                                                 head.removeChild( script );
2678                                         }
2679                                 };
2680                         }
2681
2682                         head.appendChild(script);
2683
2684                         // We handle everything using the script element injection
2685                         return undefined;
2686                 }
2687
2688                 var requestDone = false;
2689
2690                 // Create the request object; Microsoft failed to properly
2691                 // implement the XMLHttpRequest in IE7, so we use the ActiveXObject when it is available
2692                 var xhr = window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
2693
2694                 // Open the socket
2695                 // Passing null username, generates a login popup on Opera (#2865)
2696                 if( s.username )
2697                         xhr.open(type, s.url, s.async, s.username, s.password);
2698                 else
2699                         xhr.open(type, s.url, s.async);
2700
2701                 // Need an extra try/catch for cross domain requests in Firefox 3
2702                 try {
2703                         // Set the correct header, if data is being sent
2704                         if ( s.data )
2705                                 xhr.setRequestHeader("Content-Type", s.contentType);
2706
2707                         // Set the If-Modified-Since header, if ifModified mode.
2708                         if ( s.ifModified )
2709                                 xhr.setRequestHeader("If-Modified-Since",
2710                                         jQuery.lastModified[s.url] || "Thu, 01 Jan 1970 00:00:00 GMT" );
2711
2712                         // Set header so the called script knows that it's an XMLHttpRequest
2713                         xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
2714
2715                         // Set the Accepts header for the server, depending on the dataType
2716                         xhr.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ?
2717                                 s.accepts[ s.dataType ] + ", */*" :
2718                                 s.accepts._default );
2719                 } catch(e){}
2720
2721                 // Allow custom headers/mimetypes
2722                 if ( s.beforeSend && s.beforeSend(xhr, s) === false ) {
2723                         // cleanup active request counter
2724                         s.global && jQuery.active--;
2725                         // close opended socket
2726                         xhr.abort();
2727                         return false;
2728                 }
2729
2730                 if ( s.global )
2731                         jQuery.event.trigger("ajaxSend", [xhr, s]);
2732
2733                 // Wait for a response to come back
2734                 var onreadystatechange = function(isTimeout){
2735                         // The transfer is complete and the data is available, or the request timed out
2736                         if ( !requestDone && xhr && (xhr.readyState == 4 || isTimeout == "timeout") ) {
2737                                 requestDone = true;
2738
2739                                 // clear poll interval
2740                                 if (ival) {
2741                                         clearInterval(ival);
2742                                         ival = null;
2743                                 }
2744
2745                                 status = isTimeout == "timeout" && "timeout" ||
2746                                         !jQuery.httpSuccess( xhr ) && "error" ||
2747                                         s.ifModified && jQuery.httpNotModified( xhr, s.url ) && "notmodified" ||
2748                                         "success";
2749
2750                                 if ( status == "success" ) {
2751                                         // Watch for, and catch, XML document parse errors
2752                                         try {
2753                                                 // process the data (runs the xml through httpData regardless of callback)
2754                                                 data = jQuery.httpData( xhr, s.dataType, s.dataFilter );
2755                                         } catch(e) {
2756                                                 status = "parsererror";
2757                                         }
2758                                 }
2759
2760                                 // Make sure that the request was successful or notmodified
2761                                 if ( status == "success" ) {
2762                                         // Cache Last-Modified header, if ifModified mode.
2763                                         var modRes;
2764                                         try {
2765                                                 modRes = xhr.getResponseHeader("Last-Modified");
2766                                         } catch(e) {} // swallow exception thrown by FF if header is not available
2767
2768                                         if ( s.ifModified && modRes )
2769                                                 jQuery.lastModified[s.url] = modRes;
2770
2771                                         // JSONP handles its own success callback
2772                                         if ( !jsonp )
2773                                                 success();
2774                                 } else
2775                                         jQuery.handleError(s, xhr, status);
2776
2777                                 // Fire the complete handlers
2778                                 complete();
2779
2780                                 // Stop memory leaks
2781                                 if ( s.async )
2782                                         xhr = null;
2783                         }
2784                 };
2785
2786                 if ( s.async ) {
2787                         // don't attach the handler to the request, just poll it instead
2788                         var ival = setInterval(onreadystatechange, 13);
2789
2790                         // Timeout checker
2791                         if ( s.timeout > 0 )
2792                                 setTimeout(function(){
2793                                         // Check to see if the request is still happening
2794                                         if ( xhr ) {
2795                                                 // Cancel the request
2796                                                 xhr.abort();
2797
2798                                                 if( !requestDone )
2799                                                         onreadystatechange( "timeout" );
2800                                         }
2801                                 }, s.timeout);
2802                 }
2803
2804                 // Send the data
2805                 try {
2806                         xhr.send(s.data);
2807                 } catch(e) {
2808                         jQuery.handleError(s, xhr, null, e);
2809                 }
2810
2811                 // firefox 1.5 doesn't fire statechange for sync requests
2812                 if ( !s.async )
2813                         onreadystatechange();
2814
2815                 function success(){
2816                         // If a local callback was specified, fire it and pass it the data
2817                         if ( s.success )
2818                                 s.success( data, status );
2819
2820                         // Fire the global callback
2821                         if ( s.global )
2822                                 jQuery.event.trigger( "ajaxSuccess", [xhr, s] );
2823                 }
2824
2825                 function complete(){
2826                         // Process result
2827                         if ( s.complete )
2828                                 s.complete(xhr, status);
2829
2830                         // The request was completed
2831                         if ( s.global )
2832                                 jQuery.event.trigger( "ajaxComplete", [xhr, s] );
2833
2834                         // Handle the global AJAX counter
2835                         if ( s.global && ! --jQuery.active )
2836                                 jQuery.event.trigger( "ajaxStop" );
2837                 }
2838
2839                 // return XMLHttpRequest to allow aborting the request etc.
2840                 return xhr;
2841         },
2842
2843         handleError: function( s, xhr, status, e ) {
2844                 // If a local callback was specified, fire it
2845                 if ( s.error ) s.error( xhr, status, e );
2846
2847                 // Fire the global callback
2848                 if ( s.global )
2849                         jQuery.event.trigger( "ajaxError", [xhr, s, e] );
2850         },
2851
2852         // Counter for holding the number of active queries
2853         active: 0,
2854
2855         // Determines if an XMLHttpRequest was successful or not
2856         httpSuccess: function( xhr ) {
2857                 try {
2858                         // IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450
2859                         return !xhr.status && location.protocol == "file:" ||
2860                                 ( xhr.status >= 200 && xhr.status < 300 ) || xhr.status == 304 || xhr.status == 1223 ||
2861                                 jQuery.browser.safari && xhr.status == undefined;
2862                 } catch(e){}
2863                 return false;
2864         },
2865
2866         // Determines if an XMLHttpRequest returns NotModified
2867         httpNotModified: function( xhr, url ) {
2868                 try {
2869                         var xhrRes = xhr.getResponseHeader("Last-Modified");
2870
2871                         // Firefox always returns 200. check Last-Modified date
2872                         return xhr.status == 304 || xhrRes == jQuery.lastModified[url] ||
2873                                 jQuery.browser.safari && xhr.status == undefined;
2874                 } catch(e){}
2875                 return false;
2876         },
2877
2878         httpData: function( xhr, type, filter ) {
2879                 var ct = xhr.getResponseHeader("content-type"),
2880                         xml = type == "xml" || !type && ct && ct.indexOf("xml") >= 0,
2881                         data = xml ? xhr.responseXML : xhr.responseText;
2882
2883                 if ( xml && data.documentElement.tagName == "parsererror" )
2884                         throw "parsererror";
2885                         
2886                 // Allow a pre-filtering function to sanitize the response
2887                 if( filter )
2888                         data = filter( data, type );
2889
2890                 // If the type is "script", eval it in global context
2891                 if ( type == "script" )
2892                         jQuery.globalEval( data );
2893
2894                 // Get the JavaScript object, if JSON is used.
2895                 if ( type == "json" )
2896                         data = eval("(" + data + ")");
2897
2898                 return data;
2899         },
2900
2901         // Serialize an array of form elements or a set of
2902         // key/values into a query string
2903         param: function( a ) {
2904                 var s = [];
2905
2906                 // If an array was passed in, assume that it is an array
2907                 // of form elements
2908                 if ( a.constructor == Array || a.jquery )
2909                         // Serialize the form elements
2910                         jQuery.each( a, function(){
2911                                 s.push( encodeURIComponent(this.name) + "=" + encodeURIComponent( this.value ) );
2912                         });
2913
2914                 // Otherwise, assume that it's an object of key/value pairs
2915                 else
2916                         // Serialize the key/values
2917                         for ( var j in a )
2918                                 // If the value is an array then the key names need to be repeated
2919                                 if ( a[j] && a[j].constructor == Array )
2920                                         jQuery.each( a[j], function(){
2921                                                 s.push( encodeURIComponent(j) + "=" + encodeURIComponent( this ) );
2922                                         });
2923                                 else
2924                                         s.push( encodeURIComponent(j) + "=" + encodeURIComponent( jQuery.isFunction(a[j]) ? a[j]() : a[j] ) );
2925
2926                 // Return the resulting serialization
2927                 return s.join("&").replace(/%20/g, "+");
2928         }
2929
2930 });
2931 jQuery.fn.extend({
2932         show: function(speed,callback){
2933                 return speed ?
2934                         this.animate({
2935                                 height: "show", width: "show", opacity: "show"
2936                         }, speed, callback) :
2937
2938                         this.filter(":hidden").each(function(){
2939                                 this.style.display = this.oldblock || "";
2940                                 if ( jQuery.css(this,"display") == "none" ) {
2941                                         var elem = jQuery("<" + this.tagName + " />").appendTo("body");
2942                                         this.style.display = elem.css("display");
2943                                         // handle an edge condition where css is - div { display:none; } or similar
2944                                         if (this.style.display == "none")
2945                                                 this.style.display = "block";
2946                                         elem.remove();
2947                                 }
2948                         }).end();
2949         },
2950
2951         hide: function(speed,callback){
2952                 return speed ?
2953                         this.animate({
2954                                 height: "hide", width: "hide", opacity: "hide"
2955                         }, speed, callback) :
2956
2957                         this.filter(":visible").each(function(){
2958                                 this.oldblock = this.oldblock || jQuery.css(this,"display");
2959                                 this.style.display = "none";
2960                         }).end();
2961         },
2962
2963         // Save the old toggle function
2964         _toggle: jQuery.fn.toggle,
2965
2966         toggle: function( fn, fn2 ){
2967                 return jQuery.isFunction(fn) && jQuery.isFunction(fn2) ?
2968                         this._toggle.apply( this, arguments ) :
2969                         fn ?
2970                                 this.animate({
2971                                         height: "toggle", width: "toggle", opacity: "toggle"
2972                                 }, fn, fn2) :
2973                                 this.each(function(){
2974                                         jQuery(this)[ jQuery(this).is(":hidden") ? "show" : "hide" ]();
2975                                 });
2976         },
2977
2978         slideDown: function(speed,callback){
2979                 return this.animate({height: "show"}, speed, callback);
2980         },
2981
2982         slideUp: function(speed,callback){
2983                 return this.animate({height: "hide"}, speed, callback);
2984         },
2985
2986         slideToggle: function(speed, callback){
2987                 return this.animate({height: "toggle"}, speed, callback);
2988         },
2989
2990         fadeIn: function(speed, callback){
2991                 return this.animate({opacity: "show"}, speed, callback);
2992         },
2993
2994         fadeOut: function(speed, callback){
2995                 return this.animate({opacity: "hide"}, speed, callback);
2996         },
2997
2998         fadeTo: function(speed,to,callback){
2999                 return this.animate({opacity: to}, speed, callback);
3000         },
3001
3002         animate: function( prop, speed, easing, callback ) {
3003                 var optall = jQuery.speed(speed, easing, callback);
3004
3005                 return this[ optall.queue === false ? "each" : "queue" ](function(){
3006                         if ( this.nodeType != 1)
3007                                 return false;
3008
3009                         var opt = jQuery.extend({}, optall), p,
3010                                 hidden = jQuery(this).is(":hidden"), self = this;
3011
3012                         for ( p in prop ) {
3013                                 if ( prop[p] == "hide" && hidden || prop[p] == "show" && !hidden )
3014                                         return opt.complete.call(this);
3015
3016                                 if ( p == "height" || p == "width" ) {
3017                                         // Store display property
3018                                         opt.display = jQuery.css(this, "display");
3019
3020                                         // Make sure that nothing sneaks out
3021                                         opt.overflow = this.style.overflow;
3022                                 }
3023                         }
3024
3025                         if ( opt.overflow != null )
3026                                 this.style.overflow = "hidden";
3027
3028                         opt.curAnim = jQuery.extend({}, prop);
3029
3030                         jQuery.each( prop, function(name, val){
3031                                 var e = new jQuery.fx( self, opt, name );
3032
3033                                 if ( /toggle|show|hide/.test(val) )
3034                                         e[ val == "toggle" ? hidden ? "show" : "hide" : val ]( prop );
3035                                 else {
3036                                         var parts = val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),
3037                                                 start = e.cur(true) || 0;
3038
3039                                         if ( parts ) {
3040                                                 var end = parseFloat(parts[2]),
3041                                                         unit = parts[3] || "px";
3042
3043                                                 // We need to compute starting value
3044                                                 if ( unit != "px" ) {
3045                                                         self.style[ name ] = (end || 1) + unit;
3046                                                         start = ((end || 1) / e.cur(true)) * start;
3047                                                         self.style[ name ] = start + unit;
3048                                                 }
3049
3050                                                 // If a +=/-= token was provided, we're doing a relative animation
3051                                                 if ( parts[1] )
3052                                                         end = ((parts[1] == "-=" ? -1 : 1) * end) + start;
3053
3054                                                 e.custom( start, end, unit );
3055                                         } else
3056                                                 e.custom( start, val, "" );
3057                                 }
3058                         });
3059
3060                         // For JS strict compliance
3061                         return true;
3062                 });
3063         },
3064
3065         queue: function(type, fn){
3066                 if ( jQuery.isFunction(type) || ( type && type.constructor == Array )) {
3067                         fn = type;
3068                         type = "fx";
3069                 }
3070
3071                 if ( !type || (typeof type == "string" && !fn) )
3072                         return queue( this[0], type );
3073
3074                 return this.each(function(){
3075                         if ( fn.constructor == Array )
3076                                 queue(this, type, fn);
3077                         else {
3078                                 queue(this, type).push( fn );
3079
3080                                 if ( queue(this, type).length == 1 )
3081                                         fn.call(this);
3082                         }
3083                 });
3084         },
3085
3086         stop: function(clearQueue, gotoEnd){
3087                 var timers = jQuery.timers;
3088
3089                 if (clearQueue)
3090                         this.queue([]);
3091
3092                 this.each(function(){
3093                         // go in reverse order so anything added to the queue during the loop is ignored
3094                         for ( var i = timers.length - 1; i >= 0; i-- )
3095                                 if ( timers[i].elem == this ) {
3096                                         if (gotoEnd)
3097                                                 // force the next step to be the last
3098                                                 timers[i](true);
3099                                         timers.splice(i, 1);
3100                                 }
3101                 });
3102
3103                 // start the next in the queue if the last step wasn't forced
3104                 if (!gotoEnd)
3105                         this.dequeue();
3106
3107                 return this;
3108         }
3109
3110 });
3111
3112 var queue = function( elem, type, array ) {
3113         if ( elem ){
3114
3115                 type = type || "fx";
3116
3117                 var q = jQuery.data( elem, type + "queue" );
3118
3119                 if ( !q || array )
3120                         q = jQuery.data( elem, type + "queue", jQuery.makeArray(array) );
3121
3122         }
3123         return q;
3124 };
3125
3126 jQuery.fn.dequeue = function(type){
3127         type = type || "fx";
3128
3129         return this.each(function(){
3130                 var q = queue(this, type);
3131
3132                 q.shift();
3133
3134                 if ( q.length )
3135                         q[0].call( this );
3136         });
3137 };
3138
3139 jQuery.extend({
3140
3141         speed: function(speed, easing, fn) {
3142                 var opt = speed && speed.constructor == Object ? speed : {
3143                         complete: fn || !fn && easing ||
3144                                 jQuery.isFunction( speed ) && speed,
3145                         duration: speed,
3146                         easing: fn && easing || easing && easing.constructor != Function && easing
3147                 };
3148
3149                 opt.duration = (opt.duration && opt.duration.constructor == Number ?
3150                         opt.duration :
3151                         jQuery.fx.speeds[opt.duration]) || jQuery.fx.speeds.def;
3152
3153                 // Queueing
3154                 opt.old = opt.complete;
3155                 opt.complete = function(){
3156                         if ( opt.queue !== false )
3157                                 jQuery(this).dequeue();
3158                         if ( jQuery.isFunction( opt.old ) )
3159                                 opt.old.call( this );
3160                 };
3161
3162                 return opt;
3163         },
3164
3165         easing: {
3166                 linear: function( p, n, firstNum, diff ) {
3167                         return firstNum + diff * p;
3168                 },
3169                 swing: function( p, n, firstNum, diff ) {
3170                         return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
3171                 }
3172         },
3173
3174         timers: [],
3175         timerId: null,
3176
3177         fx: function( elem, options, prop ){
3178                 this.options = options;
3179                 this.elem = elem;
3180                 this.prop = prop;
3181
3182                 if ( !options.orig )
3183                         options.orig = {};
3184         }
3185
3186 });
3187
3188 jQuery.fx.prototype = {
3189
3190         // Simple function for setting a style value
3191         update: function(){
3192                 if ( this.options.step )
3193                         this.options.step.call( this.elem, this.now, this );
3194
3195                 (jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );
3196
3197                 // Set display property to block for height/width animations
3198                 if ( this.prop == "height" || this.prop == "width" )
3199                         this.elem.style.display = "block";
3200         },
3201
3202         // Get the current size
3203         cur: function(force){
3204                 if ( this.elem[this.prop] != null && this.elem.style[this.prop] == null )
3205                         return this.elem[ this.prop ];
3206
3207                 var r = parseFloat(jQuery.css(this.elem, this.prop, force));
3208                 return r && r > -10000 ? r : parseFloat(jQuery.curCSS(this.elem, this.prop)) || 0;
3209         },
3210
3211         // Start an animation from one number to another
3212         custom: function(from, to, unit){
3213                 this.startTime = now();
3214                 this.start = from;
3215                 this.end = to;
3216                 this.unit = unit || this.unit || "px";
3217                 this.now = this.start;
3218                 this.pos = this.state = 0;
3219                 this.update();
3220
3221                 var self = this;
3222                 function t(gotoEnd){
3223                         return self.step(gotoEnd);
3224                 }
3225
3226                 t.elem = this.elem;
3227
3228                 jQuery.timers.push(t);
3229
3230                 if ( jQuery.timerId == null ) {
3231                         jQuery.timerId = setInterval(function(){
3232                                 var timers = jQuery.timers;
3233
3234                                 for ( var i = 0; i < timers.length; i++ )
3235                                         if ( !timers[i]() )
3236                                                 timers.splice(i--, 1);
3237
3238                                 if ( !timers.length ) {
3239                                         clearInterval( jQuery.timerId );
3240                                         jQuery.timerId = null;
3241                                 }
3242                         }, 13);
3243                 }
3244         },
3245
3246         // Simple 'show' function
3247         show: function(){
3248                 // Remember where we started, so that we can go back to it later
3249                 this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
3250                 this.options.show = true;
3251
3252                 // Begin the animation
3253                 this.custom(0, this.cur());
3254
3255                 // Make sure that we start at a small width/height to avoid any
3256                 // flash of content
3257                 if ( this.prop == "width" || this.prop == "height" )
3258                         this.elem.style[this.prop] = "1px";
3259
3260                 // Start by showing the element
3261                 jQuery(this.elem).show();
3262         },
3263
3264         // Simple 'hide' function
3265         hide: function(){
3266                 // Remember where we started, so that we can go back to it later
3267                 this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
3268                 this.options.hide = true;
3269
3270                 // Begin the animation
3271                 this.custom(this.cur(), 0);
3272         },
3273
3274         // Each step of an animation
3275         step: function(gotoEnd){
3276                 var t = now();
3277
3278                 if ( gotoEnd || t > this.options.duration + this.startTime ) {
3279                         this.now = this.end;
3280                         this.pos = this.state = 1;
3281                         this.update();
3282
3283                         this.options.curAnim[ this.prop ] = true;
3284
3285                         var done = true;
3286                         for ( var i in this.options.curAnim )
3287                                 if ( this.options.curAnim[i] !== true )
3288                                         done = false;
3289
3290                         if ( done ) {
3291                                 if ( this.options.display != null ) {
3292                                         // Reset the overflow
3293                                         this.elem.style.overflow = this.options.overflow;
3294
3295                                         // Reset the display
3296                                         this.elem.style.display = this.options.display;
3297                                         if ( jQuery.css(this.elem, "display") == "none" )
3298                                                 this.elem.style.display = "block";
3299                                 }
3300
3301                                 // Hide the element if the "hide" operation was done
3302                                 if ( this.options.hide )
3303                                         this.elem.style.display = "none";
3304
3305                                 // Reset the properties, if the item has been hidden or shown
3306                                 if ( this.options.hide || this.options.show )
3307                                         for ( var p in this.options.curAnim )
3308                                                 jQuery.attr(this.elem.style, p, this.options.orig[p]);
3309                         }
3310
3311                         if ( done )
3312                                 // Execute the complete function
3313                                 this.options.complete.call( this.elem );
3314
3315                         return false;
3316                 } else {
3317                         var n = t - this.startTime;
3318                         this.state = n / this.options.duration;
3319
3320                         // Perform the easing function, defaults to swing
3321                         this.pos = jQuery.easing[this.options.easing || (jQuery.easing.swing ? "swing" : "linear")](this.state, n, 0, 1, this.options.duration);
3322                         this.now = this.start + ((this.end - this.start) * this.pos);
3323
3324                         // Perform the next step of the animation
3325                         this.update();
3326                 }
3327
3328                 return true;
3329         }
3330
3331 };
3332
3333 jQuery.extend( jQuery.fx, {
3334         speeds:{
3335                 slow: 600,
3336                 fast: 200,
3337                 // Default speed
3338                 def: 400
3339         },
3340         step: {
3341                 scrollLeft: function(fx){
3342                         fx.elem.scrollLeft = fx.now;
3343                 },
3344
3345                 scrollTop: function(fx){
3346                         fx.elem.scrollTop = fx.now;
3347                 },
3348
3349                 opacity: function(fx){
3350                         jQuery.attr(fx.elem.style, "opacity", fx.now);
3351                 },
3352
3353                 _default: function(fx){
3354                         fx.elem.style[ fx.prop ] = fx.now + fx.unit;
3355                 }
3356         }
3357 });
3358 // The Offset Method
3359 // Originally By Brandon Aaron, part of the Dimension Plugin
3360 // http://jquery.com/plugins/project/dimensions
3361 jQuery.fn.offset = function() {
3362         var left = 0, top = 0, elem = this[0], results;
3363
3364         if ( elem ) with ( jQuery.browser ) {
3365                 var parent       = elem.parentNode,
3366                     offsetChild  = elem,
3367                     offsetParent = elem.offsetParent,
3368                     doc          = elem.ownerDocument,
3369                     safari2      = safari && parseInt(version) < 522 && !/adobeair/i.test(userAgent),
3370                     css          = jQuery.curCSS,
3371                     fixed        = css(elem, "position") == "fixed";
3372
3373                 // Use getBoundingClientRect if available
3374                 if ( elem.getBoundingClientRect ) {
3375                         var box = elem.getBoundingClientRect();
3376
3377                         // Add the document scroll offsets
3378                         add(box.left + Math.max(doc.documentElement.scrollLeft, doc.body.scrollLeft),
3379                                 box.top  + Math.max(doc.documentElement.scrollTop,  doc.body.scrollTop));
3380
3381                         // IE adds the HTML element's border, by default it is medium which is 2px
3382                         // IE 6 and 7 quirks mode the border width is overwritable by the following css html { border: 0; }
3383                         // IE 7 standards mode, the border is always 2px
3384                         // This border/offset is typically represented by the clientLeft and clientTop properties
3385                         // However, in IE6 and 7 quirks mode the clientLeft and clientTop properties are not updated when overwriting it via CSS
3386                         // Therefore this method will be off by 2px in IE while in quirksmode
3387                         add( -doc.documentElement.clientLeft, -doc.documentElement.clientTop );
3388
3389                 // Otherwise loop through the offsetParents and parentNodes
3390                 } else {
3391
3392                         // Initial element offsets
3393                         add( elem.offsetLeft, elem.offsetTop );
3394
3395                         // Get parent offsets
3396                         while ( offsetParent ) {
3397                                 // Add offsetParent offsets
3398                                 add( offsetParent.offsetLeft, offsetParent.offsetTop );
3399
3400                                 // Mozilla and Safari > 2 does not include the border on offset parents
3401                                 // However Mozilla adds the border for table or table cells
3402                                 if ( mozilla && !/^t(able|d|h)$/i.test(offsetParent.tagName) || safari && !safari2 )
3403                                         border( offsetParent );
3404
3405                                 // Add the document scroll offsets if position is fixed on any offsetParent
3406                                 if ( !fixed && css(offsetParent, "position") == "fixed" )
3407                                         fixed = true;
3408
3409                                 // Set offsetChild to previous offsetParent unless it is the body element
3410                                 offsetChild  = /^body$/i.test(offsetParent.tagName) ? offsetChild : offsetParent;
3411                                 // Get next offsetParent
3412                                 offsetParent = offsetParent.offsetParent;
3413                         }
3414
3415                         // Get parent scroll offsets
3416                         while ( parent && parent.tagName && !/^body|html$/i.test(parent.tagName) ) {
3417                                 // Remove parent scroll UNLESS that parent is inline or a table to work around Opera inline/table scrollLeft/Top bug
3418                                 if ( !/^inline|table.*$/i.test(css(parent, "display")) )
3419                                         // Subtract parent scroll offsets
3420                                         add( -parent.scrollLeft, -parent.scrollTop );
3421
3422                                 // Mozilla does not add the border for a parent that has overflow != visible
3423                                 if ( mozilla && css(parent, "overflow") != "visible" )
3424                                         border( parent );
3425
3426                                 // Get next parent
3427                                 parent = parent.parentNode;
3428                         }
3429
3430                         // Safari <= 2 doubles body offsets with a fixed position element/offsetParent or absolutely positioned offsetChild
3431                         // Mozilla doubles body offsets with a non-absolutely positioned offsetChild
3432                         if ( (safari2 && (fixed || css(offsetChild, "position") == "absolute")) ||
3433                                 (mozilla && css(offsetChild, "position") != "absolute") )
3434                                         add( -doc.body.offsetLeft, -doc.body.offsetTop );
3435
3436                         // Add the document scroll offsets if position is fixed
3437                         if ( fixed )
3438                                 add(Math.max(doc.documentElement.scrollLeft, doc.body.scrollLeft),
3439                                         Math.max(doc.documentElement.scrollTop,  doc.body.scrollTop));
3440                 }
3441
3442                 // Return an object with top and left properties
3443                 results = { top: top, left: left };
3444         }
3445
3446         function border(elem) {
3447                 add( jQuery.curCSS(elem, "borderLeftWidth", true), jQuery.curCSS(elem, "borderTopWidth", true) );
3448         }
3449
3450         function add(l, t) {
3451                 left += parseInt(l, 10) || 0;
3452                 top += parseInt(t, 10) || 0;
3453         }
3454
3455         return results;
3456 };
3457
3458
3459 jQuery.fn.extend({
3460         position: function() {
3461                 var left = 0, top = 0, results;
3462
3463                 if ( this[0] ) {
3464                         // Get *real* offsetParent
3465                         var offsetParent = this.offsetParent(),
3466
3467                         // Get correct offsets
3468                         offset       = this.offset(),
3469                         parentOffset = /^body|html$/i.test(offsetParent[0].tagName) ? { top: 0, left: 0 } : offsetParent.offset();
3470
3471                         // Subtract element margins
3472                         // note: when an element has margin: auto the offsetLeft and marginLeft 
3473                         // are the same in Safari causing offset.left to incorrectly be 0
3474                         offset.top  -= num( this, 'marginTop' );
3475                         offset.left -= num( this, 'marginLeft' );
3476
3477                         // Add offsetParent borders
3478                         parentOffset.top  += num( offsetParent, 'borderTopWidth' );
3479                         parentOffset.left += num( offsetParent, 'borderLeftWidth' );
3480
3481                         // Subtract the two offsets
3482                         results = {
3483                                 top:  offset.top  - parentOffset.top,
3484                                 left: offset.left - parentOffset.left
3485                         };
3486                 }
3487
3488                 return results;
3489         },
3490
3491         offsetParent: function() {
3492                 var offsetParent = this[0].offsetParent;
3493                 while ( offsetParent && (!/^body|html$/i.test(offsetParent.tagName) && jQuery.css(offsetParent, 'position') == 'static') )
3494                         offsetParent = offsetParent.offsetParent;
3495                 return jQuery(offsetParent);
3496         }
3497 });
3498
3499
3500 // Create scrollLeft and scrollTop methods
3501 jQuery.each( ['Left', 'Top'], function(i, name) {
3502         var method = 'scroll' + name;
3503         
3504         jQuery.fn[ method ] = function(val) {
3505                 if (!this[0]) return;
3506
3507                 return val != undefined ?
3508
3509                         // Set the scroll offset
3510                         this.each(function() {
3511                                 this == window || this == document ?
3512                                         window.scrollTo(
3513                                                 !i ? val : jQuery(window).scrollLeft(),
3514                                                  i ? val : jQuery(window).scrollTop()
3515                                         ) :
3516                                         this[ method ] = val;
3517                         }) :
3518
3519                         // Return the scroll offset
3520                         this[0] == window || this[0] == document ?
3521                                 self[ i ? 'pageYOffset' : 'pageXOffset' ] ||
3522                                         jQuery.boxModel && document.documentElement[ method ] ||
3523                                         document.body[ method ] :
3524                                 this[0][ method ];
3525         };
3526 });
3527 // Create innerHeight, innerWidth, outerHeight and outerWidth methods
3528 jQuery.each([ "Height", "Width" ], function(i, name){
3529
3530         var tl = i ? "Left"  : "Top",  // top or left
3531                 br = i ? "Right" : "Bottom"; // bottom or right
3532
3533         // innerHeight and innerWidth
3534         jQuery.fn["inner" + name] = function(){
3535                 return this[ name.toLowerCase() ]() +
3536                         num(this, "padding" + tl) +
3537                         num(this, "padding" + br);
3538         };
3539
3540         // outerHeight and outerWidth
3541         jQuery.fn["outer" + name] = function(margin) {
3542                 return this["inner" + name]() +
3543                         num(this, "border" + tl + "Width") +
3544                         num(this, "border" + br + "Width") +
3545                         (margin ?
3546                                 num(this, "margin" + tl) + num(this, "margin" + br) : 0);
3547         };
3548
3549 });})();