]> git.pond.sub.org Git - eow/blob - static/jquery.js
Getting started on unit tests
[eow] / static / jquery.js
1 /*!
2  * jQuery JavaScript Library v1.3.2
3  * http://jquery.com/
4  *
5  * Copyright (c) 2009 John Resig
6  * Dual licensed under the MIT and GPL licenses.
7  * http://docs.jquery.com/License
8  *
9  * Date: 2009-02-19 23:34:21 +0100 (Thu, 19 Feb 2009)
10  * Revision: 6246
11  */
12 (function(){
13
14 var 
15         // Will speed up references to window, and allows munging its name.
16         window = this,
17         // Will speed up references to undefined, and allows munging its name.
18         undefined,
19         // Map over jQuery in case of overwrite
20         _jQuery = window.jQuery,
21         // Map over the $ in case of overwrite
22         _$ = window.$,
23
24         jQuery = window.jQuery = window.$ = function( selector, context ) {
25                 // The jQuery object is actually just the init constructor 'enhanced'
26                 return new jQuery.fn.init( selector, context );
27         },
28
29         // A simple way to check for HTML strings or ID strings
30         // (both of which we optimize for)
31         quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,
32         // Is it a simple selector
33         isSimple = /^.[^:#\[\.,]*$/;
34
35 jQuery.fn = jQuery.prototype = {
36         init: function( selector, context ) {
37                 // Make sure that a selection was provided
38                 selector = selector || document;
39
40                 // Handle $(DOMElement)
41                 if ( selector.nodeType ) {
42                         this[0] = selector;
43                         this.length = 1;
44                         this.context = selector;
45                         return this;
46                 }
47                 // Handle HTML strings
48                 if ( typeof selector === "string" ) {
49                         // Are we dealing with HTML string or an ID?
50                         var match = quickExpr.exec( selector );
51
52                         // Verify a match, and that no context was specified for #id
53                         if ( match && (match[1] || !context) ) {
54
55                                 // HANDLE: $(html) -> $(array)
56                                 if ( match[1] )
57                                         selector = jQuery.clean( [ match[1] ], context );
58
59                                 // HANDLE: $("#id")
60                                 else {
61                                         var elem = document.getElementById( match[3] );
62
63                                         // Handle the case where IE and Opera return items
64                                         // by name instead of ID
65                                         if ( elem && elem.id != match[3] )
66                                                 return jQuery().find( selector );
67
68                                         // Otherwise, we inject the element directly into the jQuery object
69                                         var ret = jQuery( elem || [] );
70                                         ret.context = document;
71                                         ret.selector = selector;
72                                         return ret;
73                                 }
74
75                         // HANDLE: $(expr, [context])
76                         // (which is just equivalent to: $(content).find(expr)
77                         } else
78                                 return jQuery( context ).find( selector );
79
80                 // HANDLE: $(function)
81                 // Shortcut for document ready
82                 } else if ( jQuery.isFunction( selector ) )
83                         return jQuery( document ).ready( selector );
84
85                 // Make sure that old selector state is passed along
86                 if ( selector.selector && selector.context ) {
87                         this.selector = selector.selector;
88                         this.context = selector.context;
89                 }
90
91                 return this.setArray(jQuery.isArray( selector ) ?
92                         selector :
93                         jQuery.makeArray(selector));
94         },
95
96         // Start with an empty selector
97         selector: "",
98
99         // The current version of jQuery being used
100         jquery: "1.3.2",
101
102         // The number of elements contained in the matched element set
103         size: function() {
104                 return this.length;
105         },
106
107         // Get the Nth element in the matched element set OR
108         // Get the whole matched element set as a clean array
109         get: function( num ) {
110                 return num === undefined ?
111
112                         // Return a 'clean' array
113                         Array.prototype.slice.call( this ) :
114
115                         // Return just the object
116                         this[ num ];
117         },
118
119         // Take an array of elements and push it onto the stack
120         // (returning the new matched element set)
121         pushStack: function( elems, name, selector ) {
122                 // Build a new jQuery matched element set
123                 var ret = jQuery( elems );
124
125                 // Add the old object onto the stack (as a reference)
126                 ret.prevObject = this;
127
128                 ret.context = this.context;
129
130                 if ( name === "find" )
131                         ret.selector = this.selector + (this.selector ? " " : "") + selector;
132                 else if ( name )
133                         ret.selector = this.selector + "." + name + "(" + selector + ")";
134
135                 // Return the newly-formed element set
136                 return ret;
137         },
138
139         // Force the current matched set of elements to become
140         // the specified array of elements (destroying the stack in the process)
141         // You should use pushStack() in order to do this, but maintain the stack
142         setArray: function( elems ) {
143                 // Resetting the length to 0, then using the native Array push
144                 // is a super-fast way to populate an object with array-like properties
145                 this.length = 0;
146                 Array.prototype.push.apply( this, elems );
147
148                 return this;
149         },
150
151         // Execute a callback for every element in the matched set.
152         // (You can seed the arguments with an array of args, but this is
153         // only used internally.)
154         each: function( callback, args ) {
155                 return jQuery.each( this, callback, args );
156         },
157
158         // Determine the position of an element within
159         // the matched set of elements
160         index: function( elem ) {
161                 // Locate the position of the desired element
162                 return jQuery.inArray(
163                         // If it receives a jQuery object, the first element is used
164                         elem && elem.jquery ? elem[0] : elem
165                 , this );
166         },
167
168         attr: function( name, value, type ) {
169                 var options = name;
170
171                 // Look for the case where we're accessing a style value
172                 if ( typeof name === "string" )
173                         if ( value === undefined )
174                                 return this[0] && jQuery[ type || "attr" ]( this[0], name );
175
176                         else {
177                                 options = {};
178                                 options[ name ] = value;
179                         }
180
181                 // Check to see if we're setting style values
182                 return this.each(function(i){
183                         // Set all the styles
184                         for ( name in options )
185                                 jQuery.attr(
186                                         type ?
187                                                 this.style :
188                                                 this,
189                                         name, jQuery.prop( this, options[ name ], type, i, name )
190                                 );
191                 });
192         },
193
194         css: function( key, value ) {
195                 // ignore negative width and height values
196                 if ( (key == 'width' || key == 'height') && parseFloat(value) < 0 )
197                         value = undefined;
198                 return this.attr( key, value, "curCSS" );
199         },
200
201         text: function( text ) {
202                 if ( typeof text !== "object" && text != null )
203                         return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
204
205                 var ret = "";
206
207                 jQuery.each( text || this, function(){
208                         jQuery.each( this.childNodes, function(){
209                                 if ( this.nodeType != 8 )
210                                         ret += this.nodeType != 1 ?
211                                                 this.nodeValue :
212                                                 jQuery.fn.text( [ this ] );
213                         });
214                 });
215
216                 return ret;
217         },
218
219         wrapAll: function( html ) {
220                 if ( this[0] ) {
221                         // The elements to wrap the target around
222                         var wrap = jQuery( html, this[0].ownerDocument ).clone();
223
224                         if ( this[0].parentNode )
225                                 wrap.insertBefore( this[0] );
226
227                         wrap.map(function(){
228                                 var elem = this;
229
230                                 while ( elem.firstChild )
231                                         elem = elem.firstChild;
232
233                                 return elem;
234                         }).append(this);
235                 }
236
237                 return this;
238         },
239
240         wrapInner: function( html ) {
241                 return this.each(function(){
242                         jQuery( this ).contents().wrapAll( html );
243                 });
244         },
245
246         wrap: function( html ) {
247                 return this.each(function(){
248                         jQuery( this ).wrapAll( html );
249                 });
250         },
251
252         append: function() {
253                 return this.domManip(arguments, true, function(elem){
254                         if (this.nodeType == 1)
255                                 this.appendChild( elem );
256                 });
257         },
258
259         prepend: function() {
260                 return this.domManip(arguments, true, function(elem){
261                         if (this.nodeType == 1)
262                                 this.insertBefore( elem, this.firstChild );
263                 });
264         },
265
266         before: function() {
267                 return this.domManip(arguments, false, function(elem){
268                         this.parentNode.insertBefore( elem, this );
269                 });
270         },
271
272         after: function() {
273                 return this.domManip(arguments, false, function(elem){
274                         this.parentNode.insertBefore( elem, this.nextSibling );
275                 });
276         },
277
278         end: function() {
279                 return this.prevObject || jQuery( [] );
280         },
281
282         // For internal use only.
283         // Behaves like an Array's method, not like a jQuery method.
284         push: [].push,
285         sort: [].sort,
286         splice: [].splice,
287
288         find: function( selector ) {
289                 if ( this.length === 1 ) {
290                         var ret = this.pushStack( [], "find", selector );
291                         ret.length = 0;
292                         jQuery.find( selector, this[0], ret );
293                         return ret;
294                 } else {
295                         return this.pushStack( jQuery.unique(jQuery.map(this, function(elem){
296                                 return jQuery.find( selector, elem );
297                         })), "find", selector );
298                 }
299         },
300
301         clone: function( events ) {
302                 // Do the clone
303                 var ret = this.map(function(){
304                         if ( !jQuery.support.noCloneEvent && !jQuery.isXMLDoc(this) ) {
305                                 // IE copies events bound via attachEvent when
306                                 // using cloneNode. Calling detachEvent on the
307                                 // clone will also remove the events from the orignal
308                                 // In order to get around this, we use innerHTML.
309                                 // Unfortunately, this means some modifications to
310                                 // attributes in IE that are actually only stored
311                                 // as properties will not be copied (such as the
312                                 // the name attribute on an input).
313                                 var html = this.outerHTML;
314                                 if ( !html ) {
315                                         var div = this.ownerDocument.createElement("div");
316                                         div.appendChild( this.cloneNode(true) );
317                                         html = div.innerHTML;
318                                 }
319
320                                 return jQuery.clean([html.replace(/ jQuery\d+="(?:\d+|null)"/g, "").replace(/^\s*/, "")])[0];
321                         } else
322                                 return this.cloneNode(true);
323                 });
324
325                 // Copy the events from the original to the clone
326                 if ( events === true ) {
327                         var orig = this.find("*").andSelf(), i = 0;
328
329                         ret.find("*").andSelf().each(function(){
330                                 if ( this.nodeName !== orig[i].nodeName )
331                                         return;
332
333                                 var events = jQuery.data( orig[i], "events" );
334
335                                 for ( var type in events ) {
336                                         for ( var handler in events[ type ] ) {
337                                                 jQuery.event.add( this, type, events[ type ][ handler ], events[ type ][ handler ].data );
338                                         }
339                                 }
340
341                                 i++;
342                         });
343                 }
344
345                 // Return the cloned set
346                 return ret;
347         },
348
349         filter: function( selector ) {
350                 return this.pushStack(
351                         jQuery.isFunction( selector ) &&
352                         jQuery.grep(this, function(elem, i){
353                                 return selector.call( elem, i );
354                         }) ||
355
356                         jQuery.multiFilter( selector, jQuery.grep(this, function(elem){
357                                 return elem.nodeType === 1;
358                         }) ), "filter", selector );
359         },
360
361         closest: function( selector ) {
362                 var pos = jQuery.expr.match.POS.test( selector ) ? jQuery(selector) : null,
363                         closer = 0;
364
365                 return this.map(function(){
366                         var cur = this;
367                         while ( cur && cur.ownerDocument ) {
368                                 if ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selector) ) {
369                                         jQuery.data(cur, "closest", closer);
370                                         return cur;
371                                 }
372                                 cur = cur.parentNode;
373                                 closer++;
374                         }
375                 });
376         },
377
378         not: function( selector ) {
379                 if ( typeof selector === "string" )
380                         // test special case where just one selector is passed in
381                         if ( isSimple.test( selector ) )
382                                 return this.pushStack( jQuery.multiFilter( selector, this, true ), "not", selector );
383                         else
384                                 selector = jQuery.multiFilter( selector, this );
385
386                 var isArrayLike = selector.length && selector[selector.length - 1] !== undefined && !selector.nodeType;
387                 return this.filter(function() {
388                         return isArrayLike ? jQuery.inArray( this, selector ) < 0 : this != selector;
389                 });
390         },
391
392         add: function( selector ) {
393                 return this.pushStack( jQuery.unique( jQuery.merge(
394                         this.get(),
395                         typeof selector === "string" ?
396                                 jQuery( selector ) :
397                                 jQuery.makeArray( selector )
398                 )));
399         },
400
401         is: function( selector ) {
402                 return !!selector && jQuery.multiFilter( selector, this ).length > 0;
403         },
404
405         hasClass: function( selector ) {
406                 return !!selector && this.is( "." + selector );
407         },
408
409         val: function( value ) {
410                 if ( value === undefined ) {                    
411                         var elem = this[0];
412
413                         if ( elem ) {
414                                 if( jQuery.nodeName( elem, 'option' ) )
415                                         return (elem.attributes.value || {}).specified ? elem.value : elem.text;
416                                 
417                                 // We need to handle select boxes special
418                                 if ( jQuery.nodeName( elem, "select" ) ) {
419                                         var index = elem.selectedIndex,
420                                                 values = [],
421                                                 options = elem.options,
422                                                 one = elem.type == "select-one";
423
424                                         // Nothing was selected
425                                         if ( index < 0 )
426                                                 return null;
427
428                                         // Loop through all the selected options
429                                         for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
430                                                 var option = options[ i ];
431
432                                                 if ( option.selected ) {
433                                                         // Get the specifc value for the option
434                                                         value = jQuery(option).val();
435
436                                                         // We don't need an array for one selects
437                                                         if ( one )
438                                                                 return value;
439
440                                                         // Multi-Selects return an array
441                                                         values.push( value );
442                                                 }
443                                         }
444
445                                         return values;                          
446                                 }
447
448                                 // Everything else, we just grab the value
449                                 return (elem.value || "").replace(/\r/g, "");
450
451                         }
452
453                         return undefined;
454                 }
455
456                 if ( typeof value === "number" )
457                         value += '';
458
459                 return this.each(function(){
460                         if ( this.nodeType != 1 )
461                                 return;
462
463                         if ( jQuery.isArray(value) && /radio|checkbox/.test( this.type ) )
464                                 this.checked = (jQuery.inArray(this.value, value) >= 0 ||
465                                         jQuery.inArray(this.name, value) >= 0);
466
467                         else if ( jQuery.nodeName( this, "select" ) ) {
468                                 var values = jQuery.makeArray(value);
469
470                                 jQuery( "option", this ).each(function(){
471                                         this.selected = (jQuery.inArray( this.value, values ) >= 0 ||
472                                                 jQuery.inArray( this.text, values ) >= 0);
473                                 });
474
475                                 if ( !values.length )
476                                         this.selectedIndex = -1;
477
478                         } else
479                                 this.value = value;
480                 });
481         },
482
483         html: function( value ) {
484                 return value === undefined ?
485                         (this[0] ?
486                                 this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g, "") :
487                                 null) :
488                         this.empty().append( value );
489         },
490
491         replaceWith: function( value ) {
492                 return this.after( value ).remove();
493         },
494
495         eq: function( i ) {
496                 return this.slice( i, +i + 1 );
497         },
498
499         slice: function() {
500                 return this.pushStack( Array.prototype.slice.apply( this, arguments ),
501                         "slice", Array.prototype.slice.call(arguments).join(",") );
502         },
503
504         map: function( callback ) {
505                 return this.pushStack( jQuery.map(this, function(elem, i){
506                         return callback.call( elem, i, elem );
507                 }));
508         },
509
510         andSelf: function() {
511                 return this.add( this.prevObject );
512         },
513
514         domManip: function( args, table, callback ) {
515                 if ( this[0] ) {
516                         var fragment = (this[0].ownerDocument || this[0]).createDocumentFragment(),
517                                 scripts = jQuery.clean( args, (this[0].ownerDocument || this[0]), fragment ),
518                                 first = fragment.firstChild;
519
520                         if ( first )
521                                 for ( var i = 0, l = this.length; i < l; i++ )
522                                         callback.call( root(this[i], first), this.length > 1 || i > 0 ?
523                                                         fragment.cloneNode(true) : fragment );
524                 
525                         if ( scripts )
526                                 jQuery.each( scripts, evalScript );
527                 }
528
529                 return this;
530                 
531                 function root( elem, cur ) {
532                         return table && jQuery.nodeName(elem, "table") && jQuery.nodeName(cur, "tr") ?
533                                 (elem.getElementsByTagName("tbody")[0] ||
534                                 elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
535                                 elem;
536                 }
537         }
538 };
539
540 // Give the init function the jQuery prototype for later instantiation
541 jQuery.fn.init.prototype = jQuery.fn;
542
543 function evalScript( i, elem ) {
544         if ( elem.src )
545                 jQuery.ajax({
546                         url: elem.src,
547                         async: false,
548                         dataType: "script"
549                 });
550
551         else
552                 jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
553
554         if ( elem.parentNode )
555                 elem.parentNode.removeChild( elem );
556 }
557
558 function now(){
559         return +new Date;
560 }
561
562 jQuery.extend = jQuery.fn.extend = function() {
563         // copy reference to target object
564         var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;
565
566         // Handle a deep copy situation
567         if ( typeof target === "boolean" ) {
568                 deep = target;
569                 target = arguments[1] || {};
570                 // skip the boolean and the target
571                 i = 2;
572         }
573
574         // Handle case when target is a string or something (possible in deep copy)
575         if ( typeof target !== "object" && !jQuery.isFunction(target) )
576                 target = {};
577
578         // extend jQuery itself if only one argument is passed
579         if ( length == i ) {
580                 target = this;
581                 --i;
582         }
583
584         for ( ; i < length; i++ )
585                 // Only deal with non-null/undefined values
586                 if ( (options = arguments[ i ]) != null )
587                         // Extend the base object
588                         for ( var name in options ) {
589                                 var src = target[ name ], copy = options[ name ];
590
591                                 // Prevent never-ending loop
592                                 if ( target === copy )
593                                         continue;
594
595                                 // Recurse if we're merging object values
596                                 if ( deep && copy && typeof copy === "object" && !copy.nodeType )
597                                         target[ name ] = jQuery.extend( deep, 
598                                                 // Never move original objects, clone them
599                                                 src || ( copy.length != null ? [ ] : { } )
600                                         , copy );
601
602                                 // Don't bring in undefined values
603                                 else if ( copy !== undefined )
604                                         target[ name ] = copy;
605
606                         }
607
608         // Return the modified object
609         return target;
610 };
611
612 // exclude the following css properties to add px
613 var     exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i,
614         // cache defaultView
615         defaultView = document.defaultView || {},
616         toString = Object.prototype.toString;
617
618 jQuery.extend({
619         noConflict: function( deep ) {
620                 window.$ = _$;
621
622                 if ( deep )
623                         window.jQuery = _jQuery;
624
625                 return jQuery;
626         },
627
628         // See test/unit/core.js for details concerning isFunction.
629         // Since version 1.3, DOM methods and functions like alert
630         // aren't supported. They return false on IE (#2968).
631         isFunction: function( obj ) {
632                 return toString.call(obj) === "[object Function]";
633         },
634
635         isArray: function( obj ) {
636                 return toString.call(obj) === "[object Array]";
637         },
638
639         // check if an element is in a (or is an) XML document
640         isXMLDoc: function( elem ) {
641                 return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" ||
642                         !!elem.ownerDocument && jQuery.isXMLDoc( elem.ownerDocument );
643         },
644
645         // Evalulates a script in a global context
646         globalEval: function( data ) {
647                 if ( data && /\S/.test(data) ) {
648                         // Inspired by code by Andrea Giammarchi
649                         // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
650                         var head = document.getElementsByTagName("head")[0] || document.documentElement,
651                                 script = document.createElement("script");
652
653                         script.type = "text/javascript";
654                         if ( jQuery.support.scriptEval )
655                                 script.appendChild( document.createTextNode( data ) );
656                         else
657                                 script.text = data;
658
659                         // Use insertBefore instead of appendChild  to circumvent an IE6 bug.
660                         // This arises when a base node is used (#2709).
661                         head.insertBefore( script, head.firstChild );
662                         head.removeChild( script );
663                 }
664         },
665
666         nodeName: function( elem, name ) {
667                 return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase();
668         },
669
670         // args is for internal usage only
671         each: function( object, callback, args ) {
672                 var name, i = 0, length = object.length;
673
674                 if ( args ) {
675                         if ( length === undefined ) {
676                                 for ( name in object )
677                                         if ( callback.apply( object[ name ], args ) === false )
678                                                 break;
679                         } else
680                                 for ( ; i < length; )
681                                         if ( callback.apply( object[ i++ ], args ) === false )
682                                                 break;
683
684                 // A special, fast, case for the most common use of each
685                 } else {
686                         if ( length === undefined ) {
687                                 for ( name in object )
688                                         if ( callback.call( object[ name ], name, object[ name ] ) === false )
689                                                 break;
690                         } else
691                                 for ( var value = object[0];
692                                         i < length && callback.call( value, i, value ) !== false; value = object[++i] ){}
693                 }
694
695                 return object;
696         },
697
698         prop: function( elem, value, type, i, name ) {
699                 // Handle executable functions
700                 if ( jQuery.isFunction( value ) )
701                         value = value.call( elem, i );
702
703                 // Handle passing in a number to a CSS property
704                 return typeof value === "number" && type == "curCSS" && !exclude.test( name ) ?
705                         value + "px" :
706                         value;
707         },
708
709         className: {
710                 // internal only, use addClass("class")
711                 add: function( elem, classNames ) {
712                         jQuery.each((classNames || "").split(/\s+/), function(i, className){
713                                 if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) )
714                                         elem.className += (elem.className ? " " : "") + className;
715                         });
716                 },
717
718                 // internal only, use removeClass("class")
719                 remove: function( elem, classNames ) {
720                         if (elem.nodeType == 1)
721                                 elem.className = classNames !== undefined ?
722                                         jQuery.grep(elem.className.split(/\s+/), function(className){
723                                                 return !jQuery.className.has( classNames, className );
724                                         }).join(" ") :
725                                         "";
726                 },
727
728                 // internal only, use hasClass("class")
729                 has: function( elem, className ) {
730                         return elem && jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1;
731                 }
732         },
733
734         // A method for quickly swapping in/out CSS properties to get correct calculations
735         swap: function( elem, options, callback ) {
736                 var old = {};
737                 // Remember the old values, and insert the new ones
738                 for ( var name in options ) {
739                         old[ name ] = elem.style[ name ];
740                         elem.style[ name ] = options[ name ];
741                 }
742
743                 callback.call( elem );
744
745                 // Revert the old values
746                 for ( var name in options )
747                         elem.style[ name ] = old[ name ];
748         },
749
750         css: function( elem, name, force, extra ) {
751                 if ( name == "width" || name == "height" ) {
752                         var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ];
753
754                         function getWH() {
755                                 val = name == "width" ? elem.offsetWidth : elem.offsetHeight;
756
757                                 if ( extra === "border" )
758                                         return;
759
760                                 jQuery.each( which, function() {
761                                         if ( !extra )
762                                                 val -= parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0;
763                                         if ( extra === "margin" )
764                                                 val += parseFloat(jQuery.curCSS( elem, "margin" + this, true)) || 0;
765                                         else
766                                                 val -= parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0;
767                                 });
768                         }
769
770                         if ( elem.offsetWidth !== 0 )
771                                 getWH();
772                         else
773                                 jQuery.swap( elem, props, getWH );
774
775                         return Math.max(0, Math.round(val));
776                 }
777
778                 return jQuery.curCSS( elem, name, force );
779         },
780
781         curCSS: function( elem, name, force ) {
782                 var ret, style = elem.style;
783
784                 // We need to handle opacity special in IE
785                 if ( name == "opacity" && !jQuery.support.opacity ) {
786                         ret = jQuery.attr( style, "opacity" );
787
788                         return ret == "" ?
789                                 "1" :
790                                 ret;
791                 }
792
793                 // Make sure we're using the right name for getting the float value
794                 if ( name.match( /float/i ) )
795                         name = styleFloat;
796
797                 if ( !force && style && style[ name ] )
798                         ret = style[ name ];
799
800                 else if ( defaultView.getComputedStyle ) {
801
802                         // Only "float" is needed here
803                         if ( name.match( /float/i ) )
804                                 name = "float";
805
806                         name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase();
807
808                         var computedStyle = defaultView.getComputedStyle( elem, null );
809
810                         if ( computedStyle )
811                                 ret = computedStyle.getPropertyValue( name );
812
813                         // We should always get a number back from opacity
814                         if ( name == "opacity" && ret == "" )
815                                 ret = "1";
816
817                 } else if ( elem.currentStyle ) {
818                         var camelCase = name.replace(/\-(\w)/g, function(all, letter){
819                                 return letter.toUpperCase();
820                         });
821
822                         ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ];
823
824                         // From the awesome hack by Dean Edwards
825                         // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
826
827                         // If we're not dealing with a regular pixel number
828                         // but a number that has a weird ending, we need to convert it to pixels
829                         if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) {
830                                 // Remember the original values
831                                 var left = style.left, rsLeft = elem.runtimeStyle.left;
832
833                                 // Put in the new values to get a computed value out
834                                 elem.runtimeStyle.left = elem.currentStyle.left;
835                                 style.left = ret || 0;
836                                 ret = style.pixelLeft + "px";
837
838                                 // Revert the changed values
839                                 style.left = left;
840                                 elem.runtimeStyle.left = rsLeft;
841                         }
842                 }
843
844                 return ret;
845         },
846
847         clean: function( elems, context, fragment ) {
848                 context = context || document;
849
850                 // !context.createElement fails in IE with an error but returns typeof 'object'
851                 if ( typeof context.createElement === "undefined" )
852                         context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
853
854                 // If a single string is passed in and it's a single tag
855                 // just do a createElement and skip the rest
856                 if ( !fragment && elems.length === 1 && typeof elems[0] === "string" ) {
857                         var match = /^<(\w+)\s*\/?>$/.exec(elems[0]);
858                         if ( match )
859                                 return [ context.createElement( match[1] ) ];
860                 }
861
862                 var ret = [], scripts = [], div = context.createElement("div");
863
864                 jQuery.each(elems, function(i, elem){
865                         if ( typeof elem === "number" )
866                                 elem += '';
867
868                         if ( !elem )
869                                 return;
870
871                         // Convert html string into DOM nodes
872                         if ( typeof elem === "string" ) {
873                                 // Fix "XHTML"-style tags in all browsers
874                                 elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){
875                                         return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ?
876                                                 all :
877                                                 front + "></" + tag + ">";
878                                 });
879
880                                 // Trim whitespace, otherwise indexOf won't work as expected
881                                 var tags = elem.replace(/^\s+/, "").substring(0, 10).toLowerCase();
882
883                                 var wrap =
884                                         // option or optgroup
885                                         !tags.indexOf("<opt") &&
886                                         [ 1, "<select multiple='multiple'>", "</select>" ] ||
887
888                                         !tags.indexOf("<leg") &&
889                                         [ 1, "<fieldset>", "</fieldset>" ] ||
890
891                                         tags.match(/^<(thead|tbody|tfoot|colg|cap)/) &&
892                                         [ 1, "<table>", "</table>" ] ||
893
894                                         !tags.indexOf("<tr") &&
895                                         [ 2, "<table><tbody>", "</tbody></table>" ] ||
896
897                                         // <thead> matched above
898                                         (!tags.indexOf("<td") || !tags.indexOf("<th")) &&
899                                         [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ] ||
900
901                                         !tags.indexOf("<col") &&
902                                         [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ] ||
903
904                                         // IE can't serialize <link> and <script> tags normally
905                                         !jQuery.support.htmlSerialize &&
906                                         [ 1, "div<div>", "</div>" ] ||
907
908                                         [ 0, "", "" ];
909
910                                 // Go to html and back, then peel off extra wrappers
911                                 div.innerHTML = wrap[1] + elem + wrap[2];
912
913                                 // Move to the right depth
914                                 while ( wrap[0]-- )
915                                         div = div.lastChild;
916
917                                 // Remove IE's autoinserted <tbody> from table fragments
918                                 if ( !jQuery.support.tbody ) {
919
920                                         // String was a <table>, *may* have spurious <tbody>
921                                         var hasBody = /<tbody/i.test(elem),
922                                                 tbody = !tags.indexOf("<table") && !hasBody ?
923                                                         div.firstChild && div.firstChild.childNodes :
924
925                                                 // String was a bare <thead> or <tfoot>
926                                                 wrap[1] == "<table>" && !hasBody ?
927                                                         div.childNodes :
928                                                         [];
929
930                                         for ( var j = tbody.length - 1; j >= 0 ; --j )
931                                                 if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length )
932                                                         tbody[ j ].parentNode.removeChild( tbody[ j ] );
933
934                                         }
935
936                                 // IE completely kills leading whitespace when innerHTML is used
937                                 if ( !jQuery.support.leadingWhitespace && /^\s/.test( elem ) )
938                                         div.insertBefore( context.createTextNode( elem.match(/^\s*/)[0] ), div.firstChild );
939                                 
940                                 elem = jQuery.makeArray( div.childNodes );
941                         }
942
943                         if ( elem.nodeType )
944                                 ret.push( elem );
945                         else
946                                 ret = jQuery.merge( ret, elem );
947
948                 });
949
950                 if ( fragment ) {
951                         for ( var i = 0; ret[i]; i++ ) {
952                                 if ( jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
953                                         scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
954                                 } else {
955                                         if ( ret[i].nodeType === 1 )
956                                                 ret.splice.apply( ret, [i + 1, 0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))) );
957                                         fragment.appendChild( ret[i] );
958                                 }
959                         }
960                         
961                         return scripts;
962                 }
963
964                 return ret;
965         },
966
967         attr: function( elem, name, value ) {
968                 // don't set attributes on text and comment nodes
969                 if (!elem || elem.nodeType == 3 || elem.nodeType == 8)
970                         return undefined;
971
972                 var notxml = !jQuery.isXMLDoc( elem ),
973                         // Whether we are setting (or getting)
974                         set = value !== undefined;
975
976                 // Try to normalize/fix the name
977                 name = notxml && jQuery.props[ name ] || name;
978
979                 // Only do all the following if this is a node (faster for style)
980                 // IE elem.getAttribute passes even for style
981                 if ( elem.tagName ) {
982
983                         // These attributes require special treatment
984                         var special = /href|src|style/.test( name );
985
986                         // Safari mis-reports the default selected property of a hidden option
987                         // Accessing the parent's selectedIndex property fixes it
988                         if ( name == "selected" && elem.parentNode )
989                                 elem.parentNode.selectedIndex;
990
991                         // If applicable, access the attribute via the DOM 0 way
992                         if ( name in elem && notxml && !special ) {
993                                 if ( set ){
994                                         // We can't allow the type property to be changed (since it causes problems in IE)
995                                         if ( name == "type" && jQuery.nodeName( elem, "input" ) && elem.parentNode )
996                                                 throw "type property can't be changed";
997
998                                         elem[ name ] = value;
999                                 }
1000
1001                                 // browsers index elements by id/name on forms, give priority to attributes.
1002                                 if( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) )
1003                                         return elem.getAttributeNode( name ).nodeValue;
1004
1005                                 // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
1006                                 // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
1007                                 if ( name == "tabIndex" ) {
1008                                         var attributeNode = elem.getAttributeNode( "tabIndex" );
1009                                         return attributeNode && attributeNode.specified
1010                                                 ? attributeNode.value
1011                                                 : elem.nodeName.match(/(button|input|object|select|textarea)/i)
1012                                                         ? 0
1013                                                         : elem.nodeName.match(/^(a|area)$/i) && elem.href
1014                                                                 ? 0
1015                                                                 : undefined;
1016                                 }
1017
1018                                 return elem[ name ];
1019                         }
1020
1021                         if ( !jQuery.support.style && notxml &&  name == "style" )
1022                                 return jQuery.attr( elem.style, "cssText", value );
1023
1024                         if ( set )
1025                                 // convert the value to a string (all browsers do this but IE) see #1070
1026                                 elem.setAttribute( name, "" + value );
1027
1028                         var attr = !jQuery.support.hrefNormalized && notxml && special
1029                                         // Some attributes require a special call on IE
1030                                         ? elem.getAttribute( name, 2 )
1031                                         : elem.getAttribute( name );
1032
1033                         // Non-existent attributes return null, we normalize to undefined
1034                         return attr === null ? undefined : attr;
1035                 }
1036
1037                 // elem is actually elem.style ... set the style
1038
1039                 // IE uses filters for opacity
1040                 if ( !jQuery.support.opacity && name == "opacity" ) {
1041                         if ( set ) {
1042                                 // IE has trouble with opacity if it does not have layout
1043                                 // Force it by setting the zoom level
1044                                 elem.zoom = 1;
1045
1046                                 // Set the alpha filter to set the opacity
1047                                 elem.filter = (elem.filter || "").replace( /alpha\([^)]*\)/, "" ) +
1048                                         (parseInt( value ) + '' == "NaN" ? "" : "alpha(opacity=" + value * 100 + ")");
1049                         }
1050
1051                         return elem.filter && elem.filter.indexOf("opacity=") >= 0 ?
1052                                 (parseFloat( elem.filter.match(/opacity=([^)]*)/)[1] ) / 100) + '':
1053                                 "";
1054                 }
1055
1056                 name = name.replace(/-([a-z])/ig, function(all, letter){
1057                         return letter.toUpperCase();
1058                 });
1059
1060                 if ( set )
1061                         elem[ name ] = value;
1062
1063                 return elem[ name ];
1064         },
1065
1066         trim: function( text ) {
1067                 return (text || "").replace( /^\s+|\s+$/g, "" );
1068         },
1069
1070         makeArray: function( array ) {
1071                 var ret = [];
1072
1073                 if( array != null ){
1074                         var i = array.length;
1075                         // The window, strings (and functions) also have 'length'
1076                         if( i == null || typeof array === "string" || jQuery.isFunction(array) || array.setInterval )
1077                                 ret[0] = array;
1078                         else
1079                                 while( i )
1080                                         ret[--i] = array[i];
1081                 }
1082
1083                 return ret;
1084         },
1085
1086         inArray: function( elem, array ) {
1087                 for ( var i = 0, length = array.length; i < length; i++ )
1088                 // Use === because on IE, window == document
1089                         if ( array[ i ] === elem )
1090                                 return i;
1091
1092                 return -1;
1093         },
1094
1095         merge: function( first, second ) {
1096                 // We have to loop this way because IE & Opera overwrite the length
1097                 // expando of getElementsByTagName
1098                 var i = 0, elem, pos = first.length;
1099                 // Also, we need to make sure that the correct elements are being returned
1100                 // (IE returns comment nodes in a '*' query)
1101                 if ( !jQuery.support.getAll ) {
1102                         while ( (elem = second[ i++ ]) != null )
1103                                 if ( elem.nodeType != 8 )
1104                                         first[ pos++ ] = elem;
1105
1106                 } else
1107                         while ( (elem = second[ i++ ]) != null )
1108                                 first[ pos++ ] = elem;
1109
1110                 return first;
1111         },
1112
1113         unique: function( array ) {
1114                 var ret = [], done = {};
1115
1116                 try {
1117
1118                         for ( var i = 0, length = array.length; i < length; i++ ) {
1119                                 var id = jQuery.data( array[ i ] );
1120
1121                                 if ( !done[ id ] ) {
1122                                         done[ id ] = true;
1123                                         ret.push( array[ i ] );
1124                                 }
1125                         }
1126
1127                 } catch( e ) {
1128                         ret = array;
1129                 }
1130
1131                 return ret;
1132         },
1133
1134         grep: function( elems, callback, inv ) {
1135                 var ret = [];
1136
1137                 // Go through the array, only saving the items
1138                 // that pass the validator function
1139                 for ( var i = 0, length = elems.length; i < length; i++ )
1140                         if ( !inv != !callback( elems[ i ], i ) )
1141                                 ret.push( elems[ i ] );
1142
1143                 return ret;
1144         },
1145
1146         map: function( elems, callback ) {
1147                 var ret = [];
1148
1149                 // Go through the array, translating each of the items to their
1150                 // new value (or values).
1151                 for ( var i = 0, length = elems.length; i < length; i++ ) {
1152                         var value = callback( elems[ i ], i );
1153
1154                         if ( value != null )
1155                                 ret[ ret.length ] = value;
1156                 }
1157
1158                 return ret.concat.apply( [], ret );
1159         }
1160 });
1161
1162 // Use of jQuery.browser is deprecated.
1163 // It's included for backwards compatibility and plugins,
1164 // although they should work to migrate away.
1165
1166 var userAgent = navigator.userAgent.toLowerCase();
1167
1168 // Figure out what browser is being used
1169 jQuery.browser = {
1170         version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [0,'0'])[1],
1171         safari: /webkit/.test( userAgent ),
1172         opera: /opera/.test( userAgent ),
1173         msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ),
1174         mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent )
1175 };
1176
1177 jQuery.each({
1178         parent: function(elem){return elem.parentNode;},
1179         parents: function(elem){return jQuery.dir(elem,"parentNode");},
1180         next: function(elem){return jQuery.nth(elem,2,"nextSibling");},
1181         prev: function(elem){return jQuery.nth(elem,2,"previousSibling");},
1182         nextAll: function(elem){return jQuery.dir(elem,"nextSibling");},
1183         prevAll: function(elem){return jQuery.dir(elem,"previousSibling");},
1184         siblings: function(elem){return jQuery.sibling(elem.parentNode.firstChild,elem);},
1185         children: function(elem){return jQuery.sibling(elem.firstChild);},
1186         contents: function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes);}
1187 }, function(name, fn){
1188         jQuery.fn[ name ] = function( selector ) {
1189                 var ret = jQuery.map( this, fn );
1190
1191                 if ( selector && typeof selector == "string" )
1192                         ret = jQuery.multiFilter( selector, ret );
1193
1194                 return this.pushStack( jQuery.unique( ret ), name, selector );
1195         };
1196 });
1197
1198 jQuery.each({
1199         appendTo: "append",
1200         prependTo: "prepend",
1201         insertBefore: "before",
1202         insertAfter: "after",
1203         replaceAll: "replaceWith"
1204 }, function(name, original){
1205         jQuery.fn[ name ] = function( selector ) {
1206                 var ret = [], insert = jQuery( selector );
1207
1208                 for ( var i = 0, l = insert.length; i < l; i++ ) {
1209                         var elems = (i > 0 ? this.clone(true) : this).get();
1210                         jQuery.fn[ original ].apply( jQuery(insert[i]), elems );
1211                         ret = ret.concat( elems );
1212                 }
1213
1214                 return this.pushStack( ret, name, selector );
1215         };
1216 });
1217
1218 jQuery.each({
1219         removeAttr: function( name ) {
1220                 jQuery.attr( this, name, "" );
1221                 if (this.nodeType == 1)
1222                         this.removeAttribute( name );
1223         },
1224
1225         addClass: function( classNames ) {
1226                 jQuery.className.add( this, classNames );
1227         },
1228
1229         removeClass: function( classNames ) {
1230                 jQuery.className.remove( this, classNames );
1231         },
1232
1233         toggleClass: function( classNames, state ) {
1234                 if( typeof state !== "boolean" )
1235                         state = !jQuery.className.has( this, classNames );
1236                 jQuery.className[ state ? "add" : "remove" ]( this, classNames );
1237         },
1238
1239         remove: function( selector ) {
1240                 if ( !selector || jQuery.filter( selector, [ this ] ).length ) {
1241                         // Prevent memory leaks
1242                         jQuery( "*", this ).add([this]).each(function(){
1243                                 jQuery.event.remove(this);
1244                                 jQuery.removeData(this);
1245                         });
1246                         if (this.parentNode)
1247                                 this.parentNode.removeChild( this );
1248                 }
1249         },
1250
1251         empty: function() {
1252                 // Remove element nodes and prevent memory leaks
1253                 jQuery(this).children().remove();
1254
1255                 // Remove any remaining nodes
1256                 while ( this.firstChild )
1257                         this.removeChild( this.firstChild );
1258         }
1259 }, function(name, fn){
1260         jQuery.fn[ name ] = function(){
1261                 return this.each( fn, arguments );
1262         };
1263 });
1264
1265 // Helper function used by the dimensions and offset modules
1266 function num(elem, prop) {
1267         return elem[0] && parseInt( jQuery.curCSS(elem[0], prop, true), 10 ) || 0;
1268 }
1269 var expando = "jQuery" + now(), uuid = 0, windowData = {};\r
1270 \r
1271 jQuery.extend({\r
1272         cache: {},\r
1273 \r
1274         data: function( elem, name, data ) {\r
1275                 elem = elem == window ?\r
1276                         windowData :\r
1277                         elem;\r
1278 \r
1279                 var id = elem[ expando ];\r
1280 \r
1281                 // Compute a unique ID for the element\r
1282                 if ( !id )\r
1283                         id = elem[ expando ] = ++uuid;\r
1284 \r
1285                 // Only generate the data cache if we're\r
1286                 // trying to access or manipulate it\r
1287                 if ( name && !jQuery.cache[ id ] )\r
1288                         jQuery.cache[ id ] = {};\r
1289 \r
1290                 // Prevent overriding the named cache with undefined values\r
1291                 if ( data !== undefined )\r
1292                         jQuery.cache[ id ][ name ] = data;\r
1293 \r
1294                 // Return the named cache data, or the ID for the element\r
1295                 return name ?\r
1296                         jQuery.cache[ id ][ name ] :\r
1297                         id;\r
1298         },\r
1299 \r
1300         removeData: function( elem, name ) {\r
1301                 elem = elem == window ?\r
1302                         windowData :\r
1303                         elem;\r
1304 \r
1305                 var id = elem[ expando ];\r
1306 \r
1307                 // If we want to remove a specific section of the element's data\r
1308                 if ( name ) {\r
1309                         if ( jQuery.cache[ id ] ) {\r
1310                                 // Remove the section of cache data\r
1311                                 delete jQuery.cache[ id ][ name ];\r
1312 \r
1313                                 // If we've removed all the data, remove the element's cache\r
1314                                 name = "";\r
1315 \r
1316                                 for ( name in jQuery.cache[ id ] )\r
1317                                         break;\r
1318 \r
1319                                 if ( !name )\r
1320                                         jQuery.removeData( elem );\r
1321                         }\r
1322 \r
1323                 // Otherwise, we want to remove all of the element's data\r
1324                 } else {\r
1325                         // Clean up the element expando\r
1326                         try {\r
1327                                 delete elem[ expando ];\r
1328                         } catch(e){\r
1329                                 // IE has trouble directly removing the expando\r
1330                                 // but it's ok with using removeAttribute\r
1331                                 if ( elem.removeAttribute )\r
1332                                         elem.removeAttribute( expando );\r
1333                         }\r
1334 \r
1335                         // Completely remove the data cache\r
1336                         delete jQuery.cache[ id ];\r
1337                 }\r
1338         },\r
1339         queue: function( elem, type, data ) {\r
1340                 if ( elem ){\r
1341         \r
1342                         type = (type || "fx") + "queue";\r
1343         \r
1344                         var q = jQuery.data( elem, type );\r
1345         \r
1346                         if ( !q || jQuery.isArray(data) )\r
1347                                 q = jQuery.data( elem, type, jQuery.makeArray(data) );\r
1348                         else if( data )\r
1349                                 q.push( data );\r
1350         \r
1351                 }\r
1352                 return q;\r
1353         },\r
1354 \r
1355         dequeue: function( elem, type ){\r
1356                 var queue = jQuery.queue( elem, type ),\r
1357                         fn = queue.shift();\r
1358                 \r
1359                 if( !type || type === "fx" )\r
1360                         fn = queue[0];\r
1361                         \r
1362                 if( fn !== undefined )\r
1363                         fn.call(elem);\r
1364         }\r
1365 });\r
1366 \r
1367 jQuery.fn.extend({\r
1368         data: function( key, value ){\r
1369                 var parts = key.split(".");\r
1370                 parts[1] = parts[1] ? "." + parts[1] : "";\r
1371 \r
1372                 if ( value === undefined ) {\r
1373                         var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);\r
1374 \r
1375                         if ( data === undefined && this.length )\r
1376                                 data = jQuery.data( this[0], key );\r
1377 \r
1378                         return data === undefined && parts[1] ?\r
1379                                 this.data( parts[0] ) :\r
1380                                 data;\r
1381                 } else\r
1382                         return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function(){\r
1383                                 jQuery.data( this, key, value );\r
1384                         });\r
1385         },\r
1386 \r
1387         removeData: function( key ){\r
1388                 return this.each(function(){\r
1389                         jQuery.removeData( this, key );\r
1390                 });\r
1391         },\r
1392         queue: function(type, data){\r
1393                 if ( typeof type !== "string" ) {\r
1394                         data = type;\r
1395                         type = "fx";\r
1396                 }\r
1397 \r
1398                 if ( data === undefined )\r
1399                         return jQuery.queue( this[0], type );\r
1400 \r
1401                 return this.each(function(){\r
1402                         var queue = jQuery.queue( this, type, data );\r
1403                         \r
1404                          if( type == "fx" && queue.length == 1 )\r
1405                                 queue[0].call(this);\r
1406                 });\r
1407         },\r
1408         dequeue: function(type){\r
1409                 return this.each(function(){\r
1410                         jQuery.dequeue( this, type );\r
1411                 });\r
1412         }\r
1413 });/*!
1414  * Sizzle CSS Selector Engine - v0.9.3
1415  *  Copyright 2009, The Dojo Foundation
1416  *  Released under the MIT, BSD, and GPL Licenses.
1417  *  More information: http://sizzlejs.com/
1418  */
1419 (function(){
1420
1421 var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,
1422         done = 0,
1423         toString = Object.prototype.toString;
1424
1425 var Sizzle = function(selector, context, results, seed) {
1426         results = results || [];
1427         context = context || document;
1428
1429         if ( context.nodeType !== 1 && context.nodeType !== 9 )
1430                 return [];
1431         
1432         if ( !selector || typeof selector !== "string" ) {
1433                 return results;
1434         }
1435
1436         var parts = [], m, set, checkSet, check, mode, extra, prune = true;
1437         
1438         // Reset the position of the chunker regexp (start from head)
1439         chunker.lastIndex = 0;
1440         
1441         while ( (m = chunker.exec(selector)) !== null ) {
1442                 parts.push( m[1] );
1443                 
1444                 if ( m[2] ) {
1445                         extra = RegExp.rightContext;
1446                         break;
1447                 }
1448         }
1449
1450         if ( parts.length > 1 && origPOS.exec( selector ) ) {
1451                 if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
1452                         set = posProcess( parts[0] + parts[1], context );
1453                 } else {
1454                         set = Expr.relative[ parts[0] ] ?
1455                                 [ context ] :
1456                                 Sizzle( parts.shift(), context );
1457
1458                         while ( parts.length ) {
1459                                 selector = parts.shift();
1460
1461                                 if ( Expr.relative[ selector ] )
1462                                         selector += parts.shift();
1463
1464                                 set = posProcess( selector, set );
1465                         }
1466                 }
1467         } else {
1468                 var ret = seed ?
1469                         { expr: parts.pop(), set: makeArray(seed) } :
1470                         Sizzle.find( parts.pop(), parts.length === 1 && context.parentNode ? context.parentNode : context, isXML(context) );
1471                 set = Sizzle.filter( ret.expr, ret.set );
1472
1473                 if ( parts.length > 0 ) {
1474                         checkSet = makeArray(set);
1475                 } else {
1476                         prune = false;
1477                 }
1478
1479                 while ( parts.length ) {
1480                         var cur = parts.pop(), pop = cur;
1481
1482                         if ( !Expr.relative[ cur ] ) {
1483                                 cur = "";
1484                         } else {
1485                                 pop = parts.pop();
1486                         }
1487
1488                         if ( pop == null ) {
1489                                 pop = context;
1490                         }
1491
1492                         Expr.relative[ cur ]( checkSet, pop, isXML(context) );
1493                 }
1494         }
1495
1496         if ( !checkSet ) {
1497                 checkSet = set;
1498         }
1499
1500         if ( !checkSet ) {
1501                 throw "Syntax error, unrecognized expression: " + (cur || selector);
1502         }
1503
1504         if ( toString.call(checkSet) === "[object Array]" ) {
1505                 if ( !prune ) {
1506                         results.push.apply( results, checkSet );
1507                 } else if ( context.nodeType === 1 ) {
1508                         for ( var i = 0; checkSet[i] != null; i++ ) {
1509                                 if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) {
1510                                         results.push( set[i] );
1511                                 }
1512                         }
1513                 } else {
1514                         for ( var i = 0; checkSet[i] != null; i++ ) {
1515                                 if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
1516                                         results.push( set[i] );
1517                                 }
1518                         }
1519                 }
1520         } else {
1521                 makeArray( checkSet, results );
1522         }
1523
1524         if ( extra ) {
1525                 Sizzle( extra, context, results, seed );
1526
1527                 if ( sortOrder ) {
1528                         hasDuplicate = false;
1529                         results.sort(sortOrder);
1530
1531                         if ( hasDuplicate ) {
1532                                 for ( var i = 1; i < results.length; i++ ) {
1533                                         if ( results[i] === results[i-1] ) {
1534                                                 results.splice(i--, 1);
1535                                         }
1536                                 }
1537                         }
1538                 }
1539         }
1540
1541         return results;
1542 };
1543
1544 Sizzle.matches = function(expr, set){
1545         return Sizzle(expr, null, null, set);
1546 };
1547
1548 Sizzle.find = function(expr, context, isXML){
1549         var set, match;
1550
1551         if ( !expr ) {
1552                 return [];
1553         }
1554
1555         for ( var i = 0, l = Expr.order.length; i < l; i++ ) {
1556                 var type = Expr.order[i], match;
1557                 
1558                 if ( (match = Expr.match[ type ].exec( expr )) ) {
1559                         var left = RegExp.leftContext;
1560
1561                         if ( left.substr( left.length - 1 ) !== "\\" ) {
1562                                 match[1] = (match[1] || "").replace(/\\/g, "");
1563                                 set = Expr.find[ type ]( match, context, isXML );
1564                                 if ( set != null ) {
1565                                         expr = expr.replace( Expr.match[ type ], "" );
1566                                         break;
1567                                 }
1568                         }
1569                 }
1570         }
1571
1572         if ( !set ) {
1573                 set = context.getElementsByTagName("*");
1574         }
1575
1576         return {set: set, expr: expr};
1577 };
1578
1579 Sizzle.filter = function(expr, set, inplace, not){
1580         var old = expr, result = [], curLoop = set, match, anyFound,
1581                 isXMLFilter = set && set[0] && isXML(set[0]);
1582
1583         while ( expr && set.length ) {
1584                 for ( var type in Expr.filter ) {
1585                         if ( (match = Expr.match[ type ].exec( expr )) != null ) {
1586                                 var filter = Expr.filter[ type ], found, item;
1587                                 anyFound = false;
1588
1589                                 if ( curLoop == result ) {
1590                                         result = [];
1591                                 }
1592
1593                                 if ( Expr.preFilter[ type ] ) {
1594                                         match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );
1595
1596                                         if ( !match ) {
1597                                                 anyFound = found = true;
1598                                         } else if ( match === true ) {
1599                                                 continue;
1600                                         }
1601                                 }
1602
1603                                 if ( match ) {
1604                                         for ( var i = 0; (item = curLoop[i]) != null; i++ ) {
1605                                                 if ( item ) {
1606                                                         found = filter( item, match, i, curLoop );
1607                                                         var pass = not ^ !!found;
1608
1609                                                         if ( inplace && found != null ) {
1610                                                                 if ( pass ) {
1611                                                                         anyFound = true;
1612                                                                 } else {
1613                                                                         curLoop[i] = false;
1614                                                                 }
1615                                                         } else if ( pass ) {
1616                                                                 result.push( item );
1617                                                                 anyFound = true;
1618                                                         }
1619                                                 }
1620                                         }
1621                                 }
1622
1623                                 if ( found !== undefined ) {
1624                                         if ( !inplace ) {
1625                                                 curLoop = result;
1626                                         }
1627
1628                                         expr = expr.replace( Expr.match[ type ], "" );
1629
1630                                         if ( !anyFound ) {
1631                                                 return [];
1632                                         }
1633
1634                                         break;
1635                                 }
1636                         }
1637                 }
1638
1639                 // Improper expression
1640                 if ( expr == old ) {
1641                         if ( anyFound == null ) {
1642                                 throw "Syntax error, unrecognized expression: " + expr;
1643                         } else {
1644                                 break;
1645                         }
1646                 }
1647
1648                 old = expr;
1649         }
1650
1651         return curLoop;
1652 };
1653
1654 var Expr = Sizzle.selectors = {
1655         order: [ "ID", "NAME", "TAG" ],
1656         match: {
1657                 ID: /#((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,
1658                 CLASS: /\.((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,
1659                 NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF_-]|\\.)+)['"]*\]/,
1660                 ATTR: /\[\s*((?:[\w\u00c0-\uFFFF_-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,
1661                 TAG: /^((?:[\w\u00c0-\uFFFF\*_-]|\\.)+)/,
1662                 CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,
1663                 POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,
1664                 PSEUDO: /:((?:[\w\u00c0-\uFFFF_-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/
1665         },
1666         attrMap: {
1667                 "class": "className",
1668                 "for": "htmlFor"
1669         },
1670         attrHandle: {
1671                 href: function(elem){
1672                         return elem.getAttribute("href");
1673                 }
1674         },
1675         relative: {
1676                 "+": function(checkSet, part, isXML){
1677                         var isPartStr = typeof part === "string",
1678                                 isTag = isPartStr && !/\W/.test(part),
1679                                 isPartStrNotTag = isPartStr && !isTag;
1680
1681                         if ( isTag && !isXML ) {
1682                                 part = part.toUpperCase();
1683                         }
1684
1685                         for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
1686                                 if ( (elem = checkSet[i]) ) {
1687                                         while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
1688
1689                                         checkSet[i] = isPartStrNotTag || elem && elem.nodeName === part ?
1690                                                 elem || false :
1691                                                 elem === part;
1692                                 }
1693                         }
1694
1695                         if ( isPartStrNotTag ) {
1696                                 Sizzle.filter( part, checkSet, true );
1697                         }
1698                 },
1699                 ">": function(checkSet, part, isXML){
1700                         var isPartStr = typeof part === "string";
1701
1702                         if ( isPartStr && !/\W/.test(part) ) {
1703                                 part = isXML ? part : part.toUpperCase();
1704
1705                                 for ( var i = 0, l = checkSet.length; i < l; i++ ) {
1706                                         var elem = checkSet[i];
1707                                         if ( elem ) {
1708                                                 var parent = elem.parentNode;
1709                                                 checkSet[i] = parent.nodeName === part ? parent : false;
1710                                         }
1711                                 }
1712                         } else {
1713                                 for ( var i = 0, l = checkSet.length; i < l; i++ ) {
1714                                         var elem = checkSet[i];
1715                                         if ( elem ) {
1716                                                 checkSet[i] = isPartStr ?
1717                                                         elem.parentNode :
1718                                                         elem.parentNode === part;
1719                                         }
1720                                 }
1721
1722                                 if ( isPartStr ) {
1723                                         Sizzle.filter( part, checkSet, true );
1724                                 }
1725                         }
1726                 },
1727                 "": function(checkSet, part, isXML){
1728                         var doneName = done++, checkFn = dirCheck;
1729
1730                         if ( !part.match(/\W/) ) {
1731                                 var nodeCheck = part = isXML ? part : part.toUpperCase();
1732                                 checkFn = dirNodeCheck;
1733                         }
1734
1735                         checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML);
1736                 },
1737                 "~": function(checkSet, part, isXML){
1738                         var doneName = done++, checkFn = dirCheck;
1739
1740                         if ( typeof part === "string" && !part.match(/\W/) ) {
1741                                 var nodeCheck = part = isXML ? part : part.toUpperCase();
1742                                 checkFn = dirNodeCheck;
1743                         }
1744
1745                         checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML);
1746                 }
1747         },
1748         find: {
1749                 ID: function(match, context, isXML){
1750                         if ( typeof context.getElementById !== "undefined" && !isXML ) {
1751                                 var m = context.getElementById(match[1]);
1752                                 return m ? [m] : [];
1753                         }
1754                 },
1755                 NAME: function(match, context, isXML){
1756                         if ( typeof context.getElementsByName !== "undefined" ) {
1757                                 var ret = [], results = context.getElementsByName(match[1]);
1758
1759                                 for ( var i = 0, l = results.length; i < l; i++ ) {
1760                                         if ( results[i].getAttribute("name") === match[1] ) {
1761                                                 ret.push( results[i] );
1762                                         }
1763                                 }
1764
1765                                 return ret.length === 0 ? null : ret;
1766                         }
1767                 },
1768                 TAG: function(match, context){
1769                         return context.getElementsByTagName(match[1]);
1770                 }
1771         },
1772         preFilter: {
1773                 CLASS: function(match, curLoop, inplace, result, not, isXML){
1774                         match = " " + match[1].replace(/\\/g, "") + " ";
1775
1776                         if ( isXML ) {
1777                                 return match;
1778                         }
1779
1780                         for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
1781                                 if ( elem ) {
1782                                         if ( not ^ (elem.className && (" " + elem.className + " ").indexOf(match) >= 0) ) {
1783                                                 if ( !inplace )
1784                                                         result.push( elem );
1785                                         } else if ( inplace ) {
1786                                                 curLoop[i] = false;
1787                                         }
1788                                 }
1789                         }
1790
1791                         return false;
1792                 },
1793                 ID: function(match){
1794                         return match[1].replace(/\\/g, "");
1795                 },
1796                 TAG: function(match, curLoop){
1797                         for ( var i = 0; curLoop[i] === false; i++ ){}
1798                         return curLoop[i] && isXML(curLoop[i]) ? match[1] : match[1].toUpperCase();
1799                 },
1800                 CHILD: function(match){
1801                         if ( match[1] == "nth" ) {
1802                                 // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
1803                                 var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
1804                                         match[2] == "even" && "2n" || match[2] == "odd" && "2n+1" ||
1805                                         !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
1806
1807                                 // calculate the numbers (first)n+(last) including if they are negative
1808                                 match[2] = (test[1] + (test[2] || 1)) - 0;
1809                                 match[3] = test[3] - 0;
1810                         }
1811
1812                         // TODO: Move to normal caching system
1813                         match[0] = done++;
1814
1815                         return match;
1816                 },
1817                 ATTR: function(match, curLoop, inplace, result, not, isXML){
1818                         var name = match[1].replace(/\\/g, "");
1819                         
1820                         if ( !isXML && Expr.attrMap[name] ) {
1821                                 match[1] = Expr.attrMap[name];
1822                         }
1823
1824                         if ( match[2] === "~=" ) {
1825                                 match[4] = " " + match[4] + " ";
1826                         }
1827
1828                         return match;
1829                 },
1830                 PSEUDO: function(match, curLoop, inplace, result, not){
1831                         if ( match[1] === "not" ) {
1832                                 // If we're dealing with a complex expression, or a simple one
1833                                 if ( match[3].match(chunker).length > 1 || /^\w/.test(match[3]) ) {
1834                                         match[3] = Sizzle(match[3], null, null, curLoop);
1835                                 } else {
1836                                         var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
1837                                         if ( !inplace ) {
1838                                                 result.push.apply( result, ret );
1839                                         }
1840                                         return false;
1841                                 }
1842                         } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
1843                                 return true;
1844                         }
1845                         
1846                         return match;
1847                 },
1848                 POS: function(match){
1849                         match.unshift( true );
1850                         return match;
1851                 }
1852         },
1853         filters: {
1854                 enabled: function(elem){
1855                         return elem.disabled === false && elem.type !== "hidden";
1856                 },
1857                 disabled: function(elem){
1858                         return elem.disabled === true;
1859                 },
1860                 checked: function(elem){
1861                         return elem.checked === true;
1862                 },
1863                 selected: function(elem){
1864                         // Accessing this property makes selected-by-default
1865                         // options in Safari work properly
1866                         elem.parentNode.selectedIndex;
1867                         return elem.selected === true;
1868                 },
1869                 parent: function(elem){
1870                         return !!elem.firstChild;
1871                 },
1872                 empty: function(elem){
1873                         return !elem.firstChild;
1874                 },
1875                 has: function(elem, i, match){
1876                         return !!Sizzle( match[3], elem ).length;
1877                 },
1878                 header: function(elem){
1879                         return /h\d/i.test( elem.nodeName );
1880                 },
1881                 text: function(elem){
1882                         return "text" === elem.type;
1883                 },
1884                 radio: function(elem){
1885                         return "radio" === elem.type;
1886                 },
1887                 checkbox: function(elem){
1888                         return "checkbox" === elem.type;
1889                 },
1890                 file: function(elem){
1891                         return "file" === elem.type;
1892                 },
1893                 password: function(elem){
1894                         return "password" === elem.type;
1895                 },
1896                 submit: function(elem){
1897                         return "submit" === elem.type;
1898                 },
1899                 image: function(elem){
1900                         return "image" === elem.type;
1901                 },
1902                 reset: function(elem){
1903                         return "reset" === elem.type;
1904                 },
1905                 button: function(elem){
1906                         return "button" === elem.type || elem.nodeName.toUpperCase() === "BUTTON";
1907                 },
1908                 input: function(elem){
1909                         return /input|select|textarea|button/i.test(elem.nodeName);
1910                 }
1911         },
1912         setFilters: {
1913                 first: function(elem, i){
1914                         return i === 0;
1915                 },
1916                 last: function(elem, i, match, array){
1917                         return i === array.length - 1;
1918                 },
1919                 even: function(elem, i){
1920                         return i % 2 === 0;
1921                 },
1922                 odd: function(elem, i){
1923                         return i % 2 === 1;
1924                 },
1925                 lt: function(elem, i, match){
1926                         return i < match[3] - 0;
1927                 },
1928                 gt: function(elem, i, match){
1929                         return i > match[3] - 0;
1930                 },
1931                 nth: function(elem, i, match){
1932                         return match[3] - 0 == i;
1933                 },
1934                 eq: function(elem, i, match){
1935                         return match[3] - 0 == i;
1936                 }
1937         },
1938         filter: {
1939                 PSEUDO: function(elem, match, i, array){
1940                         var name = match[1], filter = Expr.filters[ name ];
1941
1942                         if ( filter ) {
1943                                 return filter( elem, i, match, array );
1944                         } else if ( name === "contains" ) {
1945                                 return (elem.textContent || elem.innerText || "").indexOf(match[3]) >= 0;
1946                         } else if ( name === "not" ) {
1947                                 var not = match[3];
1948
1949                                 for ( var i = 0, l = not.length; i < l; i++ ) {
1950                                         if ( not[i] === elem ) {
1951                                                 return false;
1952                                         }
1953                                 }
1954
1955                                 return true;
1956                         }
1957                 },
1958                 CHILD: function(elem, match){
1959                         var type = match[1], node = elem;
1960                         switch (type) {
1961                                 case 'only':
1962                                 case 'first':
1963                                         while (node = node.previousSibling)  {
1964                                                 if ( node.nodeType === 1 ) return false;
1965                                         }
1966                                         if ( type == 'first') return true;
1967                                         node = elem;
1968                                 case 'last':
1969                                         while (node = node.nextSibling)  {
1970                                                 if ( node.nodeType === 1 ) return false;
1971                                         }
1972                                         return true;
1973                                 case 'nth':
1974                                         var first = match[2], last = match[3];
1975
1976                                         if ( first == 1 && last == 0 ) {
1977                                                 return true;
1978                                         }
1979                                         
1980                                         var doneName = match[0],
1981                                                 parent = elem.parentNode;
1982         
1983                                         if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {
1984                                                 var count = 0;
1985                                                 for ( node = parent.firstChild; node; node = node.nextSibling ) {
1986                                                         if ( node.nodeType === 1 ) {
1987                                                                 node.nodeIndex = ++count;
1988                                                         }
1989                                                 } 
1990                                                 parent.sizcache = doneName;
1991                                         }
1992                                         
1993                                         var diff = elem.nodeIndex - last;
1994                                         if ( first == 0 ) {
1995                                                 return diff == 0;
1996                                         } else {
1997                                                 return ( diff % first == 0 && diff / first >= 0 );
1998                                         }
1999                         }
2000                 },
2001                 ID: function(elem, match){
2002                         return elem.nodeType === 1 && elem.getAttribute("id") === match;
2003                 },
2004                 TAG: function(elem, match){
2005                         return (match === "*" && elem.nodeType === 1) || elem.nodeName === match;
2006                 },
2007                 CLASS: function(elem, match){
2008                         return (" " + (elem.className || elem.getAttribute("class")) + " ")
2009                                 .indexOf( match ) > -1;
2010                 },
2011                 ATTR: function(elem, match){
2012                         var name = match[1],
2013                                 result = Expr.attrHandle[ name ] ?
2014                                         Expr.attrHandle[ name ]( elem ) :
2015                                         elem[ name ] != null ?
2016                                                 elem[ name ] :
2017                                                 elem.getAttribute( name ),
2018                                 value = result + "",
2019                                 type = match[2],
2020                                 check = match[4];
2021
2022                         return result == null ?
2023                                 type === "!=" :
2024                                 type === "=" ?
2025                                 value === check :
2026                                 type === "*=" ?
2027                                 value.indexOf(check) >= 0 :
2028                                 type === "~=" ?
2029                                 (" " + value + " ").indexOf(check) >= 0 :
2030                                 !check ?
2031                                 value && result !== false :
2032                                 type === "!=" ?
2033                                 value != check :
2034                                 type === "^=" ?
2035                                 value.indexOf(check) === 0 :
2036                                 type === "$=" ?
2037                                 value.substr(value.length - check.length) === check :
2038                                 type === "|=" ?
2039                                 value === check || value.substr(0, check.length + 1) === check + "-" :
2040                                 false;
2041                 },
2042                 POS: function(elem, match, i, array){
2043                         var name = match[2], filter = Expr.setFilters[ name ];
2044
2045                         if ( filter ) {
2046                                 return filter( elem, i, match, array );
2047                         }
2048                 }
2049         }
2050 };
2051
2052 var origPOS = Expr.match.POS;
2053
2054 for ( var type in Expr.match ) {
2055         Expr.match[ type ] = RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source );
2056 }
2057
2058 var makeArray = function(array, results) {
2059         array = Array.prototype.slice.call( array );
2060
2061         if ( results ) {
2062                 results.push.apply( results, array );
2063                 return results;
2064         }
2065         
2066         return array;
2067 };
2068
2069 // Perform a simple check to determine if the browser is capable of
2070 // converting a NodeList to an array using builtin methods.
2071 try {
2072         Array.prototype.slice.call( document.documentElement.childNodes );
2073
2074 // Provide a fallback method if it does not work
2075 } catch(e){
2076         makeArray = function(array, results) {
2077                 var ret = results || [];
2078
2079                 if ( toString.call(array) === "[object Array]" ) {
2080                         Array.prototype.push.apply( ret, array );
2081                 } else {
2082                         if ( typeof array.length === "number" ) {
2083                                 for ( var i = 0, l = array.length; i < l; i++ ) {
2084                                         ret.push( array[i] );
2085                                 }
2086                         } else {
2087                                 for ( var i = 0; array[i]; i++ ) {
2088                                         ret.push( array[i] );
2089                                 }
2090                         }
2091                 }
2092
2093                 return ret;
2094         };
2095 }
2096
2097 var sortOrder;
2098
2099 if ( document.documentElement.compareDocumentPosition ) {
2100         sortOrder = function( a, b ) {
2101                 var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1;
2102                 if ( ret === 0 ) {
2103                         hasDuplicate = true;
2104                 }
2105                 return ret;
2106         };
2107 } else if ( "sourceIndex" in document.documentElement ) {
2108         sortOrder = function( a, b ) {
2109                 var ret = a.sourceIndex - b.sourceIndex;
2110                 if ( ret === 0 ) {
2111                         hasDuplicate = true;
2112                 }
2113                 return ret;
2114         };
2115 } else if ( document.createRange ) {
2116         sortOrder = function( a, b ) {
2117                 var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange();
2118                 aRange.selectNode(a);
2119                 aRange.collapse(true);
2120                 bRange.selectNode(b);
2121                 bRange.collapse(true);
2122                 var ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange);
2123                 if ( ret === 0 ) {
2124                         hasDuplicate = true;
2125                 }
2126                 return ret;
2127         };
2128 }
2129
2130 // Check to see if the browser returns elements by name when
2131 // querying by getElementById (and provide a workaround)
2132 (function(){
2133         // We're going to inject a fake input element with a specified name
2134         var form = document.createElement("form"),
2135                 id = "script" + (new Date).getTime();
2136         form.innerHTML = "<input name='" + id + "'/>";
2137
2138         // Inject it into the root element, check its status, and remove it quickly
2139         var root = document.documentElement;
2140         root.insertBefore( form, root.firstChild );
2141
2142         // The workaround has to do additional checks after a getElementById
2143         // Which slows things down for other browsers (hence the branching)
2144         if ( !!document.getElementById( id ) ) {
2145                 Expr.find.ID = function(match, context, isXML){
2146                         if ( typeof context.getElementById !== "undefined" && !isXML ) {
2147                                 var m = context.getElementById(match[1]);
2148                                 return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : [];
2149                         }
2150                 };
2151
2152                 Expr.filter.ID = function(elem, match){
2153                         var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
2154                         return elem.nodeType === 1 && node && node.nodeValue === match;
2155                 };
2156         }
2157
2158         root.removeChild( form );
2159 })();
2160
2161 (function(){
2162         // Check to see if the browser returns only elements
2163         // when doing getElementsByTagName("*")
2164
2165         // Create a fake element
2166         var div = document.createElement("div");
2167         div.appendChild( document.createComment("") );
2168
2169         // Make sure no comments are found
2170         if ( div.getElementsByTagName("*").length > 0 ) {
2171                 Expr.find.TAG = function(match, context){
2172                         var results = context.getElementsByTagName(match[1]);
2173
2174                         // Filter out possible comments
2175                         if ( match[1] === "*" ) {
2176                                 var tmp = [];
2177
2178                                 for ( var i = 0; results[i]; i++ ) {
2179                                         if ( results[i].nodeType === 1 ) {
2180                                                 tmp.push( results[i] );
2181                                         }
2182                                 }
2183
2184                                 results = tmp;
2185                         }
2186
2187                         return results;
2188                 };
2189         }
2190
2191         // Check to see if an attribute returns normalized href attributes
2192         div.innerHTML = "<a href='#'></a>";
2193         if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
2194                         div.firstChild.getAttribute("href") !== "#" ) {
2195                 Expr.attrHandle.href = function(elem){
2196                         return elem.getAttribute("href", 2);
2197                 };
2198         }
2199 })();
2200
2201 if ( document.querySelectorAll ) (function(){
2202         var oldSizzle = Sizzle, div = document.createElement("div");
2203         div.innerHTML = "<p class='TEST'></p>";
2204
2205         // Safari can't handle uppercase or unicode characters when
2206         // in quirks mode.
2207         if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
2208                 return;
2209         }
2210         
2211         Sizzle = function(query, context, extra, seed){
2212                 context = context || document;
2213
2214                 // Only use querySelectorAll on non-XML documents
2215                 // (ID selectors don't work in non-HTML documents)
2216                 if ( !seed && context.nodeType === 9 && !isXML(context) ) {
2217                         try {
2218                                 return makeArray( context.querySelectorAll(query), extra );
2219                         } catch(e){}
2220                 }
2221                 
2222                 return oldSizzle(query, context, extra, seed);
2223         };
2224
2225         Sizzle.find = oldSizzle.find;
2226         Sizzle.filter = oldSizzle.filter;
2227         Sizzle.selectors = oldSizzle.selectors;
2228         Sizzle.matches = oldSizzle.matches;
2229 })();
2230
2231 if ( document.getElementsByClassName && document.documentElement.getElementsByClassName ) (function(){
2232         var div = document.createElement("div");
2233         div.innerHTML = "<div class='test e'></div><div class='test'></div>";
2234
2235         // Opera can't find a second classname (in 9.6)
2236         if ( div.getElementsByClassName("e").length === 0 )
2237                 return;
2238
2239         // Safari caches class attributes, doesn't catch changes (in 3.2)
2240         div.lastChild.className = "e";
2241
2242         if ( div.getElementsByClassName("e").length === 1 )
2243                 return;
2244
2245         Expr.order.splice(1, 0, "CLASS");
2246         Expr.find.CLASS = function(match, context, isXML) {
2247                 if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
2248                         return context.getElementsByClassName(match[1]);
2249                 }
2250         };
2251 })();
2252
2253 function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
2254         var sibDir = dir == "previousSibling" && !isXML;
2255         for ( var i = 0, l = checkSet.length; i < l; i++ ) {
2256                 var elem = checkSet[i];
2257                 if ( elem ) {
2258                         if ( sibDir && elem.nodeType === 1 ){
2259                                 elem.sizcache = doneName;
2260                                 elem.sizset = i;
2261                         }
2262                         elem = elem[dir];
2263                         var match = false;
2264
2265                         while ( elem ) {
2266                                 if ( elem.sizcache === doneName ) {
2267                                         match = checkSet[elem.sizset];
2268                                         break;
2269                                 }
2270
2271                                 if ( elem.nodeType === 1 && !isXML ){
2272                                         elem.sizcache = doneName;
2273                                         elem.sizset = i;
2274                                 }
2275
2276                                 if ( elem.nodeName === cur ) {
2277                                         match = elem;
2278                                         break;
2279                                 }
2280
2281                                 elem = elem[dir];
2282                         }
2283
2284                         checkSet[i] = match;
2285                 }
2286         }
2287 }
2288
2289 function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
2290         var sibDir = dir == "previousSibling" && !isXML;
2291         for ( var i = 0, l = checkSet.length; i < l; i++ ) {
2292                 var elem = checkSet[i];
2293                 if ( elem ) {
2294                         if ( sibDir && elem.nodeType === 1 ) {
2295                                 elem.sizcache = doneName;
2296                                 elem.sizset = i;
2297                         }
2298                         elem = elem[dir];
2299                         var match = false;
2300
2301                         while ( elem ) {
2302                                 if ( elem.sizcache === doneName ) {
2303                                         match = checkSet[elem.sizset];
2304                                         break;
2305                                 }
2306
2307                                 if ( elem.nodeType === 1 ) {
2308                                         if ( !isXML ) {
2309                                                 elem.sizcache = doneName;
2310                                                 elem.sizset = i;
2311                                         }
2312                                         if ( typeof cur !== "string" ) {
2313                                                 if ( elem === cur ) {
2314                                                         match = true;
2315                                                         break;
2316                                                 }
2317
2318                                         } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
2319                                                 match = elem;
2320                                                 break;
2321                                         }
2322                                 }
2323
2324                                 elem = elem[dir];
2325                         }
2326
2327                         checkSet[i] = match;
2328                 }
2329         }
2330 }
2331
2332 var contains = document.compareDocumentPosition ?  function(a, b){
2333         return a.compareDocumentPosition(b) & 16;
2334 } : function(a, b){
2335         return a !== b && (a.contains ? a.contains(b) : true);
2336 };
2337
2338 var isXML = function(elem){
2339         return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" ||
2340                 !!elem.ownerDocument && isXML( elem.ownerDocument );
2341 };
2342
2343 var posProcess = function(selector, context){
2344         var tmpSet = [], later = "", match,
2345                 root = context.nodeType ? [context] : context;
2346
2347         // Position selectors must be done after the filter
2348         // And so must :not(positional) so we move all PSEUDOs to the end
2349         while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
2350                 later += match[0];
2351                 selector = selector.replace( Expr.match.PSEUDO, "" );
2352         }
2353
2354         selector = Expr.relative[selector] ? selector + "*" : selector;
2355
2356         for ( var i = 0, l = root.length; i < l; i++ ) {
2357                 Sizzle( selector, root[i], tmpSet );
2358         }
2359
2360         return Sizzle.filter( later, tmpSet );
2361 };
2362
2363 // EXPOSE
2364 jQuery.find = Sizzle;
2365 jQuery.filter = Sizzle.filter;
2366 jQuery.expr = Sizzle.selectors;
2367 jQuery.expr[":"] = jQuery.expr.filters;
2368
2369 Sizzle.selectors.filters.hidden = function(elem){
2370         return elem.offsetWidth === 0 || elem.offsetHeight === 0;
2371 };
2372
2373 Sizzle.selectors.filters.visible = function(elem){
2374         return elem.offsetWidth > 0 || elem.offsetHeight > 0;
2375 };
2376
2377 Sizzle.selectors.filters.animated = function(elem){
2378         return jQuery.grep(jQuery.timers, function(fn){
2379                 return elem === fn.elem;
2380         }).length;
2381 };
2382
2383 jQuery.multiFilter = function( expr, elems, not ) {
2384         if ( not ) {
2385                 expr = ":not(" + expr + ")";
2386         }
2387
2388         return Sizzle.matches(expr, elems);
2389 };
2390
2391 jQuery.dir = function( elem, dir ){
2392         var matched = [], cur = elem[dir];
2393         while ( cur && cur != document ) {
2394                 if ( cur.nodeType == 1 )
2395                         matched.push( cur );
2396                 cur = cur[dir];
2397         }
2398         return matched;
2399 };
2400
2401 jQuery.nth = function(cur, result, dir, elem){
2402         result = result || 1;
2403         var num = 0;
2404
2405         for ( ; cur; cur = cur[dir] )
2406                 if ( cur.nodeType == 1 && ++num == result )
2407                         break;
2408
2409         return cur;
2410 };
2411
2412 jQuery.sibling = function(n, elem){
2413         var r = [];
2414
2415         for ( ; n; n = n.nextSibling ) {
2416                 if ( n.nodeType == 1 && n != elem )
2417                         r.push( n );
2418         }
2419
2420         return r;
2421 };
2422
2423 return;
2424
2425 window.Sizzle = Sizzle;
2426
2427 })();
2428 /*
2429  * A number of helper functions used for managing events.
2430  * Many of the ideas behind this code originated from
2431  * Dean Edwards' addEvent library.
2432  */
2433 jQuery.event = {
2434
2435         // Bind an event to an element
2436         // Original by Dean Edwards
2437         add: function(elem, types, handler, data) {
2438                 if ( elem.nodeType == 3 || elem.nodeType == 8 )
2439                         return;
2440
2441                 // For whatever reason, IE has trouble passing the window object
2442                 // around, causing it to be cloned in the process
2443                 if ( elem.setInterval && elem != window )
2444                         elem = window;
2445
2446                 // Make sure that the function being executed has a unique ID
2447                 if ( !handler.guid )
2448                         handler.guid = this.guid++;
2449
2450                 // if data is passed, bind to handler
2451                 if ( data !== undefined ) {
2452                         // Create temporary function pointer to original handler
2453                         var fn = handler;
2454
2455                         // Create unique handler function, wrapped around original handler
2456                         handler = this.proxy( fn );
2457
2458                         // Store data in unique handler
2459                         handler.data = data;
2460                 }
2461
2462                 // Init the element's event structure
2463                 var events = jQuery.data(elem, "events") || jQuery.data(elem, "events", {}),
2464                         handle = jQuery.data(elem, "handle") || jQuery.data(elem, "handle", function(){
2465                                 // Handle the second event of a trigger and when
2466                                 // an event is called after a page has unloaded
2467                                 return typeof jQuery !== "undefined" && !jQuery.event.triggered ?
2468                                         jQuery.event.handle.apply(arguments.callee.elem, arguments) :
2469                                         undefined;
2470                         });
2471                 // Add elem as a property of the handle function
2472                 // This is to prevent a memory leak with non-native
2473                 // event in IE.
2474                 handle.elem = elem;
2475
2476                 // Handle multiple events separated by a space
2477                 // jQuery(...).bind("mouseover mouseout", fn);
2478                 jQuery.each(types.split(/\s+/), function(index, type) {
2479                         // Namespaced event handlers
2480                         var namespaces = type.split(".");
2481                         type = namespaces.shift();
2482                         handler.type = namespaces.slice().sort().join(".");
2483
2484                         // Get the current list of functions bound to this event
2485                         var handlers = events[type];
2486                         
2487                         if ( jQuery.event.specialAll[type] )
2488                                 jQuery.event.specialAll[type].setup.call(elem, data, namespaces);
2489
2490                         // Init the event handler queue
2491                         if (!handlers) {
2492                                 handlers = events[type] = {};
2493
2494                                 // Check for a special event handler
2495                                 // Only use addEventListener/attachEvent if the special
2496                                 // events handler returns false
2497                                 if ( !jQuery.event.special[type] || jQuery.event.special[type].setup.call(elem, data, namespaces) === false ) {
2498                                         // Bind the global event handler to the element
2499                                         if (elem.addEventListener)
2500                                                 elem.addEventListener(type, handle, false);
2501                                         else if (elem.attachEvent)
2502                                                 elem.attachEvent("on" + type, handle);
2503                                 }
2504                         }
2505
2506                         // Add the function to the element's handler list
2507                         handlers[handler.guid] = handler;
2508
2509                         // Keep track of which events have been used, for global triggering
2510                         jQuery.event.global[type] = true;
2511                 });
2512
2513                 // Nullify elem to prevent memory leaks in IE
2514                 elem = null;
2515         },
2516
2517         guid: 1,
2518         global: {},
2519
2520         // Detach an event or set of events from an element
2521         remove: function(elem, types, handler) {
2522                 // don't do events on text and comment nodes
2523                 if ( elem.nodeType == 3 || elem.nodeType == 8 )
2524                         return;
2525
2526                 var events = jQuery.data(elem, "events"), ret, index;
2527
2528                 if ( events ) {
2529                         // Unbind all events for the element
2530                         if ( types === undefined || (typeof types === "string" && types.charAt(0) == ".") )
2531                                 for ( var type in events )
2532                                         this.remove( elem, type + (types || "") );
2533                         else {
2534                                 // types is actually an event object here
2535                                 if ( types.type ) {
2536                                         handler = types.handler;
2537                                         types = types.type;
2538                                 }
2539
2540                                 // Handle multiple events seperated by a space
2541                                 // jQuery(...).unbind("mouseover mouseout", fn);
2542                                 jQuery.each(types.split(/\s+/), function(index, type){
2543                                         // Namespaced event handlers
2544                                         var namespaces = type.split(".");
2545                                         type = namespaces.shift();
2546                                         var namespace = RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)");
2547
2548                                         if ( events[type] ) {
2549                                                 // remove the given handler for the given type
2550                                                 if ( handler )
2551                                                         delete events[type][handler.guid];
2552
2553                                                 // remove all handlers for the given type
2554                                                 else
2555                                                         for ( var handle in events[type] )
2556                                                                 // Handle the removal of namespaced events
2557                                                                 if ( namespace.test(events[type][handle].type) )
2558                                                                         delete events[type][handle];
2559                                                                         
2560                                                 if ( jQuery.event.specialAll[type] )
2561                                                         jQuery.event.specialAll[type].teardown.call(elem, namespaces);
2562
2563                                                 // remove generic event handler if no more handlers exist
2564                                                 for ( ret in events[type] ) break;
2565                                                 if ( !ret ) {
2566                                                         if ( !jQuery.event.special[type] || jQuery.event.special[type].teardown.call(elem, namespaces) === false ) {
2567                                                                 if (elem.removeEventListener)
2568                                                                         elem.removeEventListener(type, jQuery.data(elem, "handle"), false);
2569                                                                 else if (elem.detachEvent)
2570                                                                         elem.detachEvent("on" + type, jQuery.data(elem, "handle"));
2571                                                         }
2572                                                         ret = null;
2573                                                         delete events[type];
2574                                                 }
2575                                         }
2576                                 });
2577                         }
2578
2579                         // Remove the expando if it's no longer used
2580                         for ( ret in events ) break;
2581                         if ( !ret ) {
2582                                 var handle = jQuery.data( elem, "handle" );
2583                                 if ( handle ) handle.elem = null;
2584                                 jQuery.removeData( elem, "events" );
2585                                 jQuery.removeData( elem, "handle" );
2586                         }
2587                 }
2588         },
2589
2590         // bubbling is internal
2591         trigger: function( event, data, elem, bubbling ) {
2592                 // Event object or event type
2593                 var type = event.type || event;
2594
2595                 if( !bubbling ){
2596                         event = typeof event === "object" ?
2597                                 // jQuery.Event object
2598                                 event[expando] ? event :
2599                                 // Object literal
2600                                 jQuery.extend( jQuery.Event(type), event ) :
2601                                 // Just the event type (string)
2602                                 jQuery.Event(type);
2603
2604                         if ( type.indexOf("!") >= 0 ) {
2605                                 event.type = type = type.slice(0, -1);
2606                                 event.exclusive = true;
2607                         }
2608
2609                         // Handle a global trigger
2610                         if ( !elem ) {
2611                                 // Don't bubble custom events when global (to avoid too much overhead)
2612                                 event.stopPropagation();
2613                                 // Only trigger if we've ever bound an event for it
2614                                 if ( this.global[type] )
2615                                         jQuery.each( jQuery.cache, function(){
2616                                                 if ( this.events && this.events[type] )
2617                                                         jQuery.event.trigger( event, data, this.handle.elem );
2618                                         });
2619                         }
2620
2621                         // Handle triggering a single element
2622
2623                         // don't do events on text and comment nodes
2624                         if ( !elem || elem.nodeType == 3 || elem.nodeType == 8 )
2625                                 return undefined;
2626                         
2627                         // Clean up in case it is reused
2628                         event.result = undefined;
2629                         event.target = elem;
2630                         
2631                         // Clone the incoming data, if any
2632                         data = jQuery.makeArray(data);
2633                         data.unshift( event );
2634                 }
2635
2636                 event.currentTarget = elem;
2637
2638                 // Trigger the event, it is assumed that "handle" is a function
2639                 var handle = jQuery.data(elem, "handle");
2640                 if ( handle )
2641                         handle.apply( elem, data );
2642
2643                 // Handle triggering native .onfoo handlers (and on links since we don't call .click() for links)
2644                 if ( (!elem[type] || (jQuery.nodeName(elem, 'a') && type == "click")) && elem["on"+type] && elem["on"+type].apply( elem, data ) === false )
2645                         event.result = false;
2646
2647                 // Trigger the native events (except for clicks on links)
2648                 if ( !bubbling && elem[type] && !event.isDefaultPrevented() && !(jQuery.nodeName(elem, 'a') && type == "click") ) {
2649                         this.triggered = true;
2650                         try {
2651                                 elem[ type ]();
2652                         // prevent IE from throwing an error for some hidden elements
2653                         } catch (e) {}
2654                 }
2655
2656                 this.triggered = false;
2657
2658                 if ( !event.isPropagationStopped() ) {
2659                         var parent = elem.parentNode || elem.ownerDocument;
2660                         if ( parent )
2661                                 jQuery.event.trigger(event, data, parent, true);
2662                 }
2663         },
2664
2665         handle: function(event) {
2666                 // returned undefined or false
2667                 var all, handlers;
2668
2669                 event = arguments[0] = jQuery.event.fix( event || window.event );
2670                 event.currentTarget = this;
2671                 
2672                 // Namespaced event handlers
2673                 var namespaces = event.type.split(".");
2674                 event.type = namespaces.shift();
2675
2676                 // Cache this now, all = true means, any handler
2677                 all = !namespaces.length && !event.exclusive;
2678                 
2679                 var namespace = RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)");
2680
2681                 handlers = ( jQuery.data(this, "events") || {} )[event.type];
2682
2683                 for ( var j in handlers ) {
2684                         var handler = handlers[j];
2685
2686                         // Filter the functions by class
2687                         if ( all || namespace.test(handler.type) ) {
2688                                 // Pass in a reference to the handler function itself
2689                                 // So that we can later remove it
2690                                 event.handler = handler;
2691                                 event.data = handler.data;
2692
2693                                 var ret = handler.apply(this, arguments);
2694
2695                                 if( ret !== undefined ){
2696                                         event.result = ret;
2697                                         if ( ret === false ) {
2698                                                 event.preventDefault();
2699                                                 event.stopPropagation();
2700                                         }
2701                                 }
2702
2703                                 if( event.isImmediatePropagationStopped() )
2704                                         break;
2705
2706                         }
2707                 }
2708         },
2709
2710         props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
2711
2712         fix: function(event) {
2713                 if ( event[expando] )
2714                         return event;
2715
2716                 // store a copy of the original event object
2717                 // and "clone" to set read-only properties
2718                 var originalEvent = event;
2719                 event = jQuery.Event( originalEvent );
2720
2721                 for ( var i = this.props.length, prop; i; ){
2722                         prop = this.props[ --i ];
2723                         event[ prop ] = originalEvent[ prop ];
2724                 }
2725
2726                 // Fix target property, if necessary
2727                 if ( !event.target )
2728                         event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
2729
2730                 // check if target is a textnode (safari)
2731                 if ( event.target.nodeType == 3 )
2732                         event.target = event.target.parentNode;
2733
2734                 // Add relatedTarget, if necessary
2735                 if ( !event.relatedTarget && event.fromElement )
2736                         event.relatedTarget = event.fromElement == event.target ? event.toElement : event.fromElement;
2737
2738                 // Calculate pageX/Y if missing and clientX/Y available
2739                 if ( event.pageX == null && event.clientX != null ) {
2740                         var doc = document.documentElement, body = document.body;
2741                         event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc.clientLeft || 0);
2742                         event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc.clientTop || 0);
2743                 }
2744
2745                 // Add which for key events
2746                 if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) )
2747                         event.which = event.charCode || event.keyCode;
2748
2749                 // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
2750                 if ( !event.metaKey && event.ctrlKey )
2751                         event.metaKey = event.ctrlKey;
2752
2753                 // Add which for click: 1 == left; 2 == middle; 3 == right
2754                 // Note: button is not normalized, so don't use it
2755                 if ( !event.which && event.button )
2756                         event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
2757
2758                 return event;
2759         },
2760
2761         proxy: function( fn, proxy ){
2762                 proxy = proxy || function(){ return fn.apply(this, arguments); };
2763                 // Set the guid of unique handler to the same of original handler, so it can be removed
2764                 proxy.guid = fn.guid = fn.guid || proxy.guid || this.guid++;
2765                 // So proxy can be declared as an argument
2766                 return proxy;
2767         },
2768
2769         special: {
2770                 ready: {
2771                         // Make sure the ready event is setup
2772                         setup: bindReady,
2773                         teardown: function() {}
2774                 }
2775         },
2776         
2777         specialAll: {
2778                 live: {
2779                         setup: function( selector, namespaces ){
2780                                 jQuery.event.add( this, namespaces[0], liveHandler );
2781                         },
2782                         teardown:  function( namespaces ){
2783                                 if ( namespaces.length ) {
2784                                         var remove = 0, name = RegExp("(^|\\.)" + namespaces[0] + "(\\.|$)");
2785                                         
2786                                         jQuery.each( (jQuery.data(this, "events").live || {}), function(){
2787                                                 if ( name.test(this.type) )
2788                                                         remove++;
2789                                         });
2790                                         
2791                                         if ( remove < 1 )
2792                                                 jQuery.event.remove( this, namespaces[0], liveHandler );
2793                                 }
2794                         }
2795                 }
2796         }
2797 };
2798
2799 jQuery.Event = function( src ){
2800         // Allow instantiation without the 'new' keyword
2801         if( !this.preventDefault )
2802                 return new jQuery.Event(src);
2803         
2804         // Event object
2805         if( src && src.type ){
2806                 this.originalEvent = src;
2807                 this.type = src.type;
2808         // Event type
2809         }else
2810                 this.type = src;
2811
2812         // timeStamp is buggy for some events on Firefox(#3843)
2813         // So we won't rely on the native value
2814         this.timeStamp = now();
2815         
2816         // Mark it as fixed
2817         this[expando] = true;
2818 };
2819
2820 function returnFalse(){
2821         return false;
2822 }
2823 function returnTrue(){
2824         return true;
2825 }
2826
2827 // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
2828 // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
2829 jQuery.Event.prototype = {
2830         preventDefault: function() {
2831                 this.isDefaultPrevented = returnTrue;
2832
2833                 var e = this.originalEvent;
2834                 if( !e )
2835                         return;
2836                 // if preventDefault exists run it on the original event
2837                 if (e.preventDefault)
2838                         e.preventDefault();
2839                 // otherwise set the returnValue property of the original event to false (IE)
2840                 e.returnValue = false;
2841         },
2842         stopPropagation: function() {
2843                 this.isPropagationStopped = returnTrue;
2844
2845                 var e = this.originalEvent;
2846                 if( !e )
2847                         return;
2848                 // if stopPropagation exists run it on the original event
2849                 if (e.stopPropagation)
2850                         e.stopPropagation();
2851                 // otherwise set the cancelBubble property of the original event to true (IE)
2852                 e.cancelBubble = true;
2853         },
2854         stopImmediatePropagation:function(){
2855                 this.isImmediatePropagationStopped = returnTrue;
2856                 this.stopPropagation();
2857         },
2858         isDefaultPrevented: returnFalse,
2859         isPropagationStopped: returnFalse,
2860         isImmediatePropagationStopped: returnFalse
2861 };
2862 // Checks if an event happened on an element within another element
2863 // Used in jQuery.event.special.mouseenter and mouseleave handlers
2864 var withinElement = function(event) {
2865         // Check if mouse(over|out) are still within the same parent element
2866         var parent = event.relatedTarget;
2867         // Traverse up the tree
2868         while ( parent && parent != this )
2869                 try { parent = parent.parentNode; }
2870                 catch(e) { parent = this; }
2871         
2872         if( parent != this ){
2873                 // set the correct event type
2874                 event.type = event.data;
2875                 // handle event if we actually just moused on to a non sub-element
2876                 jQuery.event.handle.apply( this, arguments );
2877         }
2878 };
2879         
2880 jQuery.each({ 
2881         mouseover: 'mouseenter', 
2882         mouseout: 'mouseleave'
2883 }, function( orig, fix ){
2884         jQuery.event.special[ fix ] = {
2885                 setup: function(){
2886                         jQuery.event.add( this, orig, withinElement, fix );
2887                 },
2888                 teardown: function(){
2889                         jQuery.event.remove( this, orig, withinElement );
2890                 }
2891         };                         
2892 });
2893
2894 jQuery.fn.extend({
2895         bind: function( type, data, fn ) {
2896                 return type == "unload" ? this.one(type, data, fn) : this.each(function(){
2897                         jQuery.event.add( this, type, fn || data, fn && data );
2898                 });
2899         },
2900
2901         one: function( type, data, fn ) {
2902                 var one = jQuery.event.proxy( fn || data, function(event) {
2903                         jQuery(this).unbind(event, one);
2904                         return (fn || data).apply( this, arguments );
2905                 });
2906                 return this.each(function(){
2907                         jQuery.event.add( this, type, one, fn && data);
2908                 });
2909         },
2910
2911         unbind: function( type, fn ) {
2912                 return this.each(function(){
2913                         jQuery.event.remove( this, type, fn );
2914                 });
2915         },
2916
2917         trigger: function( type, data ) {
2918                 return this.each(function(){
2919                         jQuery.event.trigger( type, data, this );
2920                 });
2921         },
2922
2923         triggerHandler: function( type, data ) {
2924                 if( this[0] ){
2925                         var event = jQuery.Event(type);
2926                         event.preventDefault();
2927                         event.stopPropagation();
2928                         jQuery.event.trigger( event, data, this[0] );
2929                         return event.result;
2930                 }               
2931         },
2932
2933         toggle: function( fn ) {
2934                 // Save reference to arguments for access in closure
2935                 var args = arguments, i = 1;
2936
2937                 // link all the functions, so any of them can unbind this click handler
2938                 while( i < args.length )
2939                         jQuery.event.proxy( fn, args[i++] );
2940
2941                 return this.click( jQuery.event.proxy( fn, function(event) {
2942                         // Figure out which function to execute
2943                         this.lastToggle = ( this.lastToggle || 0 ) % i;
2944
2945                         // Make sure that clicks stop
2946                         event.preventDefault();
2947
2948                         // and execute the function
2949                         return args[ this.lastToggle++ ].apply( this, arguments ) || false;
2950                 }));
2951         },
2952
2953         hover: function(fnOver, fnOut) {
2954                 return this.mouseenter(fnOver).mouseleave(fnOut);
2955         },
2956
2957         ready: function(fn) {
2958                 // Attach the listeners
2959                 bindReady();
2960
2961                 // If the DOM is already ready
2962                 if ( jQuery.isReady )
2963                         // Execute the function immediately
2964                         fn.call( document, jQuery );
2965
2966                 // Otherwise, remember the function for later
2967                 else
2968                         // Add the function to the wait list
2969                         jQuery.readyList.push( fn );
2970
2971                 return this;
2972         },
2973         
2974         live: function( type, fn ){
2975                 var proxy = jQuery.event.proxy( fn );
2976                 proxy.guid += this.selector + type;
2977
2978                 jQuery(document).bind( liveConvert(type, this.selector), this.selector, proxy );
2979
2980                 return this;
2981         },
2982         
2983         die: function( type, fn ){
2984                 jQuery(document).unbind( liveConvert(type, this.selector), fn ? { guid: fn.guid + this.selector + type } : null );
2985                 return this;
2986         }
2987 });
2988
2989 function liveHandler( event ){
2990         var check = RegExp("(^|\\.)" + event.type + "(\\.|$)"),
2991                 stop = true,
2992                 elems = [];
2993
2994         jQuery.each(jQuery.data(this, "events").live || [], function(i, fn){
2995                 if ( check.test(fn.type) ) {
2996                         var elem = jQuery(event.target).closest(fn.data)[0];
2997                         if ( elem )
2998                                 elems.push({ elem: elem, fn: fn });
2999                 }
3000         });
3001
3002         elems.sort(function(a,b) {
3003                 return jQuery.data(a.elem, "closest") - jQuery.data(b.elem, "closest");
3004         });
3005         
3006         jQuery.each(elems, function(){
3007                 if ( this.fn.call(this.elem, event, this.fn.data) === false )
3008                         return (stop = false);
3009         });
3010
3011         return stop;
3012 }
3013
3014 function liveConvert(type, selector){
3015         return ["live", type, selector.replace(/\./g, "`").replace(/ /g, "|")].join(".");
3016 }
3017
3018 jQuery.extend({
3019         isReady: false,
3020         readyList: [],
3021         // Handle when the DOM is ready
3022         ready: function() {
3023                 // Make sure that the DOM is not already loaded
3024                 if ( !jQuery.isReady ) {
3025                         // Remember that the DOM is ready
3026                         jQuery.isReady = true;
3027
3028                         // If there are functions bound, to execute
3029                         if ( jQuery.readyList ) {
3030                                 // Execute all of them
3031                                 jQuery.each( jQuery.readyList, function(){
3032                                         this.call( document, jQuery );
3033                                 });
3034
3035                                 // Reset the list of functions
3036                                 jQuery.readyList = null;
3037                         }
3038
3039                         // Trigger any bound ready events
3040                         jQuery(document).triggerHandler("ready");
3041                 }
3042         }
3043 });
3044
3045 var readyBound = false;
3046
3047 function bindReady(){
3048         if ( readyBound ) return;
3049         readyBound = true;
3050
3051         // Mozilla, Opera and webkit nightlies currently support this event
3052         if ( document.addEventListener ) {
3053                 // Use the handy event callback
3054                 document.addEventListener( "DOMContentLoaded", function(){
3055                         document.removeEventListener( "DOMContentLoaded", arguments.callee, false );
3056                         jQuery.ready();
3057                 }, false );
3058
3059         // If IE event model is used
3060         } else if ( document.attachEvent ) {
3061                 // ensure firing before onload,
3062                 // maybe late but safe also for iframes
3063                 document.attachEvent("onreadystatechange", function(){
3064                         if ( document.readyState === "complete" ) {
3065                                 document.detachEvent( "onreadystatechange", arguments.callee );
3066                                 jQuery.ready();
3067                         }
3068                 });
3069
3070                 // If IE and not an iframe
3071                 // continually check to see if the document is ready
3072                 if ( document.documentElement.doScroll && window == window.top ) (function(){
3073                         if ( jQuery.isReady ) return;
3074
3075                         try {
3076                                 // If IE is used, use the trick by Diego Perini
3077                                 // http://javascript.nwbox.com/IEContentLoaded/
3078                                 document.documentElement.doScroll("left");
3079                         } catch( error ) {
3080                                 setTimeout( arguments.callee, 0 );
3081                                 return;
3082                         }
3083
3084                         // and execute any waiting functions
3085                         jQuery.ready();
3086                 })();
3087         }
3088
3089         // A fallback to window.onload, that will always work
3090         jQuery.event.add( window, "load", jQuery.ready );
3091 }
3092
3093 jQuery.each( ("blur,focus,load,resize,scroll,unload,click,dblclick," +
3094         "mousedown,mouseup,mousemove,mouseover,mouseout,mouseenter,mouseleave," +
3095         "change,select,submit,keydown,keypress,keyup,error").split(","), function(i, name){
3096
3097         // Handle event binding
3098         jQuery.fn[name] = function(fn){
3099                 return fn ? this.bind(name, fn) : this.trigger(name);
3100         };
3101 });
3102
3103 // Prevent memory leaks in IE
3104 // And prevent errors on refresh with events like mouseover in other browsers
3105 // Window isn't included so as not to unbind existing unload events
3106 jQuery( window ).bind( 'unload', function(){ 
3107         for ( var id in jQuery.cache )
3108                 // Skip the window
3109                 if ( id != 1 && jQuery.cache[ id ].handle )
3110                         jQuery.event.remove( jQuery.cache[ id ].handle.elem );
3111 }); 
3112 (function(){
3113
3114         jQuery.support = {};
3115
3116         var root = document.documentElement,
3117                 script = document.createElement("script"),
3118                 div = document.createElement("div"),
3119                 id = "script" + (new Date).getTime();
3120
3121         div.style.display = "none";
3122         div.innerHTML = '   <link/><table></table><a href="/a" style="color:red;float:left;opacity:.5;">a</a><select><option>text</option></select><object><param/></object>';
3123
3124         var all = div.getElementsByTagName("*"),
3125                 a = div.getElementsByTagName("a")[0];
3126
3127         // Can't get basic test support
3128         if ( !all || !all.length || !a ) {
3129                 return;
3130         }
3131
3132         jQuery.support = {
3133                 // IE strips leading whitespace when .innerHTML is used
3134                 leadingWhitespace: div.firstChild.nodeType == 3,
3135                 
3136                 // Make sure that tbody elements aren't automatically inserted
3137                 // IE will insert them into empty tables
3138                 tbody: !div.getElementsByTagName("tbody").length,
3139                 
3140                 // Make sure that you can get all elements in an <object> element
3141                 // IE 7 always returns no results
3142                 objectAll: !!div.getElementsByTagName("object")[0]
3143                         .getElementsByTagName("*").length,
3144                 
3145                 // Make sure that link elements get serialized correctly by innerHTML
3146                 // This requires a wrapper element in IE
3147                 htmlSerialize: !!div.getElementsByTagName("link").length,
3148                 
3149                 // Get the style information from getAttribute
3150                 // (IE uses .cssText insted)
3151                 style: /red/.test( a.getAttribute("style") ),
3152                 
3153                 // Make sure that URLs aren't manipulated
3154                 // (IE normalizes it by default)
3155                 hrefNormalized: a.getAttribute("href") === "/a",
3156                 
3157                 // Make sure that element opacity exists
3158                 // (IE uses filter instead)
3159                 opacity: a.style.opacity === "0.5",
3160                 
3161                 // Verify style float existence
3162                 // (IE uses styleFloat instead of cssFloat)
3163                 cssFloat: !!a.style.cssFloat,
3164
3165                 // Will be defined later
3166                 scriptEval: false,
3167                 noCloneEvent: true,
3168                 boxModel: null
3169         };
3170         
3171         script.type = "text/javascript";
3172         try {
3173                 script.appendChild( document.createTextNode( "window." + id + "=1;" ) );
3174         } catch(e){}
3175
3176         root.insertBefore( script, root.firstChild );
3177         
3178         // Make sure that the execution of code works by injecting a script
3179         // tag with appendChild/createTextNode
3180         // (IE doesn't support this, fails, and uses .text instead)
3181         if ( window[ id ] ) {
3182                 jQuery.support.scriptEval = true;
3183                 delete window[ id ];
3184         }
3185
3186         root.removeChild( script );
3187
3188         if ( div.attachEvent && div.fireEvent ) {
3189                 div.attachEvent("onclick", function(){
3190                         // Cloning a node shouldn't copy over any
3191                         // bound event handlers (IE does this)
3192                         jQuery.support.noCloneEvent = false;
3193                         div.detachEvent("onclick", arguments.callee);
3194                 });
3195                 div.cloneNode(true).fireEvent("onclick");
3196         }
3197
3198         // Figure out if the W3C box model works as expected
3199         // document.body must exist before we can do this
3200         jQuery(function(){
3201                 var div = document.createElement("div");
3202                 div.style.width = div.style.paddingLeft = "1px";
3203
3204                 document.body.appendChild( div );
3205                 jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2;
3206                 document.body.removeChild( div ).style.display = 'none';
3207         });
3208 })();
3209
3210 var styleFloat = jQuery.support.cssFloat ? "cssFloat" : "styleFloat";
3211
3212 jQuery.props = {
3213         "for": "htmlFor",
3214         "class": "className",
3215         "float": styleFloat,
3216         cssFloat: styleFloat,
3217         styleFloat: styleFloat,
3218         readonly: "readOnly",
3219         maxlength: "maxLength",
3220         cellspacing: "cellSpacing",
3221         rowspan: "rowSpan",
3222         tabindex: "tabIndex"
3223 };
3224 jQuery.fn.extend({
3225         // Keep a copy of the old load
3226         _load: jQuery.fn.load,
3227
3228         load: function( url, params, callback ) {
3229                 if ( typeof url !== "string" )
3230                         return this._load( url );
3231
3232                 var off = url.indexOf(" ");
3233                 if ( off >= 0 ) {
3234                         var selector = url.slice(off, url.length);
3235                         url = url.slice(0, off);
3236                 }
3237
3238                 // Default to a GET request
3239                 var type = "GET";
3240
3241                 // If the second parameter was provided
3242                 if ( params )
3243                         // If it's a function
3244                         if ( jQuery.isFunction( params ) ) {
3245                                 // We assume that it's the callback
3246                                 callback = params;
3247                                 params = null;
3248
3249                         // Otherwise, build a param string
3250                         } else if( typeof params === "object" ) {
3251                                 params = jQuery.param( params );
3252                                 type = "POST";
3253                         }
3254
3255                 var self = this;
3256
3257                 // Request the remote document
3258                 jQuery.ajax({
3259                         url: url,
3260                         type: type,
3261                         dataType: "html",
3262                         data: params,
3263                         complete: function(res, status){
3264                                 // If successful, inject the HTML into all the matched elements
3265                                 if ( status == "success" || status == "notmodified" )
3266                                         // See if a selector was specified
3267                                         self.html( selector ?
3268                                                 // Create a dummy div to hold the results
3269                                                 jQuery("<div/>")
3270                                                         // inject the contents of the document in, removing the scripts
3271                                                         // to avoid any 'Permission Denied' errors in IE
3272                                                         .append(res.responseText.replace(/<script(.|\s)*?\/script>/g, ""))
3273
3274                                                         // Locate the specified elements
3275                                                         .find(selector) :
3276
3277                                                 // If not, just inject the full result
3278                                                 res.responseText );
3279
3280                                 if( callback )
3281                                         self.each( callback, [res.responseText, status, res] );
3282                         }
3283                 });
3284                 return this;
3285         },
3286
3287         serialize: function() {
3288                 return jQuery.param(this.serializeArray());
3289         },
3290         serializeArray: function() {
3291                 return this.map(function(){
3292                         return this.elements ? jQuery.makeArray(this.elements) : this;
3293                 })
3294                 .filter(function(){
3295                         return this.name && !this.disabled &&
3296                                 (this.checked || /select|textarea/i.test(this.nodeName) ||
3297                                         /text|hidden|password|search/i.test(this.type));
3298                 })
3299                 .map(function(i, elem){
3300                         var val = jQuery(this).val();
3301                         return val == null ? null :
3302                                 jQuery.isArray(val) ?
3303                                         jQuery.map( val, function(val, i){
3304                                                 return {name: elem.name, value: val};
3305                                         }) :
3306                                         {name: elem.name, value: val};
3307                 }).get();
3308         }
3309 });
3310
3311 // Attach a bunch of functions for handling common AJAX events
3312 jQuery.each( "ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","), function(i,o){
3313         jQuery.fn[o] = function(f){
3314                 return this.bind(o, f);
3315         };
3316 });
3317
3318 var jsc = now();
3319
3320 jQuery.extend({
3321   
3322         get: function( url, data, callback, type ) {
3323                 // shift arguments if data argument was ommited
3324                 if ( jQuery.isFunction( data ) ) {
3325                         callback = data;
3326                         data = null;
3327                 }
3328
3329                 return jQuery.ajax({
3330                         type: "GET",
3331                         url: url,
3332                         data: data,
3333                         success: callback,
3334                         dataType: type
3335                 });
3336         },
3337
3338         getScript: function( url, callback ) {
3339                 return jQuery.get(url, null, callback, "script");
3340         },
3341
3342         getJSON: function( url, data, callback ) {
3343                 return jQuery.get(url, data, callback, "json");
3344         },
3345
3346         post: function( url, data, callback, type ) {
3347                 if ( jQuery.isFunction( data ) ) {
3348                         callback = data;
3349                         data = {};
3350                 }
3351
3352                 return jQuery.ajax({
3353                         type: "POST",
3354                         url: url,
3355                         data: data,
3356                         success: callback,
3357                         dataType: type
3358                 });
3359         },
3360
3361         ajaxSetup: function( settings ) {
3362                 jQuery.extend( jQuery.ajaxSettings, settings );
3363         },
3364
3365         ajaxSettings: {
3366                 url: location.href,
3367                 global: true,
3368                 type: "GET",
3369                 contentType: "application/x-www-form-urlencoded",
3370                 processData: true,
3371                 async: true,
3372                 /*
3373                 timeout: 0,
3374                 data: null,
3375                 username: null,
3376                 password: null,
3377                 */
3378                 // Create the request object; Microsoft failed to properly
3379                 // implement the XMLHttpRequest in IE7, so we use the ActiveXObject when it is available
3380                 // This function can be overriden by calling jQuery.ajaxSetup
3381                 xhr:function(){
3382                         return window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
3383                 },
3384                 accepts: {
3385                         xml: "application/xml, text/xml",
3386                         html: "text/html",
3387                         script: "text/javascript, application/javascript",
3388                         json: "application/json, text/javascript",
3389                         text: "text/plain",
3390                         _default: "*/*"
3391                 }
3392         },
3393
3394         // Last-Modified header cache for next request
3395         lastModified: {},
3396
3397         ajax: function( s ) {
3398                 // Extend the settings, but re-extend 's' so that it can be
3399                 // checked again later (in the test suite, specifically)
3400                 s = jQuery.extend(true, s, jQuery.extend(true, {}, jQuery.ajaxSettings, s));
3401
3402                 var jsonp, jsre = /=\?(&|$)/g, status, data,
3403                         type = s.type.toUpperCase();
3404
3405                 // convert data if not already a string
3406                 if ( s.data && s.processData && typeof s.data !== "string" )
3407                         s.data = jQuery.param(s.data);
3408
3409                 // Handle JSONP Parameter Callbacks
3410                 if ( s.dataType == "jsonp" ) {
3411                         if ( type == "GET" ) {
3412                                 if ( !s.url.match(jsre) )
3413                                         s.url += (s.url.match(/\?/) ? "&" : "?") + (s.jsonp || "callback") + "=?";
3414                         } else if ( !s.data || !s.data.match(jsre) )
3415                                 s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
3416                         s.dataType = "json";
3417                 }
3418
3419                 // Build temporary JSONP function
3420                 if ( s.dataType == "json" && (s.data && s.data.match(jsre) || s.url.match(jsre)) ) {
3421                         jsonp = "jsonp" + jsc++;
3422
3423                         // Replace the =? sequence both in the query string and the data
3424                         if ( s.data )
3425                                 s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");
3426                         s.url = s.url.replace(jsre, "=" + jsonp + "$1");
3427
3428                         // We need to make sure
3429                         // that a JSONP style response is executed properly
3430                         s.dataType = "script";
3431
3432                         // Handle JSONP-style loading
3433                         window[ jsonp ] = function(tmp){
3434                                 data = tmp;
3435                                 success();
3436                                 complete();
3437                                 // Garbage collect
3438                                 window[ jsonp ] = undefined;
3439                                 try{ delete window[ jsonp ]; } catch(e){}
3440                                 if ( head )
3441                                         head.removeChild( script );
3442                         };
3443                 }
3444
3445                 if ( s.dataType == "script" && s.cache == null )
3446                         s.cache = false;
3447
3448                 if ( s.cache === false && type == "GET" ) {
3449                         var ts = now();
3450                         // try replacing _= if it is there
3451                         var ret = s.url.replace(/(\?|&)_=.*?(&|$)/, "$1_=" + ts + "$2");
3452                         // if nothing was replaced, add timestamp to the end
3453                         s.url = ret + ((ret == s.url) ? (s.url.match(/\?/) ? "&" : "?") + "_=" + ts : "");
3454                 }
3455
3456                 // If data is available, append data to url for get requests
3457                 if ( s.data && type == "GET" ) {
3458                         s.url += (s.url.match(/\?/) ? "&" : "?") + s.data;
3459
3460                         // IE likes to send both get and post data, prevent this
3461                         s.data = null;
3462                 }
3463
3464                 // Watch for a new set of requests
3465                 if ( s.global && ! jQuery.active++ )
3466                         jQuery.event.trigger( "ajaxStart" );
3467
3468                 // Matches an absolute URL, and saves the domain
3469                 var parts = /^(\w+:)?\/\/([^\/?#]+)/.exec( s.url );
3470
3471                 // If we're requesting a remote document
3472                 // and trying to load JSON or Script with a GET
3473                 if ( s.dataType == "script" && type == "GET" && parts
3474                         && ( parts[1] && parts[1] != location.protocol || parts[2] != location.host )){
3475
3476                         var head = document.getElementsByTagName("head")[0];
3477                         var script = document.createElement("script");
3478                         script.src = s.url;
3479                         if (s.scriptCharset)
3480                                 script.charset = s.scriptCharset;
3481
3482                         // Handle Script loading
3483                         if ( !jsonp ) {
3484                                 var done = false;
3485
3486                                 // Attach handlers for all browsers
3487                                 script.onload = script.onreadystatechange = function(){
3488                                         if ( !done && (!this.readyState ||
3489                                                         this.readyState == "loaded" || this.readyState == "complete") ) {
3490                                                 done = true;
3491                                                 success();
3492                                                 complete();
3493
3494                                                 // Handle memory leak in IE
3495                                                 script.onload = script.onreadystatechange = null;
3496                                                 head.removeChild( script );
3497                                         }
3498                                 };
3499                         }
3500
3501                         head.appendChild(script);
3502
3503                         // We handle everything using the script element injection
3504                         return undefined;
3505                 }
3506
3507                 var requestDone = false;
3508
3509                 // Create the request object
3510                 var xhr = s.xhr();
3511
3512                 // Open the socket
3513                 // Passing null username, generates a login popup on Opera (#2865)
3514                 if( s.username )
3515                         xhr.open(type, s.url, s.async, s.username, s.password);
3516                 else
3517                         xhr.open(type, s.url, s.async);
3518
3519                 // Need an extra try/catch for cross domain requests in Firefox 3
3520                 try {
3521                         // Set the correct header, if data is being sent
3522                         if ( s.data )
3523                                 xhr.setRequestHeader("Content-Type", s.contentType);
3524
3525                         // Set the If-Modified-Since header, if ifModified mode.
3526                         if ( s.ifModified )
3527                                 xhr.setRequestHeader("If-Modified-Since",
3528                                         jQuery.lastModified[s.url] || "Thu, 01 Jan 1970 00:00:00 GMT" );
3529
3530                         // Set header so the called script knows that it's an XMLHttpRequest
3531                         xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
3532
3533                         // Set the Accepts header for the server, depending on the dataType
3534                         xhr.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ?
3535                                 s.accepts[ s.dataType ] + ", */*" :
3536                                 s.accepts._default );
3537                 } catch(e){}
3538
3539                 // Allow custom headers/mimetypes and early abort
3540                 if ( s.beforeSend && s.beforeSend(xhr, s) === false ) {
3541                         // Handle the global AJAX counter
3542                         if ( s.global && ! --jQuery.active )
3543                                 jQuery.event.trigger( "ajaxStop" );
3544                         // close opended socket
3545                         xhr.abort();
3546                         return false;
3547                 }
3548
3549                 if ( s.global )
3550                         jQuery.event.trigger("ajaxSend", [xhr, s]);
3551
3552                 // Wait for a response to come back
3553                 var onreadystatechange = function(isTimeout){
3554                         // The request was aborted, clear the interval and decrement jQuery.active
3555                         if (xhr.readyState == 0) {
3556                                 if (ival) {
3557                                         // clear poll interval
3558                                         clearInterval(ival);
3559                                         ival = null;
3560                                         // Handle the global AJAX counter
3561                                         if ( s.global && ! --jQuery.active )
3562                                                 jQuery.event.trigger( "ajaxStop" );
3563                                 }
3564                         // The transfer is complete and the data is available, or the request timed out
3565                         } else if ( !requestDone && xhr && (xhr.readyState == 4 || isTimeout == "timeout") ) {
3566                                 requestDone = true;
3567
3568                                 // clear poll interval
3569                                 if (ival) {
3570                                         clearInterval(ival);
3571                                         ival = null;
3572                                 }
3573
3574                                 status = isTimeout == "timeout" ? "timeout" :
3575                                         !jQuery.httpSuccess( xhr ) ? "error" :
3576                                         s.ifModified && jQuery.httpNotModified( xhr, s.url ) ? "notmodified" :
3577                                         "success";
3578
3579                                 if ( status == "success" ) {
3580                                         // Watch for, and catch, XML document parse errors
3581                                         try {
3582                                                 // process the data (runs the xml through httpData regardless of callback)
3583                                                 data = jQuery.httpData( xhr, s.dataType, s );
3584                                         } catch(e) {
3585                                                 status = "parsererror";
3586                                         }
3587                                 }
3588
3589                                 // Make sure that the request was successful or notmodified
3590                                 if ( status == "success" ) {
3591                                         // Cache Last-Modified header, if ifModified mode.
3592                                         var modRes;
3593                                         try {
3594                                                 modRes = xhr.getResponseHeader("Last-Modified");
3595                                         } catch(e) {} // swallow exception thrown by FF if header is not available
3596
3597                                         if ( s.ifModified && modRes )
3598                                                 jQuery.lastModified[s.url] = modRes;
3599
3600                                         // JSONP handles its own success callback
3601                                         if ( !jsonp )
3602                                                 success();
3603                                 } else
3604                                         jQuery.handleError(s, xhr, status);
3605
3606                                 // Fire the complete handlers
3607                                 complete();
3608
3609                                 if ( isTimeout )
3610                                         xhr.abort();
3611
3612                                 // Stop memory leaks
3613                                 if ( s.async )
3614                                         xhr = null;
3615                         }
3616                 };
3617
3618                 if ( s.async ) {
3619                         // don't attach the handler to the request, just poll it instead
3620                         var ival = setInterval(onreadystatechange, 13);
3621
3622                         // Timeout checker
3623                         if ( s.timeout > 0 )
3624                                 setTimeout(function(){
3625                                         // Check to see if the request is still happening
3626                                         if ( xhr && !requestDone )
3627                                                 onreadystatechange( "timeout" );
3628                                 }, s.timeout);
3629                 }
3630
3631                 // Send the data
3632                 try {
3633                         xhr.send(s.data);
3634                 } catch(e) {
3635                         jQuery.handleError(s, xhr, null, e);
3636                 }
3637
3638                 // firefox 1.5 doesn't fire statechange for sync requests
3639                 if ( !s.async )
3640                         onreadystatechange();
3641
3642                 function success(){
3643                         // If a local callback was specified, fire it and pass it the data
3644                         if ( s.success )
3645                                 s.success( data, status );
3646
3647                         // Fire the global callback
3648                         if ( s.global )
3649                                 jQuery.event.trigger( "ajaxSuccess", [xhr, s] );
3650                 }
3651
3652                 function complete(){
3653                         // Process result
3654                         if ( s.complete )
3655                                 s.complete(xhr, status);
3656
3657                         // The request was completed
3658                         if ( s.global )
3659                                 jQuery.event.trigger( "ajaxComplete", [xhr, s] );
3660
3661                         // Handle the global AJAX counter
3662                         if ( s.global && ! --jQuery.active )
3663                                 jQuery.event.trigger( "ajaxStop" );
3664                 }
3665
3666                 // return XMLHttpRequest to allow aborting the request etc.
3667                 return xhr;
3668         },
3669
3670         handleError: function( s, xhr, status, e ) {
3671                 // If a local callback was specified, fire it
3672                 if ( s.error ) s.error( xhr, status, e );
3673
3674                 // Fire the global callback
3675                 if ( s.global )
3676                         jQuery.event.trigger( "ajaxError", [xhr, s, e] );
3677         },
3678
3679         // Counter for holding the number of active queries
3680         active: 0,
3681
3682         // Determines if an XMLHttpRequest was successful or not
3683         httpSuccess: function( xhr ) {
3684                 try {
3685                         // IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450
3686                         return !xhr.status && location.protocol == "file:" ||
3687                                 ( xhr.status >= 200 && xhr.status < 300 ) || xhr.status == 304 || xhr.status == 1223;
3688                 } catch(e){}
3689                 return false;
3690         },
3691
3692         // Determines if an XMLHttpRequest returns NotModified
3693         httpNotModified: function( xhr, url ) {
3694                 try {
3695                         var xhrRes = xhr.getResponseHeader("Last-Modified");
3696
3697                         // Firefox always returns 200. check Last-Modified date
3698                         return xhr.status == 304 || xhrRes == jQuery.lastModified[url];
3699                 } catch(e){}
3700                 return false;
3701         },
3702
3703         httpData: function( xhr, type, s ) {
3704                 var ct = xhr.getResponseHeader("content-type"),
3705                         xml = type == "xml" || !type && ct && ct.indexOf("xml") >= 0,
3706                         data = xml ? xhr.responseXML : xhr.responseText;
3707
3708                 if ( xml && data.documentElement.tagName == "parsererror" )
3709                         throw "parsererror";
3710                         
3711                 // Allow a pre-filtering function to sanitize the response
3712                 // s != null is checked to keep backwards compatibility
3713                 if( s && s.dataFilter )
3714                         data = s.dataFilter( data, type );
3715
3716                 // The filter can actually parse the response
3717                 if( typeof data === "string" ){
3718
3719                         // If the type is "script", eval it in global context
3720                         if ( type == "script" )
3721                                 jQuery.globalEval( data );
3722
3723                         // Get the JavaScript object, if JSON is used.
3724                         if ( type == "json" )
3725                                 data = window["eval"]("(" + data + ")");
3726                 }
3727                 
3728                 return data;
3729         },
3730
3731         // Serialize an array of form elements or a set of
3732         // key/values into a query string
3733         param: function( a ) {
3734                 var s = [ ];
3735
3736                 function add( key, value ){
3737                         s[ s.length ] = encodeURIComponent(key) + '=' + encodeURIComponent(value);
3738                 };
3739
3740                 // If an array was passed in, assume that it is an array
3741                 // of form elements
3742                 if ( jQuery.isArray(a) || a.jquery )
3743                         // Serialize the form elements
3744                         jQuery.each( a, function(){
3745                                 add( this.name, this.value );
3746                         });
3747
3748                 // Otherwise, assume that it's an object of key/value pairs
3749                 else
3750                         // Serialize the key/values
3751                         for ( var j in a )
3752                                 // If the value is an array then the key names need to be repeated
3753                                 if ( jQuery.isArray(a[j]) )
3754                                         jQuery.each( a[j], function(){
3755                                                 add( j, this );
3756                                         });
3757                                 else
3758                                         add( j, jQuery.isFunction(a[j]) ? a[j]() : a[j] );
3759
3760                 // Return the resulting serialization
3761                 return s.join("&").replace(/%20/g, "+");
3762         }
3763
3764 });
3765 var elemdisplay = {},
3766         timerId,
3767         fxAttrs = [
3768                 // height animations
3769                 [ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],
3770                 // width animations
3771                 [ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
3772                 // opacity animations
3773                 [ "opacity" ]
3774         ];
3775
3776 function genFx( type, num ){
3777         var obj = {};
3778         jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function(){
3779                 obj[ this ] = type;
3780         });
3781         return obj;
3782 }
3783
3784 jQuery.fn.extend({
3785         show: function(speed,callback){
3786                 if ( speed ) {
3787                         return this.animate( genFx("show", 3), speed, callback);
3788                 } else {
3789                         for ( var i = 0, l = this.length; i < l; i++ ){
3790                                 var old = jQuery.data(this[i], "olddisplay");
3791                                 
3792                                 this[i].style.display = old || "";
3793                                 
3794                                 if ( jQuery.css(this[i], "display") === "none" ) {
3795                                         var tagName = this[i].tagName, display;
3796                                         
3797                                         if ( elemdisplay[ tagName ] ) {
3798                                                 display = elemdisplay[ tagName ];
3799                                         } else {
3800                                                 var elem = jQuery("<" + tagName + " />").appendTo("body");
3801                                                 
3802                                                 display = elem.css("display");
3803                                                 if ( display === "none" )
3804                                                         display = "block";
3805                                                 
3806                                                 elem.remove();
3807                                                 
3808                                                 elemdisplay[ tagName ] = display;
3809                                         }
3810                                         
3811                                         jQuery.data(this[i], "olddisplay", display);
3812                                 }
3813                         }
3814
3815                         // Set the display of the elements in a second loop
3816                         // to avoid the constant reflow
3817                         for ( var i = 0, l = this.length; i < l; i++ ){
3818                                 this[i].style.display = jQuery.data(this[i], "olddisplay") || "";
3819                         }
3820                         
3821                         return this;
3822                 }
3823         },
3824
3825         hide: function(speed,callback){
3826                 if ( speed ) {
3827                         return this.animate( genFx("hide", 3), speed, callback);
3828                 } else {
3829                         for ( var i = 0, l = this.length; i < l; i++ ){
3830                                 var old = jQuery.data(this[i], "olddisplay");
3831                                 if ( !old && old !== "none" )
3832                                         jQuery.data(this[i], "olddisplay", jQuery.css(this[i], "display"));
3833                         }
3834
3835                         // Set the display of the elements in a second loop
3836                         // to avoid the constant reflow
3837                         for ( var i = 0, l = this.length; i < l; i++ ){
3838                                 this[i].style.display = "none";
3839                         }
3840
3841                         return this;
3842                 }
3843         },
3844
3845         // Save the old toggle function
3846         _toggle: jQuery.fn.toggle,
3847
3848         toggle: function( fn, fn2 ){
3849                 var bool = typeof fn === "boolean";
3850
3851                 return jQuery.isFunction(fn) && jQuery.isFunction(fn2) ?
3852                         this._toggle.apply( this, arguments ) :
3853                         fn == null || bool ?
3854                                 this.each(function(){
3855                                         var state = bool ? fn : jQuery(this).is(":hidden");
3856                                         jQuery(this)[ state ? "show" : "hide" ]();
3857                                 }) :
3858                                 this.animate(genFx("toggle", 3), fn, fn2);
3859         },
3860
3861         fadeTo: function(speed,to,callback){
3862                 return this.animate({opacity: to}, speed, callback);
3863         },
3864
3865         animate: function( prop, speed, easing, callback ) {
3866                 var optall = jQuery.speed(speed, easing, callback);
3867
3868                 return this[ optall.queue === false ? "each" : "queue" ](function(){
3869                 
3870                         var opt = jQuery.extend({}, optall), p,
3871                                 hidden = this.nodeType == 1 && jQuery(this).is(":hidden"),
3872                                 self = this;
3873         
3874                         for ( p in prop ) {
3875                                 if ( prop[p] == "hide" && hidden || prop[p] == "show" && !hidden )
3876                                         return opt.complete.call(this);
3877
3878                                 if ( ( p == "height" || p == "width" ) && this.style ) {
3879                                         // Store display property
3880                                         opt.display = jQuery.css(this, "display");
3881
3882                                         // Make sure that nothing sneaks out
3883                                         opt.overflow = this.style.overflow;
3884                                 }
3885                         }
3886
3887                         if ( opt.overflow != null )
3888                                 this.style.overflow = "hidden";
3889
3890                         opt.curAnim = jQuery.extend({}, prop);
3891
3892                         jQuery.each( prop, function(name, val){
3893                                 var e = new jQuery.fx( self, opt, name );
3894
3895                                 if ( /toggle|show|hide/.test(val) )
3896                                         e[ val == "toggle" ? hidden ? "show" : "hide" : val ]( prop );
3897                                 else {
3898                                         var parts = val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),
3899                                                 start = e.cur(true) || 0;
3900
3901                                         if ( parts ) {
3902                                                 var end = parseFloat(parts[2]),
3903                                                         unit = parts[3] || "px";
3904
3905                                                 // We need to compute starting value
3906                                                 if ( unit != "px" ) {
3907                                                         self.style[ name ] = (end || 1) + unit;
3908                                                         start = ((end || 1) / e.cur(true)) * start;
3909                                                         self.style[ name ] = start + unit;
3910                                                 }
3911
3912                                                 // If a +=/-= token was provided, we're doing a relative animation
3913                                                 if ( parts[1] )
3914                                                         end = ((parts[1] == "-=" ? -1 : 1) * end) + start;
3915
3916                                                 e.custom( start, end, unit );
3917                                         } else
3918                                                 e.custom( start, val, "" );
3919                                 }
3920                         });
3921
3922                         // For JS strict compliance
3923                         return true;
3924                 });
3925         },
3926
3927         stop: function(clearQueue, gotoEnd){
3928                 var timers = jQuery.timers;
3929
3930                 if (clearQueue)
3931                         this.queue([]);
3932
3933                 this.each(function(){
3934                         // go in reverse order so anything added to the queue during the loop is ignored
3935                         for ( var i = timers.length - 1; i >= 0; i-- )
3936                                 if ( timers[i].elem == this ) {
3937                                         if (gotoEnd)
3938                                                 // force the next step to be the last
3939                                                 timers[i](true);
3940                                         timers.splice(i, 1);
3941                                 }
3942                 });
3943
3944                 // start the next in the queue if the last step wasn't forced
3945                 if (!gotoEnd)
3946                         this.dequeue();
3947
3948                 return this;
3949         }
3950
3951 });
3952
3953 // Generate shortcuts for custom animations
3954 jQuery.each({
3955         slideDown: genFx("show", 1),
3956         slideUp: genFx("hide", 1),
3957         slideToggle: genFx("toggle", 1),
3958         fadeIn: { opacity: "show" },
3959         fadeOut: { opacity: "hide" }
3960 }, function( name, props ){
3961         jQuery.fn[ name ] = function( speed, callback ){
3962                 return this.animate( props, speed, callback );
3963         };
3964 });
3965
3966 jQuery.extend({
3967
3968         speed: function(speed, easing, fn) {
3969                 var opt = typeof speed === "object" ? speed : {
3970                         complete: fn || !fn && easing ||
3971                                 jQuery.isFunction( speed ) && speed,
3972                         duration: speed,
3973                         easing: fn && easing || easing && !jQuery.isFunction(easing) && easing
3974                 };
3975
3976                 opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
3977                         jQuery.fx.speeds[opt.duration] || jQuery.fx.speeds._default;
3978
3979                 // Queueing
3980                 opt.old = opt.complete;
3981                 opt.complete = function(){
3982                         if ( opt.queue !== false )
3983                                 jQuery(this).dequeue();
3984                         if ( jQuery.isFunction( opt.old ) )
3985                                 opt.old.call( this );
3986                 };
3987
3988                 return opt;
3989         },
3990
3991         easing: {
3992                 linear: function( p, n, firstNum, diff ) {
3993                         return firstNum + diff * p;
3994                 },
3995                 swing: function( p, n, firstNum, diff ) {
3996                         return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
3997                 }
3998         },
3999
4000         timers: [],
4001
4002         fx: function( elem, options, prop ){
4003                 this.options = options;
4004                 this.elem = elem;
4005                 this.prop = prop;
4006
4007                 if ( !options.orig )
4008                         options.orig = {};
4009         }
4010
4011 });
4012
4013 jQuery.fx.prototype = {
4014
4015         // Simple function for setting a style value
4016         update: function(){
4017                 if ( this.options.step )
4018                         this.options.step.call( this.elem, this.now, this );
4019
4020                 (jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );
4021
4022                 // Set display property to block for height/width animations
4023                 if ( ( this.prop == "height" || this.prop == "width" ) && this.elem.style )
4024                         this.elem.style.display = "block";
4025         },
4026
4027         // Get the current size
4028         cur: function(force){
4029                 if ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) )
4030                         return this.elem[ this.prop ];
4031
4032                 var r = parseFloat(jQuery.css(this.elem, this.prop, force));
4033                 return r && r > -10000 ? r : parseFloat(jQuery.curCSS(this.elem, this.prop)) || 0;
4034         },
4035
4036         // Start an animation from one number to another
4037         custom: function(from, to, unit){
4038                 this.startTime = now();
4039                 this.start = from;
4040                 this.end = to;
4041                 this.unit = unit || this.unit || "px";
4042                 this.now = this.start;
4043                 this.pos = this.state = 0;
4044
4045                 var self = this;
4046                 function t(gotoEnd){
4047                         return self.step(gotoEnd);
4048                 }
4049
4050                 t.elem = this.elem;
4051
4052                 if ( t() && jQuery.timers.push(t) && !timerId ) {
4053                         timerId = setInterval(function(){
4054                                 var timers = jQuery.timers;
4055
4056                                 for ( var i = 0; i < timers.length; i++ )
4057                                         if ( !timers[i]() )
4058                                                 timers.splice(i--, 1);
4059
4060                                 if ( !timers.length ) {
4061                                         clearInterval( timerId );
4062                                         timerId = undefined;
4063                                 }
4064                         }, 13);
4065                 }
4066         },
4067
4068         // Simple 'show' function
4069         show: function(){
4070                 // Remember where we started, so that we can go back to it later
4071                 this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
4072                 this.options.show = true;
4073
4074                 // Begin the animation
4075                 // Make sure that we start at a small width/height to avoid any
4076                 // flash of content
4077                 this.custom(this.prop == "width" || this.prop == "height" ? 1 : 0, this.cur());
4078
4079                 // Start by showing the element
4080                 jQuery(this.elem).show();
4081         },
4082
4083         // Simple 'hide' function
4084         hide: function(){
4085                 // Remember where we started, so that we can go back to it later
4086                 this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
4087                 this.options.hide = true;
4088
4089                 // Begin the animation
4090                 this.custom(this.cur(), 0);
4091         },
4092
4093         // Each step of an animation
4094         step: function(gotoEnd){
4095                 var t = now();
4096
4097                 if ( gotoEnd || t >= this.options.duration + this.startTime ) {
4098                         this.now = this.end;
4099                         this.pos = this.state = 1;
4100                         this.update();
4101
4102                         this.options.curAnim[ this.prop ] = true;
4103
4104                         var done = true;
4105                         for ( var i in this.options.curAnim )
4106                                 if ( this.options.curAnim[i] !== true )
4107                                         done = false;
4108
4109                         if ( done ) {
4110                                 if ( this.options.display != null ) {
4111                                         // Reset the overflow
4112                                         this.elem.style.overflow = this.options.overflow;
4113
4114                                         // Reset the display
4115                                         this.elem.style.display = this.options.display;
4116                                         if ( jQuery.css(this.elem, "display") == "none" )
4117                                                 this.elem.style.display = "block";
4118                                 }
4119
4120                                 // Hide the element if the "hide" operation was done
4121                                 if ( this.options.hide )
4122                                         jQuery(this.elem).hide();
4123
4124                                 // Reset the properties, if the item has been hidden or shown
4125                                 if ( this.options.hide || this.options.show )
4126                                         for ( var p in this.options.curAnim )
4127                                                 jQuery.attr(this.elem.style, p, this.options.orig[p]);
4128                                         
4129                                 // Execute the complete function
4130                                 this.options.complete.call( this.elem );
4131                         }
4132
4133                         return false;
4134                 } else {
4135                         var n = t - this.startTime;
4136                         this.state = n / this.options.duration;
4137
4138                         // Perform the easing function, defaults to swing
4139                         this.pos = jQuery.easing[this.options.easing || (jQuery.easing.swing ? "swing" : "linear")](this.state, n, 0, 1, this.options.duration);
4140                         this.now = this.start + ((this.end - this.start) * this.pos);
4141
4142                         // Perform the next step of the animation
4143                         this.update();
4144                 }
4145
4146                 return true;
4147         }
4148
4149 };
4150
4151 jQuery.extend( jQuery.fx, {
4152         speeds:{
4153                 slow: 600,
4154                 fast: 200,
4155                 // Default speed
4156                 _default: 400
4157         },
4158         step: {
4159
4160                 opacity: function(fx){
4161                         jQuery.attr(fx.elem.style, "opacity", fx.now);
4162                 },
4163
4164                 _default: function(fx){
4165                         if ( fx.elem.style && fx.elem.style[ fx.prop ] != null )
4166                                 fx.elem.style[ fx.prop ] = fx.now + fx.unit;
4167                         else
4168                                 fx.elem[ fx.prop ] = fx.now;
4169                 }
4170         }
4171 });
4172 if ( document.documentElement["getBoundingClientRect"] )
4173         jQuery.fn.offset = function() {
4174                 if ( !this[0] ) return { top: 0, left: 0 };
4175                 if ( this[0] === this[0].ownerDocument.body ) return jQuery.offset.bodyOffset( this[0] );
4176                 var box  = this[0].getBoundingClientRect(), doc = this[0].ownerDocument, body = doc.body, docElem = doc.documentElement,
4177                         clientTop = docElem.clientTop || body.clientTop || 0, clientLeft = docElem.clientLeft || body.clientLeft || 0,
4178                         top  = box.top  + (self.pageYOffset || jQuery.boxModel && docElem.scrollTop  || body.scrollTop ) - clientTop,
4179                         left = box.left + (self.pageXOffset || jQuery.boxModel && docElem.scrollLeft || body.scrollLeft) - clientLeft;
4180                 return { top: top, left: left };
4181         };
4182 else 
4183         jQuery.fn.offset = function() {
4184                 if ( !this[0] ) return { top: 0, left: 0 };
4185                 if ( this[0] === this[0].ownerDocument.body ) return jQuery.offset.bodyOffset( this[0] );
4186                 jQuery.offset.initialized || jQuery.offset.initialize();
4187
4188                 var elem = this[0], offsetParent = elem.offsetParent, prevOffsetParent = elem,
4189                         doc = elem.ownerDocument, computedStyle, docElem = doc.documentElement,
4190                         body = doc.body, defaultView = doc.defaultView,
4191                         prevComputedStyle = defaultView.getComputedStyle(elem, null),
4192                         top = elem.offsetTop, left = elem.offsetLeft;
4193
4194                 while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {
4195                         computedStyle = defaultView.getComputedStyle(elem, null);
4196                         top -= elem.scrollTop, left -= elem.scrollLeft;
4197                         if ( elem === offsetParent ) {
4198                                 top += elem.offsetTop, left += elem.offsetLeft;
4199                                 if ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && /^t(able|d|h)$/i.test(elem.tagName)) )
4200                                         top  += parseInt( computedStyle.borderTopWidth,  10) || 0,
4201                                         left += parseInt( computedStyle.borderLeftWidth, 10) || 0;
4202                                 prevOffsetParent = offsetParent, offsetParent = elem.offsetParent;
4203                         }
4204                         if ( jQuery.offset.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" )
4205                                 top  += parseInt( computedStyle.borderTopWidth,  10) || 0,
4206                                 left += parseInt( computedStyle.borderLeftWidth, 10) || 0;
4207                         prevComputedStyle = computedStyle;
4208                 }
4209
4210                 if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" )
4211                         top  += body.offsetTop,
4212                         left += body.offsetLeft;
4213
4214                 if ( prevComputedStyle.position === "fixed" )
4215                         top  += Math.max(docElem.scrollTop, body.scrollTop),
4216                         left += Math.max(docElem.scrollLeft, body.scrollLeft);
4217
4218                 return { top: top, left: left };
4219         };
4220
4221 jQuery.offset = {
4222         initialize: function() {
4223                 if ( this.initialized ) return;
4224                 var body = document.body, container = document.createElement('div'), innerDiv, checkDiv, table, td, rules, prop, bodyMarginTop = body.style.marginTop,
4225                         html = '<div style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;"><div></div></div><table style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;" cellpadding="0" cellspacing="0"><tr><td></td></tr></table>';
4226
4227                 rules = { position: 'absolute', top: 0, left: 0, margin: 0, border: 0, width: '1px', height: '1px', visibility: 'hidden' };
4228                 for ( prop in rules ) container.style[prop] = rules[prop];
4229
4230                 container.innerHTML = html;
4231                 body.insertBefore(container, body.firstChild);
4232                 innerDiv = container.firstChild, checkDiv = innerDiv.firstChild, td = innerDiv.nextSibling.firstChild.firstChild;
4233
4234                 this.doesNotAddBorder = (checkDiv.offsetTop !== 5);
4235                 this.doesAddBorderForTableAndCells = (td.offsetTop === 5);
4236
4237                 innerDiv.style.overflow = 'hidden', innerDiv.style.position = 'relative';
4238                 this.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5);
4239
4240                 body.style.marginTop = '1px';
4241                 this.doesNotIncludeMarginInBodyOffset = (body.offsetTop === 0);
4242                 body.style.marginTop = bodyMarginTop;
4243
4244                 body.removeChild(container);
4245                 this.initialized = true;
4246         },
4247
4248         bodyOffset: function(body) {
4249                 jQuery.offset.initialized || jQuery.offset.initialize();
4250                 var top = body.offsetTop, left = body.offsetLeft;
4251                 if ( jQuery.offset.doesNotIncludeMarginInBodyOffset )
4252                         top  += parseInt( jQuery.curCSS(body, 'marginTop',  true), 10 ) || 0,
4253                         left += parseInt( jQuery.curCSS(body, 'marginLeft', true), 10 ) || 0;
4254                 return { top: top, left: left };
4255         }
4256 };
4257
4258
4259 jQuery.fn.extend({
4260         position: function() {
4261                 var left = 0, top = 0, results;
4262
4263                 if ( this[0] ) {
4264                         // Get *real* offsetParent
4265                         var offsetParent = this.offsetParent(),
4266
4267                         // Get correct offsets
4268                         offset       = this.offset(),
4269                         parentOffset = /^body|html$/i.test(offsetParent[0].tagName) ? { top: 0, left: 0 } : offsetParent.offset();
4270
4271                         // Subtract element margins
4272                         // note: when an element has margin: auto the offsetLeft and marginLeft 
4273                         // are the same in Safari causing offset.left to incorrectly be 0
4274                         offset.top  -= num( this, 'marginTop'  );
4275                         offset.left -= num( this, 'marginLeft' );
4276
4277                         // Add offsetParent borders
4278                         parentOffset.top  += num( offsetParent, 'borderTopWidth'  );
4279                         parentOffset.left += num( offsetParent, 'borderLeftWidth' );
4280
4281                         // Subtract the two offsets
4282                         results = {
4283                                 top:  offset.top  - parentOffset.top,
4284                                 left: offset.left - parentOffset.left
4285                         };
4286                 }
4287
4288                 return results;
4289         },
4290
4291         offsetParent: function() {
4292                 var offsetParent = this[0].offsetParent || document.body;
4293                 while ( offsetParent && (!/^body|html$/i.test(offsetParent.tagName) && jQuery.css(offsetParent, 'position') == 'static') )
4294                         offsetParent = offsetParent.offsetParent;
4295                 return jQuery(offsetParent);
4296         }
4297 });
4298
4299
4300 // Create scrollLeft and scrollTop methods
4301 jQuery.each( ['Left', 'Top'], function(i, name) {
4302         var method = 'scroll' + name;
4303         
4304         jQuery.fn[ method ] = function(val) {
4305                 if (!this[0]) return null;
4306
4307                 return val !== undefined ?
4308
4309                         // Set the scroll offset
4310                         this.each(function() {
4311                                 this == window || this == document ?
4312                                         window.scrollTo(
4313                                                 !i ? val : jQuery(window).scrollLeft(),
4314                                                  i ? val : jQuery(window).scrollTop()
4315                                         ) :
4316                                         this[ method ] = val;
4317                         }) :
4318
4319                         // Return the scroll offset
4320                         this[0] == window || this[0] == document ?
4321                                 self[ i ? 'pageYOffset' : 'pageXOffset' ] ||
4322                                         jQuery.boxModel && document.documentElement[ method ] ||
4323                                         document.body[ method ] :
4324                                 this[0][ method ];
4325         };
4326 });
4327 // Create innerHeight, innerWidth, outerHeight and outerWidth methods
4328 jQuery.each([ "Height", "Width" ], function(i, name){
4329
4330         var tl = i ? "Left"  : "Top",  // top or left
4331                 br = i ? "Right" : "Bottom", // bottom or right
4332                 lower = name.toLowerCase();
4333
4334         // innerHeight and innerWidth
4335         jQuery.fn["inner" + name] = function(){
4336                 return this[0] ?
4337                         jQuery.css( this[0], lower, false, "padding" ) :
4338                         null;
4339         };
4340
4341         // outerHeight and outerWidth
4342         jQuery.fn["outer" + name] = function(margin) {
4343                 return this[0] ?
4344                         jQuery.css( this[0], lower, false, margin ? "margin" : "border" ) :
4345                         null;
4346         };
4347         
4348         var type = name.toLowerCase();
4349
4350         jQuery.fn[ type ] = function( size ) {
4351                 // Get window width or height
4352                 return this[0] == window ?
4353                         // Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
4354                         document.compatMode == "CSS1Compat" && document.documentElement[ "client" + name ] ||
4355                         document.body[ "client" + name ] :
4356
4357                         // Get document width or height
4358                         this[0] == document ?
4359                                 // Either scroll[Width/Height] or offset[Width/Height], whichever is greater
4360                                 Math.max(
4361                                         document.documentElement["client" + name],
4362                                         document.body["scroll" + name], document.documentElement["scroll" + name],
4363                                         document.body["offset" + name], document.documentElement["offset" + name]
4364                                 ) :
4365
4366                                 // Get or set width or height on the element
4367                                 size === undefined ?
4368                                         // Get width or height on the element
4369                                         (this.length ? jQuery.css( this[0], type ) : null) :
4370
4371                                         // Set the width or height on the element (default to pixels if value is unitless)
4372                                         this.css( type, typeof size === "string" ? size : size + "px" );
4373         };
4374
4375 });
4376 })();