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