WordPress源代码——jquery(jquery-1.2.6.js)

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

请登录后发表评论

    暂无评论内容