1/*!
2 * jQuery JavaScript Library v1.4.2
3 * http://jquery.com/
4 *
5 * Copyright 2010, John Resig
6 * Dual licensed under the MIT or GPL Version 2 licenses.
7 * http://jquery.org/license
8 *
9 * Includes Sizzle.js
10 * http://sizzlejs.com/
11 * Copyright 2010, The Dojo Foundation
12 * Released under the MIT, BSD, and GPL Licenses.
13 *
14 * Date: Sat Feb 13 22:33:48 2010 -0500
15 */
16(function( window, undefined ) {
17
18// Define a local copy of jQuery
19var jQuery = function( selector, context ) {
20		// The jQuery object is actually just the init constructor 'enhanced'
21		return new jQuery.fn.init( selector, context );
22	},
23
24	// Map over jQuery in case of overwrite
25	_jQuery = window.jQuery,
26
27	// Map over the $ in case of overwrite
28	_$ = window.$,
29
30	// Use the correct document accordingly with window argument (sandbox)
31	document = window.document,
32
33	// A central reference to the root jQuery(document)
34	rootjQuery,
35
36	// A simple way to check for HTML strings or ID strings
37	// (both of which we optimize for)
38	quickExpr = /^[^<]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/,
39
40	// Is it a simple selector
41	isSimple = /^.[^:#\[\.,]*$/,
42
43	// Check if a string has a non-whitespace character in it
44	rnotwhite = /\S/,
45
46	// Used for trimming whitespace
47	rtrim = /^(\s|\u00A0)+|(\s|\u00A0)+$/g,
48
49	// Match a standalone tag
50	rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/,
51
52	// Keep a UserAgent string for use with jQuery.browser
53	userAgent = navigator.userAgent,
54
55	// For matching the engine and version of the browser
56	browserMatch,
57
58	// Has the ready events already been bound?
59	readyBound = false,
60
61	// The functions to execute on DOM ready
62	readyList = [],
63
64	// The ready event handler
65	DOMContentLoaded,
66
67	// Save a reference to some core methods
68	toString = Object.prototype.toString,
69	hasOwnProperty = Object.prototype.hasOwnProperty,
70	push = Array.prototype.push,
71	slice = Array.prototype.slice,
72	indexOf = Array.prototype.indexOf;
73
74jQuery.fn = jQuery.prototype = {
75	init: function( selector, context ) {
76		var match, elem, ret, doc;
77
78		// Handle $(""), $(null), or $(undefined)
79		if ( !selector ) {
80			return this;
81		}
82
83		// Handle $(DOMElement)
84		if ( selector.nodeType ) {
85			this.context = this[0] = selector;
86			this.length = 1;
87			return this;
88		}
89
90		// The body element only exists once, optimize finding it
91		if ( selector === "body" && !context ) {
92			this.context = document;
93			this[0] = document.body;
94			this.selector = "body";
95			this.length = 1;
96			return this;
97		}
98
99		// Handle HTML strings
100		if ( typeof selector === "string" ) {
101			// Are we dealing with HTML string or an ID?
102			match = quickExpr.exec( selector );
103
104			// Verify a match, and that no context was specified for #id
105			if ( match && (match[1] || !context) ) {
106
107				// HANDLE: $(html) -> $(array)
108				if ( match[1] ) {
109					doc = (context ? context.ownerDocument || context : document);
110
111					// If a single string is passed in and it's a single tag
112					// just do a createElement and skip the rest
113					ret = rsingleTag.exec( selector );
114
115					if ( ret ) {
116						if ( jQuery.isPlainObject( context ) ) {
117							selector = [ document.createElement( ret[1] ) ];
118							jQuery.fn.attr.call( selector, context, true );
119
120						} else {
121							selector = [ doc.createElement( ret[1] ) ];
122						}
123
124					} else {
125						ret = buildFragment( [ match[1] ], [ doc ] );
126						selector = (ret.cacheable ? ret.fragment.cloneNode(true) : ret.fragment).childNodes;
127					}
128
129					return jQuery.merge( this, selector );
130
131				// HANDLE: $("#id")
132				} else {
133					elem = document.getElementById( match[2] );
134
135					if ( elem ) {
136						// Handle the case where IE and Opera return items
137						// by name instead of ID
138						if ( elem.id !== match[2] ) {
139							return rootjQuery.find( selector );
140						}
141
142						// Otherwise, we inject the element directly into the jQuery object
143						this.length = 1;
144						this[0] = elem;
145					}
146
147					this.context = document;
148					this.selector = selector;
149					return this;
150				}
151
152			// HANDLE: $("TAG")
153			} else if ( !context && /^\w+$/.test( selector ) ) {
154				this.selector = selector;
155				this.context = document;
156				selector = document.getElementsByTagName( selector );
157				return jQuery.merge( this, selector );
158
159			// HANDLE: $(expr, $(...))
160			} else if ( !context || context.jquery ) {
161				return (context || rootjQuery).find( selector );
162
163			// HANDLE: $(expr, context)
164			// (which is just equivalent to: $(context).find(expr)
165			} else {
166				return jQuery( context ).find( selector );
167			}
168
169		// HANDLE: $(function)
170		// Shortcut for document ready
171		} else if ( jQuery.isFunction( selector ) ) {
172			return rootjQuery.ready( selector );
173		}
174
175		if (selector.selector !== undefined) {
176			this.selector = selector.selector;
177			this.context = selector.context;
178		}
179
180		return jQuery.makeArray( selector, this );
181	},
182
183	// Start with an empty selector
184	selector: "",
185
186	// The current version of jQuery being used
187	jquery: "1.4.2",
188
189	// The default length of a jQuery object is 0
190	length: 0,
191
192	// The number of elements contained in the matched element set
193	size: function() {
194		return this.length;
195	},
196
197	toArray: function() {
198		return slice.call( this, 0 );
199	},
200
201	// Get the Nth element in the matched element set OR
202	// Get the whole matched element set as a clean array
203	get: function( num ) {
204		return num == null ?
205
206			// Return a 'clean' array
207			this.toArray() :
208
209			// Return just the object
210			( num < 0 ? this.slice(num)[ 0 ] : this[ num ] );
211	},
212
213	// Take an array of elements and push it onto the stack
214	// (returning the new matched element set)
215	pushStack: function( elems, name, selector ) {
216		// Build a new jQuery matched element set
217		var ret = jQuery();
218
219		if ( jQuery.isArray( elems ) ) {
220			push.apply( ret, elems );
221
222		} else {
223			jQuery.merge( ret, elems );
224		}
225
226		// Add the old object onto the stack (as a reference)
227		ret.prevObject = this;
228
229		ret.context = this.context;
230
231		if ( name === "find" ) {
232			ret.selector = this.selector + (this.selector ? " " : "") + selector;
233		} else if ( name ) {
234			ret.selector = this.selector + "." + name + "(" + selector + ")";
235		}
236
237		// Return the newly-formed element set
238		return ret;
239	},
240
241	// Execute a callback for every element in the matched set.
242	// (You can seed the arguments with an array of args, but this is
243	// only used internally.)
244	each: function( callback, args ) {
245		return jQuery.each( this, callback, args );
246	},
247
248	ready: function( fn ) {
249		// Attach the listeners
250		jQuery.bindReady();
251
252		// If the DOM is already ready
253		if ( jQuery.isReady ) {
254			// Execute the function immediately
255			fn.call( document, jQuery );
256
257		// Otherwise, remember the function for later
258		} else if ( readyList ) {
259			// Add the function to the wait list
260			readyList.push( fn );
261		}
262
263		return this;
264	},
265
266	eq: function( i ) {
267		return i === -1 ?
268			this.slice( i ) :
269			this.slice( i, +i + 1 );
270	},
271
272	first: function() {
273		return this.eq( 0 );
274	},
275
276	last: function() {
277		return this.eq( -1 );
278	},
279
280	slice: function() {
281		return this.pushStack( slice.apply( this, arguments ),
282			"slice", slice.call(arguments).join(",") );
283	},
284
285	map: function( callback ) {
286		return this.pushStack( jQuery.map(this, function( elem, i ) {
287			return callback.call( elem, i, elem );
288		}));
289	},
290
291	end: function() {
292		return this.prevObject || jQuery(null);
293	},
294
295	// For internal use only.
296	// Behaves like an Array's method, not like a jQuery method.
297	push: push,
298	sort: [].sort,
299	splice: [].splice
300};
301
302// Give the init function the jQuery prototype for later instantiation
303jQuery.fn.init.prototype = jQuery.fn;
304
305jQuery.extend = jQuery.fn.extend = function() {
306	// copy reference to target object
307	var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options, name, src, copy;
308
309	// Handle a deep copy situation
310	if ( typeof target === "boolean" ) {
311		deep = target;
312		target = arguments[1] || {};
313		// skip the boolean and the target
314		i = 2;
315	}
316
317	// Handle case when target is a string or something (possible in deep copy)
318	if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
319		target = {};
320	}
321
322	// extend jQuery itself if only one argument is passed
323	if ( length === i ) {
324		target = this;
325		--i;
326	}
327
328	for ( ; i < length; i++ ) {
329		// Only deal with non-null/undefined values
330		if ( (options = arguments[ i ]) != null ) {
331			// Extend the base object
332			for ( name in options ) {
333				src = target[ name ];
334				copy = options[ name ];
335
336				// Prevent never-ending loop
337				if ( target === copy ) {
338					continue;
339				}
340
341				// Recurse if we're merging object literal values or arrays
342				if ( deep && copy && ( jQuery.isPlainObject(copy) || jQuery.isArray(copy) ) ) {
343					var clone = src && ( jQuery.isPlainObject(src) || jQuery.isArray(src) ) ? src
344						: jQuery.isArray(copy) ? [] : {};
345
346					// Never move original objects, clone them
347					target[ name ] = jQuery.extend( deep, clone, copy );
348
349				// Don't bring in undefined values
350				} else if ( copy !== undefined ) {
351					target[ name ] = copy;
352				}
353			}
354		}
355	}
356
357	// Return the modified object
358	return target;
359};
360
361jQuery.extend({
362	noConflict: function( deep ) {
363		window.$ = _$;
364
365		if ( deep ) {
366			window.jQuery = _jQuery;
367		}
368
369		return jQuery;
370	},
371
372	// Is the DOM ready to be used? Set to true once it occurs.
373	isReady: false,
374
375	// Handle when the DOM is ready
376	ready: function() {
377		// Make sure that the DOM is not already loaded
378		if ( !jQuery.isReady ) {
379			// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
380			if ( !document.body ) {
381				return setTimeout( jQuery.ready, 13 );
382			}
383
384			// Remember that the DOM is ready
385			jQuery.isReady = true;
386
387			// If there are functions bound, to execute
388			if ( readyList ) {
389				// Execute all of them
390				var fn, i = 0;
391				while ( (fn = readyList[ i++ ]) ) {
392					fn.call( document, jQuery );
393				}
394
395				// Reset the list of functions
396				readyList = null;
397			}
398
399			// Trigger any bound ready events
400			if ( jQuery.fn.triggerHandler ) {
401				jQuery( document ).triggerHandler( "ready" );
402			}
403		}
404	},
405
406	bindReady: function() {
407		if ( readyBound ) {
408			return;
409		}
410
411		readyBound = true;
412
413		// Catch cases where $(document).ready() is called after the
414		// browser event has already occurred.
415		if ( document.readyState === "complete" ) {
416			return jQuery.ready();
417		}
418
419		// Mozilla, Opera and webkit nightlies currently support this event
420		if ( document.addEventListener ) {
421			// Use the handy event callback
422			document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
423
424			// A fallback to window.onload, that will always work
425			window.addEventListener( "load", jQuery.ready, false );
426
427		// If IE event model is used
428		} else if ( document.attachEvent ) {
429			// ensure firing before onload,
430			// maybe late but safe also for iframes
431			document.attachEvent("onreadystatechange", DOMContentLoaded);
432
433			// A fallback to window.onload, that will always work
434			window.attachEvent( "onload", jQuery.ready );
435
436			// If IE and not a frame
437			// continually check to see if the document is ready
438			var toplevel = false;
439
440			try {
441				toplevel = window.frameElement == null;
442			} catch(e) {}
443
444			if ( document.documentElement.doScroll && toplevel ) {
445				doScrollCheck();
446			}
447		}
448	},
449
450	// See test/unit/core.js for details concerning isFunction.
451	// Since version 1.3, DOM methods and functions like alert
452	// aren't supported. They return false on IE (#2968).
453	isFunction: function( obj ) {
454		return toString.call(obj) === "[object Function]";
455	},
456
457	isArray: function( obj ) {
458		return toString.call(obj) === "[object Array]";
459	},
460
461	isPlainObject: function( obj ) {
462		// Must be an Object.
463		// Because of IE, we also have to check the presence of the constructor property.
464		// Make sure that DOM nodes and window objects don't pass through, as well
465		if ( !obj || toString.call(obj) !== "[object Object]" || obj.nodeType || obj.setInterval ) {
466			return false;
467		}
468
469		// Not own constructor property must be Object
470		if ( obj.constructor
471			&& !hasOwnProperty.call(obj, "constructor")
472			&& !hasOwnProperty.call(obj.constructor.prototype, "isPrototypeOf") ) {
473			return false;
474		}
475
476		// Own properties are enumerated firstly, so to speed up,
477		// if last one is own, then all properties are own.
478
479		var key;
480		for ( key in obj ) {}
481
482		return key === undefined || hasOwnProperty.call( obj, key );
483	},
484
485	isEmptyObject: function( obj ) {
486		for ( var name in obj ) {
487			return false;
488		}
489		return true;
490	},
491
492	error: function( msg ) {
493		throw msg;
494	},
495
496	parseJSON: function( data ) {
497		if ( typeof data !== "string" || !data ) {
498			return null;
499		}
500
501		// Make sure leading/trailing whitespace is removed (IE can't handle it)
502		data = jQuery.trim( data );
503
504		// Make sure the incoming data is actual JSON
505		// Logic borrowed from http://json.org/json2.js
506		if ( /^[\],:{}\s]*$/.test(data.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, "@")
507			.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, "]")
508			.replace(/(?:^|:|,)(?:\s*\[)+/g, "")) ) {
509
510			// Try to use the native JSON parser first
511			return window.JSON && window.JSON.parse ?
512				window.JSON.parse( data ) :
513				(new Function("return " + data))();
514
515		} else {
516			jQuery.error( "Invalid JSON: " + data );
517		}
518	},
519
520	noop: function() {},
521
522	// Evalulates a script in a global context
523	globalEval: function( data ) {
524		if ( data && rnotwhite.test(data) ) {
525			// Inspired by code by Andrea Giammarchi
526			// http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
527			var head = document.getElementsByTagName("head")[0] || document.documentElement,
528				script = document.createElement("script");
529
530			script.type = "text/javascript";
531
532			if ( jQuery.support.scriptEval ) {
533				script.appendChild( document.createTextNode( data ) );
534			} else {
535				script.text = data;
536			}
537
538			// Use insertBefore instead of appendChild to circumvent an IE6 bug.
539			// This arises when a base node is used (#2709).
540			head.insertBefore( script, head.firstChild );
541			head.removeChild( script );
542		}
543	},
544
545	nodeName: function( elem, name ) {
546		return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
547	},
548
549	// args is for internal usage only
550	each: function( object, callback, args ) {
551		var name, i = 0,
552			length = object.length,
553			isObj = length === undefined || jQuery.isFunction(object);
554
555		if ( args ) {
556			if ( isObj ) {
557				for ( name in object ) {
558					if ( callback.apply( object[ name ], args ) === false ) {
559						break;
560					}
561				}
562			} else {
563				for ( ; i < length; ) {
564					if ( callback.apply( object[ i++ ], args ) === false ) {
565						break;
566					}
567				}
568			}
569
570		// A special, fast, case for the most common use of each
571		} else {
572			if ( isObj ) {
573				for ( name in object ) {
574					if ( callback.call( object[ name ], name, object[ name ] ) === false ) {
575						break;
576					}
577				}
578			} else {
579				for ( var value = object[0];
580					i < length && callback.call( value, i, value ) !== false; value = object[++i] ) {}
581			}
582		}
583
584		return object;
585	},
586
587	trim: function( text ) {
588		return (text || "").replace( rtrim, "" );
589	},
590
591	// results is for internal usage only
592	makeArray: function( array, results ) {
593		var ret = results || [];
594
595		if ( array != null ) {
596			// The window, strings (and functions) also have 'length'
597			// The extra typeof function check is to prevent crashes
598			// in Safari 2 (See: #3039)
599			if ( array.length == null || typeof array === "string" || jQuery.isFunction(array) || (typeof array !== "function" && array.setInterval) ) {
600				push.call( ret, array );
601			} else {
602				jQuery.merge( ret, array );
603			}
604		}
605
606		return ret;
607	},
608
609	inArray: function( elem, array ) {
610		if ( array.indexOf ) {
611			return array.indexOf( elem );
612		}
613
614		for ( var i = 0, length = array.length; i < length; i++ ) {
615			if ( array[ i ] === elem ) {
616				return i;
617			}
618		}
619
620		return -1;
621	},
622
623	merge: function( first, second ) {
624		var i = first.length, j = 0;
625
626		if ( typeof second.length === "number" ) {
627			for ( var l = second.length; j < l; j++ ) {
628				first[ i++ ] = second[ j ];
629			}
630
631		} else {
632			while ( second[j] !== undefined ) {
633				first[ i++ ] = second[ j++ ];
634			}
635		}
636
637		first.length = i;
638
639		return first;
640	},
641
642	grep: function( elems, callback, inv ) {
643		var ret = [];
644
645		// Go through the array, only saving the items
646		// that pass the validator function
647		for ( var i = 0, length = elems.length; i < length; i++ ) {
648			if ( !inv !== !callback( elems[ i ], i ) ) {
649				ret.push( elems[ i ] );
650			}
651		}
652
653		return ret;
654	},
655
656	// arg is for internal usage only
657	map: function( elems, callback, arg ) {
658		var ret = [], value;
659
660		// Go through the array, translating each of the items to their
661		// new value (or values).
662		for ( var i = 0, length = elems.length; i < length; i++ ) {
663			value = callback( elems[ i ], i, arg );
664
665			if ( value != null ) {
666				ret[ ret.length ] = value;
667			}
668		}
669
670		return ret.concat.apply( [], ret );
671	},
672
673	// A global GUID counter for objects
674	guid: 1,
675
676	proxy: function( fn, proxy, thisObject ) {
677		if ( arguments.length === 2 ) {
678			if ( typeof proxy === "string" ) {
679				thisObject = fn;
680				fn = thisObject[ proxy ];
681				proxy = undefined;
682
683			} else if ( proxy && !jQuery.isFunction( proxy ) ) {
684				thisObject = proxy;
685				proxy = undefined;
686			}
687		}
688
689		if ( !proxy && fn ) {
690			proxy = function() {
691				return fn.apply( thisObject || this, arguments );
692			};
693		}
694
695		// Set the guid of unique handler to the same of original handler, so it can be removed
696		if ( fn ) {
697			proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;
698		}
699
700		// So proxy can be declared as an argument
701		return proxy;
702	},
703
704	// Use of jQuery.browser is frowned upon.
705	// More details: http://docs.jquery.com/Utilities/jQuery.browser
706	uaMatch: function( ua ) {
707		ua = ua.toLowerCase();
708
709		var match = /(webkit)[ \/]([\w.]+)/.exec( ua ) ||
710			/(opera)(?:.*version)?[ \/]([\w.]+)/.exec( ua ) ||
711			/(msie) ([\w.]+)/.exec( ua ) ||
712			!/compatible/.test( ua ) && /(mozilla)(?:.*? rv:([\w.]+))?/.exec( ua ) ||
713		  	[];
714
715		return { browser: match[1] || "", version: match[2] || "0" };
716	},
717
718	browser: {}
719});
720
721browserMatch = jQuery.uaMatch( userAgent );
722if ( browserMatch.browser ) {
723	jQuery.browser[ browserMatch.browser ] = true;
724	jQuery.browser.version = browserMatch.version;
725}
726
727// Deprecated, use jQuery.browser.webkit instead
728if ( jQuery.browser.webkit ) {
729	jQuery.browser.safari = true;
730}
731
732if ( indexOf ) {
733	jQuery.inArray = function( elem, array ) {
734		return indexOf.call( array, elem );
735	};
736}
737
738// All jQuery objects should point back to these
739rootjQuery = jQuery(document);
740
741// Cleanup functions for the document ready method
742if ( document.addEventListener ) {
743	DOMContentLoaded = function() {
744		document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
745		jQuery.ready();
746	};
747
748} else if ( document.attachEvent ) {
749	DOMContentLoaded = function() {
750		// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
751		if ( document.readyState === "complete" ) {
752			document.detachEvent( "onreadystatechange", DOMContentLoaded );
753			jQuery.ready();
754		}
755	};
756}
757
758// The DOM ready check for Internet Explorer
759function doScrollCheck() {
760	if ( jQuery.isReady ) {
761		return;
762	}
763
764	try {
765		// If IE is used, use the trick by Diego Perini
766		// http://javascript.nwbox.com/IEContentLoaded/
767		document.documentElement.doScroll("left");
768	} catch( error ) {
769		setTimeout( doScrollCheck, 1 );
770		return;
771	}
772
773	// and execute any waiting functions
774	jQuery.ready();
775}
776
777function evalScript( i, elem ) {
778	if ( elem.src ) {
779		jQuery.ajax({
780			url: elem.src,
781			async: false,
782			dataType: "script"
783		});
784	} else {
785		jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
786	}
787
788	if ( elem.parentNode ) {
789		elem.parentNode.removeChild( elem );
790	}
791}
792
793// Mutifunctional method to get and set values to a collection
794// The value/s can be optionally by executed if its a function
795function access( elems, key, value, exec, fn, pass ) {
796	var length = elems.length;
797
798	// Setting many attributes
799	if ( typeof key === "object" ) {
800		for ( var k in key ) {
801			access( elems, k, key[k], exec, fn, value );
802		}
803		return elems;
804	}
805
806	// Setting one attribute
807	if ( value !== undefined ) {
808		// Optionally, function values get executed if exec is true
809		exec = !pass && exec && jQuery.isFunction(value);
810
811		for ( var i = 0; i < length; i++ ) {
812			fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
813		}
814
815		return elems;
816	}
817
818	// Getting an attribute
819	return length ? fn( elems[0], key ) : undefined;
820}
821
822function now() {
823	return (new Date).getTime();
824}
825(function() {
826
827	jQuery.support = {};
828
829	var root = document.documentElement,
830		script = document.createElement("script"),
831		div = document.createElement("div"),
832		id = "script" + now();
833
834	div.style.display = "none";
835	div.innerHTML = "   <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
836
837	var all = div.getElementsByTagName("*"),
838		a = div.getElementsByTagName("a")[0];
839
840	// Can't get basic test support
841	if ( !all || !all.length || !a ) {
842		return;
843	}
844
845	jQuery.support = {
846		// IE strips leading whitespace when .innerHTML is used
847		leadingWhitespace: div.firstChild.nodeType === 3,
848
849		// Make sure that tbody elements aren't automatically inserted
850		// IE will insert them into empty tables
851		tbody: !div.getElementsByTagName("tbody").length,
852
853		// Make sure that link elements get serialized correctly by innerHTML
854		// This requires a wrapper element in IE
855		htmlSerialize: !!div.getElementsByTagName("link").length,
856
857		// Get the style information from getAttribute
858		// (IE uses .cssText insted)
859		style: /red/.test( a.getAttribute("style") ),
860
861		// Make sure that URLs aren't manipulated
862		// (IE normalizes it by default)
863		hrefNormalized: a.getAttribute("href") === "/a",
864
865		// Make sure that element opacity exists
866		// (IE uses filter instead)
867		// Use a regex to work around a WebKit issue. See #5145
868		opacity: /^0.55$/.test( a.style.opacity ),
869
870		// Verify style float existence
871		// (IE uses styleFloat instead of cssFloat)
872		cssFloat: !!a.style.cssFloat,
873
874		// Make sure that if no value is specified for a checkbox
875		// that it defaults to "on".
876		// (WebKit defaults to "" instead)
877		checkOn: div.getElementsByTagName("input")[0].value === "on",
878
879		// Make sure that a selected-by-default option has a working selected property.
880		// (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
881		optSelected: document.createElement("select").appendChild( document.createElement("option") ).selected,
882
883		parentNode: div.removeChild( div.appendChild( document.createElement("div") ) ).parentNode === null,
884
885		// Will be defined later
886		deleteExpando: true,
887		checkClone: false,
888		scriptEval: false,
889		noCloneEvent: true,
890		boxModel: null
891	};
892
893	script.type = "text/javascript";
894	try {
895		script.appendChild( document.createTextNode( "window." + id + "=1;" ) );
896	} catch(e) {}
897
898	root.insertBefore( script, root.firstChild );
899
900	// Make sure that the execution of code works by injecting a script
901	// tag with appendChild/createTextNode
902	// (IE doesn't support this, fails, and uses .text instead)
903	if ( window[ id ] ) {
904		jQuery.support.scriptEval = true;
905		delete window[ id ];
906	}
907
908	// Test to see if it's possible to delete an expando from an element
909	// Fails in Internet Explorer
910	try {
911		delete script.test;
912
913	} catch(e) {
914		jQuery.support.deleteExpando = false;
915	}
916
917	root.removeChild( script );
918
919	if ( div.attachEvent && div.fireEvent ) {
920		div.attachEvent("onclick", function click() {
921			// Cloning a node shouldn't copy over any
922			// bound event handlers (IE does this)
923			jQuery.support.noCloneEvent = false;
924			div.detachEvent("onclick", click);
925		});
926		div.cloneNode(true).fireEvent("onclick");
927	}
928
929	div = document.createElement("div");
930	div.innerHTML = "<input type='radio' name='radiotest' checked='checked'/>";
931
932	var fragment = document.createDocumentFragment();
933	fragment.appendChild( div.firstChild );
934
935	// WebKit doesn't clone checked state correctly in fragments
936	jQuery.support.checkClone = fragment.cloneNode(true).cloneNode(true).lastChild.checked;
937
938	// Figure out if the W3C box model works as expected
939	// document.body must exist before we can do this
940	jQuery(function() {
941		var div = document.createElement("div");
942		div.style.width = div.style.paddingLeft = "1px";
943
944		document.body.appendChild( div );
945		jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2;
946		document.body.removeChild( div ).style.display = 'none';
947
948		div = null;
949	});
950
951	// Technique from Juriy Zaytsev
952	// http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/
953	var eventSupported = function( eventName ) {
954		var el = document.createElement("div");
955		eventName = "on" + eventName;
956
957		var isSupported = (eventName in el);
958		if ( !isSupported ) {
959			el.setAttribute(eventName, "return;");
960			isSupported = typeof el[eventName] === "function";
961		}
962		el = null;
963
964		return isSupported;
965	};
966
967	jQuery.support.submitBubbles = eventSupported("submit");
968	jQuery.support.changeBubbles = eventSupported("change");
969
970	// release memory in IE
971	root = script = div = all = a = null;
972})();
973
974jQuery.props = {
975	"for": "htmlFor",
976	"class": "className",
977	readonly: "readOnly",
978	maxlength: "maxLength",
979	cellspacing: "cellSpacing",
980	rowspan: "rowSpan",
981	colspan: "colSpan",
982	tabindex: "tabIndex",
983	usemap: "useMap",
984	frameborder: "frameBorder"
985};
986var expando = "jQuery" + now(), uuid = 0, windowData = {};
987
988jQuery.extend({
989	cache: {},
990
991	expando:expando,
992
993	// The following elements throw uncatchable exceptions if you
994	// attempt to add expando properties to them.
995	noData: {
996		"embed": true,
997		"object": true,
998		"applet": true
999	},
1000
1001	data: function( elem, name, data ) {
1002		if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {
1003			return;
1004		}
1005
1006		elem = elem == window ?
1007			windowData :
1008			elem;
1009
1010		var id = elem[ expando ], cache = jQuery.cache, thisCache;
1011
1012		if ( !id && typeof name === "string" && data === undefined ) {
1013			return null;
1014		}
1015
1016		// Compute a unique ID for the element
1017		if ( !id ) {
1018			id = ++uuid;
1019		}
1020
1021		// Avoid generating a new cache unless none exists and we
1022		// want to manipulate it.
1023		if ( typeof name === "object" ) {
1024			elem[ expando ] = id;
1025			thisCache = cache[ id ] = jQuery.extend(true, {}, name);
1026
1027		} else if ( !cache[ id ] ) {
1028			elem[ expando ] = id;
1029			cache[ id ] = {};
1030		}
1031
1032		thisCache = cache[ id ];
1033
1034		// Prevent overriding the named cache with undefined values
1035		if ( data !== undefined ) {
1036			thisCache[ name ] = data;
1037		}
1038
1039		return typeof name === "string" ? thisCache[ name ] : thisCache;
1040	},
1041
1042	removeData: function( elem, name ) {
1043		if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {
1044			return;
1045		}
1046
1047		elem = elem == window ?
1048			windowData :
1049			elem;
1050
1051		var id = elem[ expando ], cache = jQuery.cache, thisCache = cache[ id ];
1052
1053		// If we want to remove a specific section of the element's data
1054		if ( name ) {
1055			if ( thisCache ) {
1056				// Remove the section of cache data
1057				delete thisCache[ name ];
1058
1059				// If we've removed all the data, remove the element's cache
1060				if ( jQuery.isEmptyObject(thisCache) ) {
1061					jQuery.removeData( elem );
1062				}
1063			}
1064
1065		// Otherwise, we want to remove all of the element's data
1066		} else {
1067			if ( jQuery.support.deleteExpando ) {
1068				delete elem[ jQuery.expando ];
1069
1070			} else if ( elem.removeAttribute ) {
1071				elem.removeAttribute( jQuery.expando );
1072			}
1073
1074			// Completely remove the data cache
1075			delete cache[ id ];
1076		}
1077	}
1078});
1079
1080jQuery.fn.extend({
1081	data: function( key, value ) {
1082		if ( typeof key === "undefined" && this.length ) {
1083			return jQuery.data( this[0] );
1084
1085		} else if ( typeof key === "object" ) {
1086			return this.each(function() {
1087				jQuery.data( this, key );
1088			});
1089		}
1090
1091		var parts = key.split(".");
1092		parts[1] = parts[1] ? "." + parts[1] : "";
1093
1094		if ( value === undefined ) {
1095			var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
1096
1097			if ( data === undefined && this.length ) {
1098				data = jQuery.data( this[0], key );
1099			}
1100			return data === undefined && parts[1] ?
1101				this.data( parts[0] ) :
1102				data;
1103		} else {
1104			return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function() {
1105				jQuery.data( this, key, value );
1106			});
1107		}
1108	},
1109
1110	removeData: function( key ) {
1111		return this.each(function() {
1112			jQuery.removeData( this, key );
1113		});
1114	}
1115});
1116jQuery.extend({
1117	queue: function( elem, type, data ) {
1118		if ( !elem ) {
1119			return;
1120		}
1121
1122		type = (type || "fx") + "queue";
1123		var q = jQuery.data( elem, type );
1124
1125		// Speed up dequeue by getting out quickly if this is just a lookup
1126		if ( !data ) {
1127			return q || [];
1128		}
1129
1130		if ( !q || jQuery.isArray(data) ) {
1131			q = jQuery.data( elem, type, jQuery.makeArray(data) );
1132
1133		} else {
1134			q.push( data );
1135		}
1136
1137		return q;
1138	},
1139
1140	dequeue: function( elem, type ) {
1141		type = type || "fx";
1142
1143		var queue = jQuery.queue( elem, type ), fn = queue.shift();
1144
1145		// If the fx queue is dequeued, always remove the progress sentinel
1146		if ( fn === "inprogress" ) {
1147			fn = queue.shift();
1148		}
1149
1150		if ( fn ) {
1151			// Add a progress sentinel to prevent the fx queue from being
1152			// automatically dequeued
1153			if ( type === "fx" ) {
1154				queue.unshift("inprogress");
1155			}
1156
1157			fn.call(elem, function() {
1158				jQuery.dequeue(elem, type);
1159			});
1160		}
1161	}
1162});
1163
1164jQuery.fn.extend({
1165	queue: function( type, data ) {
1166		if ( typeof type !== "string" ) {
1167			data = type;
1168			type = "fx";
1169		}
1170
1171		if ( data === undefined ) {
1172			return jQuery.queue( this[0], type );
1173		}
1174		return this.each(function( i, elem ) {
1175			var queue = jQuery.queue( this, type, data );
1176
1177			if ( type === "fx" && queue[0] !== "inprogress" ) {
1178				jQuery.dequeue( this, type );
1179			}
1180		});
1181	},
1182	dequeue: function( type ) {
1183		return this.each(function() {
1184			jQuery.dequeue( this, type );
1185		});
1186	},
1187
1188	// Based off of the plugin by Clint Helfers, with permission.
1189	// http://blindsignals.com/index.php/2009/07/jquery-delay/
1190	delay: function( time, type ) {
1191		time = jQuery.fx ? jQuery.fx.speeds[time] || time : time;
1192		type = type || "fx";
1193
1194		return this.queue( type, function() {
1195			var elem = this;
1196			setTimeout(function() {
1197				jQuery.dequeue( elem, type );
1198			}, time );
1199		});
1200	},
1201
1202	clearQueue: function( type ) {
1203		return this.queue( type || "fx", [] );
1204	}
1205});
1206var rclass = /[\n\t]/g,
1207	rspace = /\s+/,
1208	rreturn = /\r/g,
1209	rspecialurl = /href|src|style/,
1210	rtype = /(button|input)/i,
1211	rfocusable = /(button|input|object|select|textarea)/i,
1212	rclickable = /^(a|area)$/i,
1213	rradiocheck = /radio|checkbox/;
1214
1215jQuery.fn.extend({
1216	attr: function( name, value ) {
1217		return access( this, name, value, true, jQuery.attr );
1218	},
1219
1220	removeAttr: function( name, fn ) {
1221		return this.each(function(){
1222			jQuery.attr( this, name, "" );
1223			if ( this.nodeType === 1 ) {
1224				this.removeAttribute( name );
1225			}
1226		});
1227	},
1228
1229	addClass: function( value ) {
1230		if ( jQuery.isFunction(value) ) {
1231			return this.each(function(i) {
1232				var self = jQuery(this);
1233				self.addClass( value.call(this, i, self.attr("class")) );
1234			});
1235		}
1236
1237		if ( value && typeof value === "string" ) {
1238			var classNames = (value || "").split( rspace );
1239
1240			for ( var i = 0, l = this.length; i < l; i++ ) {
1241				var elem = this[i];
1242
1243				if ( elem.nodeType === 1 ) {
1244					if ( !elem.className ) {
1245						elem.className = value;
1246
1247					} else {
1248						var className = " " + elem.className + " ", setClass = elem.className;
1249						for ( var c = 0, cl = classNames.length; c < cl; c++ ) {
1250							if ( className.indexOf( " " + classNames[c] + " " ) < 0 ) {
1251								setClass += " " + classNames[c];
1252							}
1253						}
1254						elem.className = jQuery.trim( setClass );
1255					}
1256				}
1257			}
1258		}
1259
1260		return this;
1261	},
1262
1263	removeClass: function( value ) {
1264		if ( jQuery.isFunction(value) ) {
1265			return this.each(function(i) {
1266				var self = jQuery(this);
1267				self.removeClass( value.call(this, i, self.attr("class")) );
1268			});
1269		}
1270
1271		if ( (value && typeof value === "string") || value === undefined ) {
1272			var classNames = (value || "").split(rspace);
1273
1274			for ( var i = 0, l = this.length; i < l; i++ ) {
1275				var elem = this[i];
1276
1277				if ( elem.nodeType === 1 && elem.className ) {
1278					if ( value ) {
1279						var className = (" " + elem.className + " ").replace(rclass, " ");
1280						for ( var c = 0, cl = classNames.length; c < cl; c++ ) {
1281							className = className.replace(" " + classNames[c] + " ", " ");
1282						}
1283						elem.className = jQuery.trim( className );
1284
1285					} else {
1286						elem.className = "";
1287					}
1288				}
1289			}
1290		}
1291
1292		return this;
1293	},
1294
1295	toggleClass: function( value, stateVal ) {
1296		var type = typeof value, isBool = typeof stateVal === "boolean";
1297
1298		if ( jQuery.isFunction( value ) ) {
1299			return this.each(function(i) {
1300				var self = jQuery(this);
1301				self.toggleClass( value.call(this, i, self.attr("class"), stateVal), stateVal );
1302			});
1303		}
1304
1305		return this.each(function() {
1306			if ( type === "string" ) {
1307				// toggle individual class names
1308				var className, i = 0, self = jQuery(this),
1309					state = stateVal,
1310					classNames = value.split( rspace );
1311
1312				while ( (className = classNames[ i++ ]) ) {
1313					// check each className given, space seperated list
1314					state = isBool ? state : !self.hasClass( className );
1315					self[ state ? "addClass" : "removeClass" ]( className );
1316				}
1317
1318			} else if ( type === "undefined" || type === "boolean" ) {
1319				if ( this.className ) {
1320					// store className if set
1321					jQuery.data( this, "__className__", this.className );
1322				}
1323
1324				// toggle whole className
1325				this.className = this.className || value === false ? "" : jQuery.data( this, "__className__" ) || "";
1326			}
1327		});
1328	},
1329
1330	hasClass: function( selector ) {
1331		var className = " " + selector + " ";
1332		for ( var i = 0, l = this.length; i < l; i++ ) {
1333			if ( (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) {
1334				return true;
1335			}
1336		}
1337
1338		return false;
1339	},
1340
1341	val: function( value ) {
1342		if ( value === undefined ) {
1343			var elem = this[0];
1344
1345			if ( elem ) {
1346				if ( jQuery.nodeName( elem, "option" ) ) {
1347					return (elem.attributes.value || {}).specified ? elem.value : elem.text;
1348				}
1349
1350				// We need to handle select boxes special
1351				if ( jQuery.nodeName( elem, "select" ) ) {
1352					var index = elem.selectedIndex,
1353						values = [],
1354						options = elem.options,
1355						one = elem.type === "select-one";
1356
1357					// Nothing was selected
1358					if ( index < 0 ) {
1359						return null;
1360					}
1361
1362					// Loop through all the selected options
1363					for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
1364						var option = options[ i ];
1365
1366						if ( option.selected ) {
1367							// Get the specifc value for the option
1368							value = jQuery(option).val();
1369
1370							// We don't need an array for one selects
1371							if ( one ) {
1372								return value;
1373							}
1374
1375							// Multi-Selects return an array
1376							values.push( value );
1377						}
1378					}
1379
1380					return values;
1381				}
1382
1383				// Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
1384				if ( rradiocheck.test( elem.type ) && !jQuery.support.checkOn ) {
1385					return elem.getAttribute("value") === null ? "on" : elem.value;
1386				}
1387
1388
1389				// Everything else, we just grab the value
1390				return (elem.value || "").replace(rreturn, "");
1391
1392			}
1393
1394			return undefined;
1395		}
1396
1397		var isFunction = jQuery.isFunction(value);
1398
1399		return this.each(function(i) {
1400			var self = jQuery(this), val = value;
1401
1402			if ( this.nodeType !== 1 ) {
1403				return;
1404			}
1405
1406			if ( isFunction ) {
1407				val = value.call(this, i, self.val());
1408			}
1409
1410			// Typecast each time if the value is a Function and the appended
1411			// value is therefore different each time.
1412			if ( typeof val === "number" ) {
1413				val += "";
1414			}
1415
1416			if ( jQuery.isArray(val) && rradiocheck.test( this.type ) ) {
1417				this.checked = jQuery.inArray( self.val(), val ) >= 0;
1418
1419			} else if ( jQuery.nodeName( this, "select" ) ) {
1420				var values = jQuery.makeArray(val);
1421
1422				jQuery( "option", this ).each(function() {
1423					this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
1424				});
1425
1426				if ( !values.length ) {
1427					this.selectedIndex = -1;
1428				}
1429
1430			} else {
1431				this.value = val;
1432			}
1433		});
1434	}
1435});
1436
1437jQuery.extend({
1438	attrFn: {
1439		val: true,
1440		css: true,
1441		html: true,
1442		text: true,
1443		data: true,
1444		width: true,
1445		height: true,
1446		offset: true
1447	},
1448
1449	attr: function( elem, name, value, pass ) {
1450		// don't set attributes on text and comment nodes
1451		if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
1452			return undefined;
1453		}
1454
1455		if ( pass && name in jQuery.attrFn ) {
1456			return jQuery(elem)[name](value);
1457		}
1458
1459		var notxml = elem.nodeType !== 1 || !jQuery.isXMLDoc( elem ),
1460			// Whether we are setting (or getting)
1461			set = value !== undefined;
1462
1463		// Try to normalize/fix the name
1464		name = notxml && jQuery.props[ name ] || name;
1465
1466		// Only do all the following if this is a node (faster for style)
1467		if ( elem.nodeType === 1 ) {
1468			// These attributes require special treatment
1469			var special = rspecialurl.test( name );
1470
1471			// Safari mis-reports the default selected property of an option
1472			// Accessing the parent's selectedIndex property fixes it
1473			if ( name === "selected" && !jQuery.support.optSelected ) {
1474				var parent = elem.parentNode;
1475				if ( parent ) {
1476					parent.selectedIndex;
1477
1478					// Make sure that it also works with optgroups, see #5701
1479					if ( parent.parentNode ) {
1480						parent.parentNode.selectedIndex;
1481					}
1482				}
1483			}
1484
1485			// If applicable, access the attribute via the DOM 0 way
1486			if ( name in elem && notxml && !special ) {
1487				if ( set ) {
1488					// We can't allow the type property to be changed (since it causes problems in IE)
1489					if ( name === "type" && rtype.test( elem.nodeName ) && elem.parentNode ) {
1490						jQuery.error( "type property can't be changed" );
1491					}
1492
1493					elem[ name ] = value;
1494				}
1495
1496				// browsers index elements by id/name on forms, give priority to attributes.
1497				if ( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) ) {
1498					return elem.getAttributeNode( name ).nodeValue;
1499				}
1500
1501				// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
1502				// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
1503				if ( name === "tabIndex" ) {
1504					var attributeNode = elem.getAttributeNode( "tabIndex" );
1505
1506					return attributeNode && attributeNode.specified ?
1507						attributeNode.value :
1508						rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
1509							0 :
1510							undefined;
1511				}
1512
1513				return elem[ name ];
1514			}
1515
1516			if ( !jQuery.support.style && notxml && name === "style" ) {
1517				if ( set ) {
1518					elem.style.cssText = "" + value;
1519				}
1520
1521				return elem.style.cssText;
1522			}
1523
1524			if ( set ) {
1525				// convert the value to a string (all browsers do this but IE) see #1070
1526				elem.setAttribute( name, "" + value );
1527			}
1528
1529			var attr = !jQuery.support.hrefNormalized && notxml && special ?
1530					// Some attributes require a special call on IE
1531					elem.getAttribute( name, 2 ) :
1532					elem.getAttribute( name );
1533
1534			// Non-existent attributes return null, we normalize to undefined
1535			return attr === null ? undefined : attr;
1536		}
1537
1538		// elem is actually elem.style ... set the style
1539		// Using attr for specific style information is now deprecated. Use style instead.
1540		return jQuery.style( elem, name, value );
1541	}
1542});
1543var rnamespaces = /\.(.*)$/,
1544	fcleanup = function( nm ) {
1545		return nm.replace(/[^\w\s\.\|`]/g, function( ch ) {
1546			return "\\" + ch;
1547		});
1548	};
1549
1550/*
1551 * A number of helper functions used for managing events.
1552 * Many of the ideas behind this code originated from
1553 * Dean Edwards' addEvent library.
1554 */
1555jQuery.event = {
1556
1557	// Bind an event to an element
1558	// Original by Dean Edwards
1559	add: function( elem, types, handler, data ) {
1560		if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
1561			return;
1562		}
1563
1564		// For whatever reason, IE has trouble passing the window object
1565		// around, causing it to be cloned in the process
1566		if ( elem.setInterval && ( elem !== window && !elem.frameElement ) ) {
1567			elem = window;
1568		}
1569
1570		var handleObjIn, handleObj;
1571
1572		if ( handler.handler ) {
1573			handleObjIn = handler;
1574			handler = handleObjIn.handler;
1575		}
1576
1577		// Make sure that the function being executed has a unique ID
1578		if ( !handler.guid ) {
1579			handler.guid = jQuery.guid++;
1580		}
1581
1582		// Init the element's event structure
1583		var elemData = jQuery.data( elem );
1584
1585		// If no elemData is found then we must be trying to bind to one of the
1586		// banned noData elements
1587		if ( !elemData ) {
1588			return;
1589		}
1590
1591		var events = elemData.events = elemData.events || {},
1592			eventHandle = elemData.handle, eventHandle;
1593
1594		if ( !eventHandle ) {
1595			elemData.handle = eventHandle = function() {
1596				// Handle the second event of a trigger and when
1597				// an event is called after a page has unloaded
1598				return typeof jQuery !== "undefined" && !jQuery.event.triggered ?
1599					jQuery.event.handle.apply( eventHandle.elem, arguments ) :
1600					undefined;
1601			};
1602		}
1603
1604		// Add elem as a property of the handle function
1605		// This is to prevent a memory leak with non-native events in IE.
1606		eventHandle.elem = elem;
1607
1608		// Handle multiple events separated by a space
1609		// jQuery(...).bind("mouseover mouseout", fn);
1610		types = types.split(" ");
1611
1612		var type, i = 0, namespaces;
1613
1614		while ( (type = types[ i++ ]) ) {
1615			handleObj = handleObjIn ?
1616				jQuery.extend({}, handleObjIn) :
1617				{ handler: handler, data: data };
1618
1619			// Namespaced event handlers
1620			if ( type.indexOf(".") > -1 ) {
1621				namespaces = type.split(".");
1622				type = namespaces.shift();
1623				handleObj.namespace = namespaces.slice(0).sort().join(".");
1624
1625			} else {
1626				namespaces = [];
1627				handleObj.namespace = "";
1628			}
1629
1630			handleObj.type = type;
1631			handleObj.guid = handler.guid;
1632
1633			// Get the current list of functions bound to this event
1634			var handlers = events[ type ],
1635				special = jQuery.event.special[ type ] || {};
1636
1637			// Init the event handler queue
1638			if ( !handlers ) {
1639				handlers = events[ type ] = [];
1640
1641				// Check for a special event handler
1642				// Only use addEventListener/attachEvent if the special
1643				// events handler returns false
1644				if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
1645					// Bind the global event handler to the element
1646					if ( elem.addEventListener ) {
1647						elem.addEventListener( type, eventHandle, false );
1648
1649					} else if ( elem.attachEvent ) {
1650						elem.attachEvent( "on" + type, eventHandle );
1651					}
1652				}
1653			}
1654
1655			if ( special.add ) {
1656				special.add.call( elem, handleObj );
1657
1658				if ( !handleObj.handler.guid ) {
1659					handleObj.handler.guid = handler.guid;
1660				}
1661			}
1662
1663			// Add the function to the element's handler list
1664			handlers.push( handleObj );
1665
1666			// Keep track of which events have been used, for global triggering
1667			jQuery.event.global[ type ] = true;
1668		}
1669
1670		// Nullify elem to prevent memory leaks in IE
1671		elem = null;
1672	},
1673
1674	global: {},
1675
1676	// Detach an event or set of events from an element
1677	remove: function( elem, types, handler, pos ) {
1678		// don't do events on text and comment nodes
1679		if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
1680			return;
1681		}
1682
1683		var ret, type, fn, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType,
1684			elemData = jQuery.data( elem ),
1685			events = elemData && elemData.events;
1686
1687		if ( !elemData || !events ) {
1688			return;
1689		}
1690
1691		// types is actually an event object here
1692		if ( types && types.type ) {
1693			handler = types.handler;
1694			types = types.type;
1695		}
1696
1697		// Unbind all events for the element
1698		if ( !types || typeof types === "string" && types.charAt(0) === "." ) {
1699			types = types || "";
1700
1701			for ( type in events ) {
1702				jQuery.event.remove( elem, type + types );
1703			}
1704
1705			return;
1706		}
1707
1708		// Handle multiple events separated by a space
1709		// jQuery(...).unbind("mouseover mouseout", fn);
1710		types = types.split(" ");
1711
1712		while ( (type = types[ i++ ]) ) {
1713			origType = type;
1714			handleObj = null;
1715			all = type.indexOf(".") < 0;
1716			namespaces = [];
1717
1718			if ( !all ) {
1719				// Namespaced event handlers
1720				namespaces = type.split(".");
1721				type = namespaces.shift();
1722
1723				namespace = new RegExp("(^|\\.)" +
1724					jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)")
1725			}
1726
1727			eventType = events[ type ];
1728
1729			if ( !eventType ) {
1730				continue;
1731			}
1732
1733			if ( !handler ) {
1734				for ( var j = 0; j < eventType.length; j++ ) {
1735					handleObj = eventType[ j ];
1736
1737					if ( all || namespace.test( handleObj.namespace ) ) {
1738						jQuery.event.remove( elem, origType, handleObj.handler, j );
1739						eventType.splice( j--, 1 );
1740					}
1741				}
1742
1743				continue;
1744			}
1745
1746			special = jQuery.event.special[ type ] || {};
1747
1748			for ( var j = pos || 0; j < eventType.length; j++ ) {
1749				handleObj = eventType[ j ];
1750
1751				if ( handler.guid === handleObj.guid ) {
1752					// remove the given handler for the given type
1753					if ( all || namespace.test( handleObj.namespace ) ) {
1754						if ( pos == null ) {
1755							eventType.splice( j--, 1 );
1756						}
1757
1758						if ( special.remove ) {
1759							special.remove.call( elem, handleObj );
1760						}
1761					}
1762
1763					if ( pos != null ) {
1764						break;
1765					}
1766				}
1767			}
1768
1769			// remove generic event handler if no more handlers exist
1770			if ( eventType.length === 0 || pos != null && eventType.length === 1 ) {
1771				if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
1772					removeEvent( elem, type, elemData.handle );
1773				}
1774
1775				ret = null;
1776				delete events[ type ];
1777			}
1778		}
1779
1780		// Remove the expando if it's no longer used
1781		if ( jQuery.isEmptyObject( events ) ) {
1782			var handle = elemData.handle;
1783			if ( handle ) {
1784				handle.elem = null;
1785			}
1786
1787			delete elemData.events;
1788			delete elemData.handle;
1789
1790			if ( jQuery.isEmptyObject( elemData ) ) {
1791				jQuery.removeData( elem );
1792			}
1793		}
1794	},
1795
1796	// bubbling is internal
1797	trigger: function( event, data, elem /*, bubbling */ ) {
1798		// Event object or event type
1799		var type = event.type || event,
1800			bubbling = arguments[3];
1801
1802		if ( !bubbling ) {
1803			event = typeof event === "object" ?
1804				// jQuery.Event object
1805				event[expando] ? event :
1806				// Object literal
1807				jQuery.extend( jQuery.Event(type), event ) :
1808				// Just the event type (string)
1809				jQuery.Event(type);
1810
1811			if ( type.indexOf("!") >= 0 ) {
1812				event.type = type = type.slice(0, -1);
1813				event.exclusive = true;
1814			}
1815
1816			// Handle a global trigger
1817			if ( !elem ) {
1818				// Don't bubble custom events when global (to avoid too much overhead)
1819				event.stopPropagation();
1820
1821				// Only trigger if we've ever bound an event for it
1822				if ( jQuery.event.global[ type ] ) {
1823					jQuery.each( jQuery.cache, function() {
1824						if ( this.events && this.events[type] ) {
1825							jQuery.event.trigger( event, data, this.handle.elem );
1826						}
1827					});
1828				}
1829			}
1830
1831			// Handle triggering a single element
1832
1833			// don't do events on text and comment nodes
1834			if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
1835				return undefined;
1836			}
1837
1838			// Clean up in case it is reused
1839			event.result = undefined;
1840			event.target = elem;
1841
1842			// Clone the incoming data, if any
1843			data = jQuery.makeArray( data );
1844			data.unshift( event );
1845		}
1846
1847		event.currentTarget = elem;
1848
1849		// Trigger the event, it is assumed that "handle" is a function
1850		var handle = jQuery.data( elem, "handle" );
1851		if ( handle ) {
1852			handle.apply( elem, data );
1853		}
1854
1855		var parent = elem.parentNode || elem.ownerDocument;
1856
1857		// Trigger an inline bound script
1858		try {
1859			if ( !(elem && elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()]) ) {
1860				if ( elem[ "on" + type ] && elem[ "on" + type ].apply( elem, data ) === false ) {
1861					event.result = false;
1862				}
1863			}
1864
1865		// prevent IE from throwing an error for some elements with some event types, see #3533
1866		} catch (e) {}
1867
1868		if ( !event.isPropagationStopped() && parent ) {
1869			jQuery.event.trigger( event, data, parent, true );
1870
1871		} else if ( !event.isDefaultPrevented() ) {
1872			var target = event.target, old,
1873				isClick = jQuery.nodeName(target, "a") && type === "click",
1874				special = jQuery.event.special[ type ] || {};
1875
1876			if ( (!special._default || special._default.call( elem, event ) === false) &&
1877				!isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) {
1878
1879				try {
1880					if ( target[ type ] ) {
1881						// Make sure that we don't accidentally re-trigger the onFOO events
1882						old = target[ "on" + type ];
1883
1884						if ( old ) {
1885							target[ "on" + type ] = null;
1886						}
1887
1888						jQuery.event.triggered = true;
1889						target[ type ]();
1890					}
1891
1892				// prevent IE from throwing an error for some elements with some event types, see #3533
1893				} catch (e) {}
1894
1895				if ( old ) {
1896					target[ "on" + type ] = old;
1897				}
1898
1899				jQuery.event.triggered = false;
1900			}
1901		}
1902	},
1903
1904	handle: function( event ) {
1905		var all, handlers, namespaces, namespace, events;
1906
1907		event = arguments[0] = jQuery.event.fix( event || window.event );
1908		event.currentTarget = this;
1909
1910		// Namespaced event handlers
1911		all = event.type.indexOf(".") < 0 && !event.exclusive;
1912
1913		if ( !all ) {
1914			namespaces = event.type.split(".");
1915			event.type = namespaces.shift();
1916			namespace = new RegExp("(^|\\.)" + namespaces.slice(0).sort().join("\\.(?:.*\\.)?") + "(\\.|$)");
1917		}
1918
1919		var events = jQuery.data(this, "events"), handlers = events[ event.type ];
1920
1921		if ( events && handlers ) {
1922			// Clone the handlers to prevent manipulation
1923			handlers = handlers.slice(0);
1924
1925			for ( var j = 0, l = handlers.length; j < l; j++ ) {
1926				var handleObj = handlers[ j ];
1927
1928				// Filter the functions by class
1929				if ( all || namespace.test( handleObj.namespace ) ) {
1930					// Pass in a reference to the handler function itself
1931					// So that we can later remove it
1932					event.handler = handleObj.handler;
1933					event.data = handleObj.data;
1934					event.handleObj = handleObj;
1935
1936					var ret = handleObj.handler.apply( this, arguments );
1937
1938					if ( ret !== undefined ) {
1939						event.result = ret;
1940						if ( ret === false ) {
1941							event.preventDefault();
1942							event.stopPropagation();
1943						}
1944					}
1945
1946					if ( event.isImmediatePropagationStopped() ) {
1947						break;
1948					}
1949				}
1950			}
1951		}
1952
1953		return event.result;
1954	},
1955
1956	props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
1957
1958	fix: function( event ) {
1959		if ( event[ expando ] ) {
1960			return event;
1961		}
1962
1963		// store a copy of the original event object
1964		// and "clone" to set read-only properties
1965		var originalEvent = event;
1966		event = jQuery.Event( originalEvent );
1967
1968		for ( var i = this.props.length, prop; i; ) {
1969			prop = this.props[ --i ];
1970			event[ prop ] = originalEvent[ prop ];
1971		}
1972
1973		// Fix target property, if necessary
1974		if ( !event.target ) {
1975			event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
1976		}
1977
1978		// check if target is a textnode (safari)
1979		if ( event.target.nodeType === 3 ) {
1980			event.target = event.target.parentNode;
1981		}
1982
1983		// Add relatedTarget, if necessary
1984		if ( !event.relatedTarget && event.fromElement ) {
1985			event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement;
1986		}
1987
1988		// Calculate pageX/Y if missing and clientX/Y available
1989		if ( event.pageX == null && event.clientX != null ) {
1990			var doc = document.documentElement, body = document.body;
1991			event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
1992			event.pageY = event.clientY + (doc && doc.scrollTop  || body && body.scrollTop  || 0) - (doc && doc.clientTop  || body && body.clientTop  || 0);
1993		}
1994
1995		// Add which for key events
1996		if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) ) {
1997			event.which = event.charCode || event.keyCode;
1998		}
1999
2000		// Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
2001		if ( !event.metaKey && event.ctrlKey ) {
2002			event.metaKey = event.ctrlKey;
2003		}
2004
2005		// Add which for click: 1 === left; 2 === middle; 3 === right
2006		// Note: button is not normalized, so don't use it
2007		if ( !event.which && event.button !== undefined ) {
2008			event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
2009		}
2010
2011		return event;
2012	},
2013
2014	// Deprecated, use jQuery.guid instead
2015	guid: 1E8,
2016
2017	// Deprecated, use jQuery.proxy instead
2018	proxy: jQuery.proxy,
2019
2020	special: {
2021		ready: {
2022			// Make sure the ready event is setup
2023			setup: jQuery.bindReady,
2024			teardown: jQuery.noop
2025		},
2026
2027		live: {
2028			add: function( handleObj ) {
2029				jQuery.event.add( this, handleObj.origType, jQuery.extend({}, handleObj, {handler: liveHandler}) );
2030			},
2031
2032			remove: function( handleObj ) {
2033				var remove = true,
2034					type = handleObj.origType.replace(rnamespaces, "");
2035
2036				jQuery.each( jQuery.data(this, "events").live || [], function() {
2037					if ( type === this.origType.replace(rnamespaces, "") ) {
2038						remove = false;
2039						return false;
2040					}
2041				});
2042
2043				if ( remove ) {
2044					jQuery.event.remove( this, handleObj.origType, liveHandler );
2045				}
2046			}
2047
2048		},
2049
2050		beforeunload: {
2051			setup: function( data, namespaces, eventHandle ) {
2052				// We only want to do this special case on windows
2053				if ( this.setInterval ) {
2054					this.onbeforeunload = eventHandle;
2055				}
2056
2057				return false;
2058			},
2059			teardown: function( namespaces, eventHandle ) {
2060				if ( this.onbeforeunload === eventHandle ) {
2061					this.onbeforeunload = null;
2062				}
2063			}
2064		}
2065	}
2066};
2067
2068var removeEvent = document.removeEventListener ?
2069	function( elem, type, handle ) {
2070		elem.removeEventListener( type, handle, false );
2071	} :
2072	function( elem, type, handle ) {
2073		elem.detachEvent( "on" + type, handle );
2074	};
2075
2076jQuery.Event = function( src ) {
2077	// Allow instantiation without the 'new' keyword
2078	if ( !this.preventDefault ) {
2079		return new jQuery.Event( src );
2080	}
2081
2082	// Event object
2083	if ( src && src.type ) {
2084		this.originalEvent = src;
2085		this.type = src.type;
2086	// Event type
2087	} else {
2088		this.type = src;
2089	}
2090
2091	// timeStamp is buggy for some events on Firefox(#3843)
2092	// So we won't rely on the native value
2093	this.timeStamp = now();
2094
2095	// Mark it as fixed
2096	this[ expando ] = true;
2097};
2098
2099function returnFalse() {
2100	return false;
2101}
2102function returnTrue() {
2103	return true;
2104}
2105
2106// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
2107// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
2108jQuery.Event.prototype = {
2109	preventDefault: function() {
2110		this.isDefaultPrevented = returnTrue;
2111
2112		var e = this.originalEvent;
2113		if ( !e ) {
2114			return;
2115		}
2116
2117		// if preventDefault exists run it on the original event
2118		if ( e.preventDefault ) {
2119			e.preventDefault();
2120		}
2121		// otherwise set the returnValue property of the original event to false (IE)
2122		e.returnValue = false;
2123	},
2124	stopPropagation: function() {
2125		this.isPropagationStopped = returnTrue;
2126
2127		var e = this.originalEvent;
2128		if ( !e ) {
2129			return;
2130		}
2131		// if stopPropagation exists run it on the original event
2132		if ( e.stopPropagation ) {
2133			e.stopPropagation();
2134		}
2135		// otherwise set the cancelBubble property of the original event to true (IE)
2136		e.cancelBubble = true;
2137	},
2138	stopImmediatePropagation: function() {
2139		this.isImmediatePropagationStopped = returnTrue;
2140		this.stopPropagation();
2141	},
2142	isDefaultPrevented: returnFalse,
2143	isPropagationStopped: returnFalse,
2144	isImmediatePropagationStopped: returnFalse
2145};
2146
2147// Checks if an event happened on an element within another element
2148// Used in jQuery.event.special.mouseenter and mouseleave handlers
2149var withinElement = function( event ) {
2150	// Check if mouse(over|out) are still within the same parent element
2151	var parent = event.relatedTarget;
2152
2153	// Firefox sometimes assigns relatedTarget a XUL element
2154	// which we cannot access the parentNode property of
2155	try {
2156		// Traverse up the tree
2157		while ( parent && parent !== this ) {
2158			parent = parent.parentNode;
2159		}
2160
2161		if ( parent !== this ) {
2162			// set the correct event type
2163			event.type = event.data;
2164
2165			// handle event if we actually just moused on to a non sub-element
2166			jQuery.event.handle.apply( this, arguments );
2167		}
2168
2169	// assuming we've left the element since we most likely mousedover a xul element
2170	} catch(e) { }
2171},
2172
2173// In case of event delegation, we only need to rename the event.type,
2174// liveHandler will take care of the rest.
2175delegate = function( event ) {
2176	event.type = event.data;
2177	jQuery.event.handle.apply( this, arguments );
2178};
2179
2180// Create mouseenter and mouseleave events
2181jQuery.each({
2182	mouseenter: "mouseover",
2183	mouseleave: "mouseout"
2184}, function( orig, fix ) {
2185	jQuery.event.special[ orig ] = {
2186		setup: function( data ) {
2187			jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig );
2188		},
2189		teardown: function( data ) {
2190			jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement );
2191		}
2192	};
2193});
2194
2195// submit delegation
2196if ( !jQuery.support.submitBubbles ) {
2197
2198	jQuery.event.special.submit = {
2199		setup: function( data, namespaces ) {
2200			if ( this.nodeName.toLowerCase() !== "form" ) {
2201				jQuery.event.add(this, "click.specialSubmit", function( e ) {
2202					var elem = e.target, type = elem.type;
2203
2204					if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) {
2205						return trigger( "submit", this, arguments );
2206					}
2207				});
2208
2209				jQuery.event.add(this, "keypress.specialSubmit", function( e ) {
2210					var elem = e.target, type = elem.type;
2211
2212					if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) {
2213						return trigger( "submit", this, arguments );
2214					}
2215				});
2216
2217			} else {
2218				return false;
2219			}
2220		},
2221
2222		teardown: function( namespaces ) {
2223			jQuery.event.remove( this, ".specialSubmit" );
2224		}
2225	};
2226
2227}
2228
2229// change delegation, happens here so we have bind.
2230if ( !jQuery.support.changeBubbles ) {
2231
2232	var formElems = /textarea|input|select/i,
2233
2234	changeFilters,
2235
2236	getVal = function( elem ) {
2237		var type = elem.type, val = elem.value;
2238
2239		if ( type === "radio" || type === "checkbox" ) {
2240			val = elem.checked;
2241
2242		} else if ( type === "select-multiple" ) {
2243			val = elem.selectedIndex > -1 ?
2244				jQuery.map( elem.options, function( elem ) {
2245					return elem.selected;
2246				}).join("-") :
2247				"";
2248
2249		} else if ( elem.nodeName.toLowerCase() === "select" ) {
2250			val = elem.selectedIndex;
2251		}
2252
2253		return val;
2254	},
2255
2256	testChange = function testChange( e ) {
2257		var elem = e.target, data, val;
2258
2259		if ( !formElems.test( elem.nodeName ) || elem.readOnly ) {
2260			return;
2261		}
2262
2263		data = jQuery.data( elem, "_change_data" );
2264		val = getVal(elem);
2265
2266		// the current data will be also retrieved by beforeactivate
2267		if ( e.type !== "focusout" || elem.type !== "radio" ) {
2268			jQuery.data( elem, "_change_data", val );
2269		}
2270
2271		if ( data === undefined || val === data ) {
2272			return;
2273		}
2274
2275		if ( data != null || val ) {
2276			e.type = "change";
2277			return jQuery.event.trigger( e, arguments[1], elem );
2278		}
2279	};
2280
2281	jQuery.event.special.change = {
2282		filters: {
2283			focusout: testChange,
2284
2285			click: function( e ) {
2286				var elem = e.target, type = elem.type;
2287
2288				if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) {
2289					return testChange.call( this, e );
2290				}
2291			},
2292
2293			// Change has to be called before submit
2294			// Keydown will be called before keypress, which is used in submit-event delegation
2295			keydown: function( e ) {
2296				var elem = e.target, type = elem.type;
2297
2298				if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") ||
2299					(e.keyCode === 32 && (type === "checkbox" || type === "radio")) ||
2300					type === "select-multiple" ) {
2301					return testChange.call( this, e );
2302				}
2303			},
2304
2305			// Beforeactivate happens also before the previous element is blurred
2306			// with this event you can't trigger a change event, but you can store
2307			// information/focus[in] is not needed anymore
2308			beforeactivate: function( e ) {
2309				var elem = e.target;
2310				jQuery.data( elem, "_change_data", getVal(elem) );
2311			}
2312		},
2313
2314		setup: function( data, namespaces ) {
2315			if ( this.type === "file" ) {
2316				return false;
2317			}
2318
2319			for ( var type in changeFilters ) {
2320				jQuery.event.add( this, type + ".specialChange", changeFilters[type] );
2321			}
2322
2323			return formElems.test( this.nodeName );
2324		},
2325
2326		teardown: function( namespaces ) {
2327			jQuery.event.remove( this, ".specialChange" );
2328
2329			return formElems.test( this.nodeName );
2330		}
2331	};
2332
2333	changeFilters = jQuery.event.special.change.filters;
2334}
2335
2336function trigger( type, elem, args ) {
2337	args[0].type = type;
2338	return jQuery.event.handle.apply( elem, args );
2339}
2340
2341// Create "bubbling" focus and blur events
2342if ( document.addEventListener ) {
2343	jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
2344		jQuery.event.special[ fix ] = {
2345			setup: function() {
2346				this.addEventListener( orig, handler, true );
2347			},
2348			teardown: function() {
2349				this.removeEventListener( orig, handler, true );
2350			}
2351		};
2352
2353		function handler( e ) {
2354			e = jQuery.event.fix( e );
2355			e.type = fix;
2356			return jQuery.event.handle.call( this, e );
2357		}
2358	});
2359}
2360
2361jQuery.each(["bind", "one"], function( i, name ) {
2362	jQuery.fn[ name ] = function( type, data, fn ) {
2363		// Handle object literals
2364		if ( typeof type === "object" ) {
2365			for ( var key in type ) {
2366				this[ name ](key, data, type[key], fn);
2367			}
2368			return this;
2369		}
2370
2371		if ( jQuery.isFunction( data ) ) {
2372			fn = data;
2373			data = undefined;
2374		}
2375
2376		var handler = name === "one" ? jQuery.proxy( fn, function( event ) {
2377			jQuery( this ).unbind( event, handler );
2378			return fn.apply( this, arguments );
2379		}) : fn;
2380
2381		if ( type === "unload" && name !== "one" ) {
2382			this.one( type, data, fn );
2383
2384		} else {
2385			for ( var i = 0, l = this.length; i < l; i++ ) {
2386				jQuery.event.add( this[i], type, handler, data );
2387			}
2388		}
2389
2390		return this;
2391	};
2392});
2393
2394jQuery.fn.extend({
2395	unbind: function( type, fn ) {
2396		// Handle object literals
2397		if ( typeof type === "object" && !type.preventDefault ) {
2398			for ( var key in type ) {
2399				this.unbind(key, type[key]);
2400			}
2401
2402		} else {
2403			for ( var i = 0, l = this.length; i < l; i++ ) {
2404				jQuery.event.remove( this[i], type, fn );
2405			}
2406		}
2407
2408		return this;
2409	},
2410
2411	delegate: function( selector, types, data, fn ) {
2412		return this.live( types, data, fn, selector );
2413	},
2414
2415	undelegate: function( selector, types, fn ) {
2416		if ( arguments.length === 0 ) {
2417				return this.unbind( "live" );
2418
2419		} else {
2420			return this.die( types, null, fn, selector );
2421		}
2422	},
2423
2424	trigger: function( type, data ) {
2425		return this.each(function() {
2426			jQuery.event.trigger( type, data, this );
2427		});
2428	},
2429
2430	triggerHandler: function( type, data ) {
2431		if ( this[0] ) {
2432			var event = jQuery.Event( type );
2433			event.preventDefault();
2434			event.stopPropagation();
2435			jQuery.event.trigger( event, data, this[0] );
2436			return event.result;
2437		}
2438	},
2439
2440	toggle: function( fn ) {
2441		// Save reference to arguments for access in closure
2442		var args = arguments, i = 1;
2443
2444		// link all the functions, so any of them can unbind this click handler
2445		while ( i < args.length ) {
2446			jQuery.proxy( fn, args[ i++ ] );
2447		}
2448
2449		return this.click( jQuery.proxy( fn, function( event ) {
2450			// Figure out which function to execute
2451			var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i;
2452			jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 );
2453
2454			// Make sure that clicks stop
2455			event.preventDefault();
2456
2457			// and execute the function
2458			return args[ lastToggle ].apply( this, arguments ) || false;
2459		}));
2460	},
2461
2462	hover: function( fnOver, fnOut ) {
2463		return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
2464	}
2465});
2466
2467var liveMap = {
2468	focus: "focusin",
2469	blur: "focusout",
2470	mouseenter: "mouseover",
2471	mouseleave: "mouseout"
2472};
2473
2474jQuery.each(["live", "die"], function( i, name ) {
2475	jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) {
2476		var type, i = 0, match, namespaces, preType,
2477			selector = origSelector || this.selector,
2478			context = origSelector ? this : jQuery( this.context );
2479
2480		if ( jQuery.isFunction( data ) ) {
2481			fn = data;
2482			data = undefined;
2483		}
2484
2485		types = (types || "").split(" ");
2486
2487		while ( (type = types[ i++ ]) != null ) {
2488			match = rnamespaces.exec( type );
2489			namespaces = "";
2490
2491			if ( match )  {
2492				namespaces = match[0];
2493				type = type.replace( rnamespaces, "" );
2494			}
2495
2496			if ( type === "hover" ) {
2497				types.push( "mouseenter" + namespaces, "mouseleave" + namespaces );
2498				continue;
2499			}
2500
2501			preType = type;
2502
2503			if ( type === "focus" || type === "blur" ) {
2504				types.push( liveMap[ type ] + namespaces );
2505				type = type + namespaces;
2506
2507			} else {
2508				type = (liveMap[ type ] || type) + namespaces;
2509			}
2510
2511			if ( name === "live" ) {
2512				// bind live handler
2513				context.each(function(){
2514					jQuery.event.add( this, liveConvert( type, selector ),
2515						{ data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } );
2516				});
2517
2518			} else {
2519				// unbind live handler
2520				context.unbind( liveConvert( type, selector ), fn );
2521			}
2522		}
2523
2524		return this;
2525	}
2526});
2527
2528function liveHandler( event ) {
2529	var stop, elems = [], selectors = [], args = arguments,
2530		related, match, handleObj, elem, j, i, l, data,
2531		events = jQuery.data( this, "events" );
2532
2533	// Make sure we avoid non-left-click bubbling in Firefox (#3861)
2534	if ( event.liveFired === this || !events || !events.live || event.button && event.type === "click" ) {
2535		return;
2536	}
2537
2538	event.liveFired = this;
2539
2540	var live = events.live.slice(0);
2541
2542	for ( j = 0; j < live.length; j++ ) {
2543		handleObj = live[j];
2544
2545		if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) {
2546			selectors.push( handleObj.selector );
2547
2548		} else {
2549			live.splice( j--, 1 );
2550		}
2551	}
2552
2553	match = jQuery( event.target ).closest( selectors, event.currentTarget );
2554
2555	for ( i = 0, l = match.length; i < l; i++ ) {
2556		for ( j = 0; j < live.length; j++ ) {
2557			handleObj = live[j];
2558
2559			if ( match[i].selector === handleObj.selector ) {
2560				elem = match[i].elem;
2561				related = null;
2562
2563				// Those two events require additional checking
2564				if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) {
2565					related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0];
2566				}
2567
2568				if ( !related || related !== elem ) {
2569					elems.push({ elem: elem, handleObj: handleObj });
2570				}
2571			}
2572		}
2573	}
2574
2575	for ( i = 0, l = elems.length; i < l; i++ ) {
2576		match = elems[i];
2577		event.currentTarget = match.elem;
2578		event.data = match.handleObj.data;
2579		event.handleObj = match.handleObj;
2580
2581		if ( match.handleObj.origHandler.apply( match.elem, args ) === false ) {
2582			stop = false;
2583			break;
2584		}
2585	}
2586
2587	return stop;
2588}
2589
2590function liveConvert( type, selector ) {
2591	return "live." + (type && type !== "*" ? type + "." : "") + selector.replace(/\./g, "`").replace(/ /g, "&");
2592}
2593
2594jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
2595	"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
2596	"change select submit keydown keypress keyup error").split(" "), function( i, name ) {
2597
2598	// Handle event binding
2599	jQuery.fn[ name ] = function( fn ) {
2600		return fn ? this.bind( name, fn ) : this.trigger( name );
2601	};
2602
2603	if ( jQuery.attrFn ) {
2604		jQuery.attrFn[ name ] = true;
2605	}
2606});
2607
2608// Prevent memory leaks in IE
2609// Window isn't included so as not to unbind existing unload events
2610// More info:
2611//  - http://isaacschlueter.com/2006/10/msie-memory-leaks/
2612if ( window.attachEvent && !window.addEventListener ) {
2613	window.attachEvent("onunload", function() {
2614		for ( var id in jQuery.cache ) {
2615			if ( jQuery.cache[ id ].handle ) {
2616				// Try/Catch is to handle iframes being unloaded, see #4280
2617				try {
2618					jQuery.event.remove( jQuery.cache[ id ].handle.elem );
2619				} catch(e) {}
2620			}
2621		}
2622	});
2623}
2624/*!
2625 * Sizzle CSS Selector Engine - v1.0
2626 *  Copyright 2009, The Dojo Foundation
2627 *  Released under the MIT, BSD, and GPL Licenses.
2628 *  More information: http://sizzlejs.com/
2629 */
2630(function(){
2631
2632var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
2633	done = 0,
2634	toString = Object.prototype.toString,
2635	hasDuplicate = false,
2636	baseHasDuplicate = true;
2637
2638// Here we check if the JavaScript engine is using some sort of
2639// optimization where it does not always call our comparision
2640// function. If that is the case, discard the hasDuplicate value.
2641//   Thus far that includes Google Chrome.
2642[0, 0].sort(function(){
2643	baseHasDuplicate = false;
2644	return 0;
2645});
2646
2647var Sizzle = function(selector, context, results, seed) {
2648	results = results || [];
2649	var origContext = context = context || document;
2650
2651	if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
2652		return [];
2653	}
2654
2655	if ( !selector || typeof selector !== "string" ) {
2656		return results;
2657	}
2658
2659	var parts = [], m, set, checkSet, extra, prune = true, contextXML = isXML(context),
2660		soFar = selector;
2661
2662	// Reset the position of the chunker regexp (start from head)
2663	while ( (chunker.exec(""), m = chunker.exec(soFar)) !== null ) {
2664		soFar = m[3];
2665
2666		parts.push( m[1] );
2667
2668		if ( m[2] ) {
2669			extra = m[3];
2670			break;
2671		}
2672	}
2673
2674	if ( parts.length > 1 && origPOS.exec( selector ) ) {
2675		if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
2676			set = posProcess( parts[0] + parts[1], context );
2677		} else {
2678			set = Expr.relative[ parts[0] ] ?
2679				[ context ] :
2680				Sizzle( parts.shift(), context );
2681
2682			while ( parts.length ) {
2683				selector = parts.shift();
2684
2685				if ( Expr.relative[ selector ] ) {
2686					selector += parts.shift();
2687				}
2688
2689				set = posProcess( selector, set );
2690			}
2691		}
2692	} else {
2693		// Take a shortcut and set the context if the root selector is an ID
2694		// (but not if it'll be faster if the inner selector is an ID)
2695		if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&
2696				Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {
2697			var ret = Sizzle.find( parts.shift(), context, contextXML );
2698			context = ret.expr ? Sizzle.filter( ret.expr, ret.set )[0] : ret.set[0];
2699		}
2700
2701		if ( context ) {
2702			var ret = seed ?
2703				{ expr: parts.pop(), set: makeArray(seed) } :
2704				Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML );
2705			set = ret.expr ? Sizzle.filter( ret.expr, ret.set ) : ret.set;
2706
2707			if ( parts.length > 0 ) {
2708				checkSet = makeArray(set);
2709			} else {
2710				prune = false;
2711			}
2712
2713			while ( parts.length ) {
2714				var cur = parts.pop(), pop = cur;
2715
2716				if ( !Expr.relative[ cur ] ) {
2717					cur = "";
2718				} else {
2719					pop = parts.pop();
2720				}
2721
2722				if ( pop == null ) {
2723					pop = context;
2724				}
2725
2726				Expr.relative[ cur ]( checkSet, pop, contextXML );
2727			}
2728		} else {
2729			checkSet = parts = [];
2730		}
2731	}
2732
2733	if ( !checkSet ) {
2734		checkSet = set;
2735	}
2736
2737	if ( !checkSet ) {
2738		Sizzle.error( cur || selector );
2739	}
2740
2741	if ( toString.call(checkSet) === "[object Array]" ) {
2742		if ( !prune ) {
2743			results.push.apply( results, checkSet );
2744		} else if ( context && context.nodeType === 1 ) {
2745			for ( var i = 0; checkSet[i] != null; i++ ) {
2746				if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) {
2747					results.push( set[i] );
2748				}
2749			}
2750		} else {
2751			for ( var i = 0; checkSet[i] != null; i++ ) {
2752				if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
2753					results.push( set[i] );
2754				}
2755			}
2756		}
2757	} else {
2758		makeArray( checkSet, results );
2759	}
2760
2761	if ( extra ) {
2762		Sizzle( extra, origContext, results, seed );
2763		Sizzle.uniqueSort( results );
2764	}
2765
2766	return results;
2767};
2768
2769Sizzle.uniqueSort = function(results){
2770	if ( sortOrder ) {
2771		hasDuplicate = baseHasDuplicate;
2772		results.sort(sortOrder);
2773
2774		if ( hasDuplicate ) {
2775			for ( var i = 1; i < results.length; i++ ) {
2776				if ( results[i] === results[i-1] ) {
2777					results.splice(i--, 1);
2778				}
2779			}
2780		}
2781	}
2782
2783	return results;
2784};
2785
2786Sizzle.matches = function(expr, set){
2787	return Sizzle(expr, null, null, set);
2788};
2789
2790Sizzle.find = function(expr, context, isXML){
2791	var set, match;
2792
2793	if ( !expr ) {
2794		return [];
2795	}
2796
2797	for ( var i = 0, l = Expr.order.length; i < l; i++ ) {
2798		var type = Expr.order[i], match;
2799
2800		if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {
2801			var left = match[1];
2802			match.splice(1,1);
2803
2804			if ( left.substr( left.length - 1 ) !== "\\" ) {
2805				match[1] = (match[1] || "").replace(/\\/g, "");
2806				set = Expr.find[ type ]( match, context, isXML );
2807				if ( set != null ) {
2808					expr = expr.replace( Expr.match[ type ], "" );
2809					break;
2810				}
2811			}
2812		}
2813	}
2814
2815	if ( !set ) {
2816		set = context.getElementsByTagName("*");
2817	}
2818
2819	return {set: set, expr: expr};
2820};
2821
2822Sizzle.filter = function(expr, set, inplace, not){
2823	var old = expr, result = [], curLoop = set, match, anyFound,
2824		isXMLFilter = set && set[0] && isXML(set[0]);
2825
2826	while ( expr && set.length ) {
2827		for ( var type in Expr.filter ) {
2828			if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {
2829				var filter = Expr.filter[ type ], found, item, left = match[1];
2830				anyFound = false;
2831
2832				match.splice(1,1);
2833
2834				if ( left.substr( left.length - 1 ) === "\\" ) {
2835					continue;
2836				}
2837
2838				if ( curLoop === result ) {
2839					result = [];
2840				}
2841
2842				if ( Expr.preFilter[ type ] ) {
2843					match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );
2844
2845					if ( !match ) {
2846						anyFound = found = true;
2847					} else if ( match === true ) {
2848						continue;
2849					}
2850				}
2851
2852				if ( match ) {
2853					for ( var i = 0; (item = curLoop[i]) != null; i++ ) {
2854						if ( item ) {
2855							found = filter( item, match, i, curLoop );
2856							var pass = not ^ !!found;
2857
2858							if ( inplace && found != null ) {
2859								if ( pass ) {
2860									anyFound = true;
2861								} else {
2862									curLoop[i] = false;
2863								}
2864							} else if ( pass ) {
2865								result.push( item );
2866								anyFound = true;
2867							}
2868						}
2869					}
2870				}
2871
2872				if ( found !== undefined ) {
2873					if ( !inplace ) {
2874						curLoop = result;
2875					}
2876
2877					expr = expr.replace( Expr.match[ type ], "" );
2878
2879					if ( !anyFound ) {
2880						return [];
2881					}
2882
2883					break;
2884				}
2885			}
2886		}
2887
2888		// Improper expression
2889		if ( expr === old ) {
2890			if ( anyFound == null ) {
2891				Sizzle.error( expr );
2892			} else {
2893				break;
2894			}
2895		}
2896
2897		old = expr;
2898	}
2899
2900	return curLoop;
2901};
2902
2903Sizzle.error = function( msg ) {
2904	throw "Syntax error, unrecognized expression: " + msg;
2905};
2906
2907var Expr = Sizzle.selectors = {
2908	order: [ "ID", "NAME", "TAG" ],
2909	match: {
2910		ID: /#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
2911		CLASS: /\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
2912		NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,
2913		ATTR: /\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,
2914		TAG: /^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,
2915		CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,
2916		POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,
2917		PSEUDO: /:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/
2918	},
2919	leftMatch: {},
2920	attrMap: {
2921		"class": "className",
2922		"for": "htmlFor"
2923	},
2924	attrHandle: {
2925		href: function(elem){
2926			return elem.getAttribute("href");
2927		}
2928	},
2929	relative: {
2930		"+": function(checkSet, part){
2931			var isPartStr = typeof part === "string",
2932				isTag = isPartStr && !/\W/.test(part),
2933				isPartStrNotTag = isPartStr && !isTag;
2934
2935			if ( isTag ) {
2936				part = part.toLowerCase();
2937			}
2938
2939			for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
2940				if ( (elem = checkSet[i]) ) {
2941					while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
2942
2943					checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?
2944						elem || false :
2945						elem === part;
2946				}
2947			}
2948
2949			if ( isPartStrNotTag ) {
2950				Sizzle.filter( part, checkSet, true );
2951			}
2952		},
2953		">": function(checkSet, part){
2954			var isPartStr = typeof part === "string";
2955
2956			if ( isPartStr && !/\W/.test(part) ) {
2957				part = part.toLowerCase();
2958
2959				for ( var i = 0, l = checkSet.length; i < l; i++ ) {
2960					var elem = checkSet[i];
2961					if ( elem ) {
2962						var parent = elem.parentNode;
2963						checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;
2964					}
2965				}
2966			} else {
2967				for ( var i = 0, l = checkSet.length; i < l; i++ ) {
2968					var elem = checkSet[i];
2969					if ( elem ) {
2970						checkSet[i] = isPartStr ?
2971							elem.parentNode :
2972							elem.parentNode === part;
2973					}
2974				}
2975
2976				if ( isPartStr ) {
2977					Sizzle.filter( part, checkSet, true );
2978				}
2979			}
2980		},
2981		"": function(checkSet, part, isXML){
2982			var doneName = done++, checkFn = dirCheck;
2983
2984			if ( typeof part === "string" && !/\W/.test(part) ) {
2985				var nodeCheck = part = part.toLowerCase();
2986				checkFn = dirNodeCheck;
2987			}
2988
2989			checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML);
2990		},
2991		"~": function(checkSet, part, isXML){
2992			var doneName = done++, checkFn = dirCheck;
2993
2994			if ( typeof part === "string" && !/\W/.test(part) ) {
2995				var nodeCheck = part = part.toLowerCase();
2996				checkFn = dirNodeCheck;
2997			}
2998
2999			checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML);
3000		}
3001	},
3002	find: {
3003		ID: function(match, context, isXML){
3004			if ( typeof context.getElementById !== "undefined" && !isXML ) {
3005				var m = context.getElementById(match[1]);
3006				return m ? [m] : [];
3007			}
3008		},
3009		NAME: function(match, context){
3010			if ( typeof context.getElementsByName !== "undefined" ) {
3011				var ret = [], results = context.getElementsByName(match[1]);
3012
3013				for ( var i = 0, l = results.length; i < l; i++ ) {
3014					if ( results[i].getAttribute("name") === match[1] ) {
3015						ret.push( results[i] );
3016					}
3017				}
3018
3019				return ret.length === 0 ? null : ret;
3020			}
3021		},
3022		TAG: function(match, context){
3023			return context.getElementsByTagName(match[1]);
3024		}
3025	},
3026	preFilter: {
3027		CLASS: function(match, curLoop, inplace, result, not, isXML){
3028			match = " " + match[1].replace(/\\/g, "") + " ";
3029
3030			if ( isXML ) {
3031				return match;
3032			}
3033
3034			for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
3035				if ( elem ) {
3036					if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n]/g, " ").indexOf(match) >= 0) ) {
3037						if ( !inplace ) {
3038							result.push( elem );
3039						}
3040					} else if ( inplace ) {
3041						curLoop[i] = false;
3042					}
3043				}
3044			}
3045
3046			return false;
3047		},
3048		ID: function(match){
3049			return match[1].replace(/\\/g, "");
3050		},
3051		TAG: function(match, curLoop){
3052			return match[1].toLowerCase();
3053		},
3054		CHILD: function(match){
3055			if ( match[1] === "nth" ) {
3056				// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
3057				var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
3058					match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" ||
3059					!/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
3060
3061				// calculate the numbers (first)n+(last) including if they are negative
3062				match[2] = (test[1] + (test[2] || 1)) - 0;
3063				match[3] = test[3] - 0;
3064			}
3065
3066			// TODO: Move to normal caching system
3067			match[0] = done++;
3068
3069			return match;
3070		},
3071		ATTR: function(match, curLoop, inplace, result, not, isXML){
3072			var name = match[1].replace(/\\/g, "");
3073
3074			if ( !isXML && Expr.attrMap[name] ) {
3075				match[1] = Expr.attrMap[name];
3076			}
3077
3078			if ( match[2] === "~=" ) {
3079				match[4] = " " + match[4] + " ";
3080			}
3081
3082			return match;
3083		},
3084		PSEUDO: function(match, curLoop, inplace, result, not){
3085			if ( match[1] === "not" ) {
3086				// If we're dealing with a complex expression, or a simple one
3087				if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) {
3088					match[3] = Sizzle(match[3], null, null, curLoop);
3089				} else {
3090					var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
3091					if ( !inplace ) {
3092						result.push.apply( result, ret );
3093					}
3094					return false;
3095				}
3096			} else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
3097				return true;
3098			}
3099
3100			return match;
3101		},
3102		POS: function(match){
3103			match.unshift( true );
3104			return match;
3105		}
3106	},
3107	filters: {
3108		enabled: function(elem){
3109			return elem.disabled === false && elem.type !== "hidden";
3110		},
3111		disabled: function(elem){
3112			return elem.disabled === true;
3113		},
3114		checked: function(elem){
3115			return elem.checked === true;
3116		},
3117		selected: function(elem){
3118			// Accessing this property makes selected-by-default
3119			// options in Safari work properly
3120			elem.parentNode.selectedIndex;
3121			return elem.selected === true;
3122		},
3123		parent: function(elem){
3124			return !!elem.firstChild;
3125		},
3126		empty: function(elem){
3127			return !elem.firstChild;
3128		},
3129		has: function(elem, i, match){
3130			return !!Sizzle( match[3], elem ).length;
3131		},
3132		header: function(elem){
3133			return /h\d/i.test( elem.nodeName );
3134		},
3135		text: function(elem){
3136			return "text" === elem.type;
3137		},
3138		radio: function(elem){
3139			return "radio" === elem.type;
3140		},
3141		checkbox: function(elem){
3142			return "checkbox" === elem.type;
3143		},
3144		file: function(elem){
3145			return "file" === elem.type;
3146		},
3147		password: function(elem){
3148			return "password" === elem.type;
3149		},
3150		submit: function(elem){
3151			return "submit" === elem.type;
3152		},
3153		image: function(elem){
3154			return "image" === elem.type;
3155		},
3156		reset: function(elem){
3157			return "reset" === elem.type;
3158		},
3159		button: function(elem){
3160			return "button" === elem.type || elem.nodeName.toLowerCase() === "button";
3161		},
3162		input: function(elem){
3163			return /input|select|textarea|button/i.test(elem.nodeName);
3164		}
3165	},
3166	setFilters: {
3167		first: function(elem, i){
3168			return i === 0;
3169		},
3170		last: function(elem, i, match, array){
3171			return i === array.length - 1;
3172		},
3173		even: function(elem, i){
3174			return i % 2 === 0;
3175		},
3176		odd: function(elem, i){
3177			return i % 2 === 1;
3178		},
3179		lt: function(elem, i, match){
3180			return i < match[3] - 0;
3181		},
3182		gt: function(elem, i, match){
3183			return i > match[3] - 0;
3184		},
3185		nth: function(elem, i, match){
3186			return match[3] - 0 === i;
3187		},
3188		eq: function(elem, i, match){
3189			return match[3] - 0 === i;
3190		}
3191	},
3192	filter: {
3193		PSEUDO: function(elem, match, i, array){
3194			var name = match[1], filter = Expr.filters[ name ];
3195
3196			if ( filter ) {
3197				return filter( elem, i, match, array );
3198			} else if ( name === "contains" ) {
3199				return (elem.textContent || elem.innerText || getText([ elem ]) || "").indexOf(match[3]) >= 0;
3200			} else if ( name === "not" ) {
3201				var not = match[3];
3202
3203				for ( var i = 0, l = not.length; i < l; i++ ) {
3204					if ( not[i] === elem ) {
3205						return false;
3206					}
3207				}
3208
3209				return true;
3210			} else {
3211				Sizzle.error( "Syntax error, unrecognized expression: " + name );
3212			}
3213		},
3214		CHILD: function(elem, match){
3215			var type = match[1], node = elem;
3216			switch (type) {
3217				case 'only':
3218				case 'first':
3219					while ( (node = node.previousSibling) )	 {
3220						if ( node.nodeType === 1 ) {
3221							return false;
3222						}
3223					}
3224					if ( type === "first" ) {
3225						return true;
3226					}
3227					node = elem;
3228				case 'last':
3229					while ( (node = node.nextSibling) )	 {
3230						if ( node.nodeType === 1 ) {
3231							return false;
3232						}
3233					}
3234					return true;
3235				case 'nth':
3236					var first = match[2], last = match[3];
3237
3238					if ( first === 1 && last === 0 ) {
3239						return true;
3240					}
3241
3242					var doneName = match[0],
3243						parent = elem.parentNode;
3244
3245					if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {
3246						var count = 0;
3247						for ( node = parent.firstChild; node; node = node.nextSibling ) {
3248							if ( node.nodeType === 1 ) {
3249								node.nodeIndex = ++count;
3250							}
3251						}
3252						parent.sizcache = doneName;
3253					}
3254
3255					var diff = elem.nodeIndex - last;
3256					if ( first === 0 ) {
3257						return diff === 0;
3258					} else {
3259						return ( diff % first === 0 && diff / first >= 0 );
3260					}
3261			}
3262		},
3263		ID: function(elem, match){
3264			return elem.nodeType === 1 && elem.getAttribute("id") === match;
3265		},
3266		TAG: function(elem, match){
3267			return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match;
3268		},
3269		CLASS: function(elem, match){
3270			return (" " + (elem.className || elem.getAttribute("class")) + " ")
3271				.indexOf( match ) > -1;
3272		},
3273		ATTR: function(elem, match){
3274			var name = match[1],
3275				result = Expr.attrHandle[ name ] ?
3276					Expr.attrHandle[ name ]( elem ) :
3277					elem[ name ] != null ?
3278						elem[ name ] :
3279						elem.getAttribute( name ),
3280				value = result + "",
3281				type = match[2],
3282				check = match[4];
3283
3284			return result == null ?
3285				type === "!=" :
3286				type === "=" ?
3287				value === check :
3288				type === "*=" ?
3289				value.indexOf(check) >= 0 :
3290				type === "~=" ?
3291				(" " + value + " ").indexOf(check) >= 0 :
3292				!check ?
3293				value && result !== false :
3294				type === "!=" ?
3295				value !== check :
3296				type === "^=" ?
3297				value.indexOf(check) === 0 :
3298				type === "$=" ?
3299				value.substr(value.length - check.length) === check :
3300				type === "|=" ?
3301				value === check || value.substr(0, check.length + 1) === check + "-" :
3302				false;
3303		},
3304		POS: function(elem, match, i, array){
3305			var name = match[2], filter = Expr.setFilters[ name ];
3306
3307			if ( filter ) {
3308				return filter( elem, i, match, array );
3309			}
3310		}
3311	}
3312};
3313
3314var origPOS = Expr.match.POS;
3315
3316for ( var type in Expr.match ) {
3317	Expr.match[ type ] = new RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source );
3318	Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, function(all, num){
3319		return "\\" + (num - 0 + 1);
3320	}));
3321}
3322
3323var makeArray = function(array, results) {
3324	array = Array.prototype.slice.call( array, 0 );
3325
3326	if ( results ) {
3327		results.push.apply( results, array );
3328		return results;
3329	}
3330
3331	return array;
3332};
3333
3334// Perform a simple check to determine if the browser is capable of
3335// converting a NodeList to an array using builtin methods.
3336// Also verifies that the returned array holds DOM nodes
3337// (which is not the case in the Blackberry browser)
3338try {
3339	Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;
3340
3341// Provide a fallback method if it does not work
3342} catch(e){
3343	makeArray = function(array, results) {
3344		var ret = results || [];
3345
3346		if ( toString.call(array) === "[object Array]" ) {
3347			Array.prototype.push.apply( ret, array );
3348		} else {
3349			if ( typeof array.length === "number" ) {
3350				for ( var i = 0, l = array.length; i < l; i++ ) {
3351					ret.push( array[i] );
3352				}
3353			} else {
3354				for ( var i = 0; array[i]; i++ ) {
3355					ret.push( array[i] );
3356				}
3357			}
3358		}
3359
3360		return ret;
3361	};
3362}
3363
3364var sortOrder;
3365
3366if ( document.documentElement.compareDocumentPosition ) {
3367	sortOrder = function( a, b ) {
3368		if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {
3369			if ( a == b ) {
3370				hasDuplicate = true;
3371			}
3372			return a.compareDocumentPosition ? -1 : 1;
3373		}
3374
3375		var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1;
3376		if ( ret === 0 ) {
3377			hasDuplicate = true;
3378		}
3379		return ret;
3380	};
3381} else if ( "sourceIndex" in document.documentElement ) {
3382	sortOrder = function( a, b ) {
3383		if ( !a.sourceIndex || !b.sourceIndex ) {
3384			if ( a == b ) {
3385				hasDuplicate = true;
3386			}
3387			return a.sourceIndex ? -1 : 1;
3388		}
3389
3390		var ret = a.sourceIndex - b.sourceIndex;
3391		if ( ret === 0 ) {
3392			hasDuplicate = true;
3393		}
3394		return ret;
3395	};
3396} else if ( document.createRange ) {
3397	sortOrder = function( a, b ) {
3398		if ( !a.ownerDocument || !b.ownerDocument ) {
3399			if ( a == b ) {
3400				hasDuplicate = true;
3401			}
3402			return a.ownerDocument ? -1 : 1;
3403		}
3404
3405		var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange();
3406		aRange.setStart(a, 0);
3407		aRange.setEnd(a, 0);
3408		bRange.setStart(b, 0);
3409		bRange.setEnd(b, 0);
3410		var ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange);
3411		if ( ret === 0 ) {
3412			hasDuplicate = true;
3413		}
3414		return ret;
3415	};
3416}
3417
3418// Utility function for retreiving the text value of an array of DOM nodes
3419function getText( elems ) {
3420	var ret = "", elem;
3421
3422	for ( var i = 0; elems[i]; i++ ) {
3423		elem = elems[i];
3424
3425		// Get the text from text nodes and CDATA nodes
3426		if ( elem.nodeType === 3 || elem.nodeType === 4 ) {
3427			ret += elem.nodeValue;
3428
3429		// Traverse everything else, except comment nodes
3430		} else if ( elem.nodeType !== 8 ) {
3431			ret += getText( elem.childNodes );
3432		}
3433	}
3434
3435	return ret;
3436}
3437
3438// Check to see if the browser returns elements by name when
3439// querying by getElementById (and provide a workaround)
3440(function(){
3441	// We're going to inject a fake input element with a specified name
3442	var form = document.createElement("div"),
3443		id = "script" + (new Date).getTime();
3444	form.innerHTML = "<a name='" + id + "'/>";
3445
3446	// Inject it into the root element, check its status, and remove it quickly
3447	var root = document.documentElement;
3448	root.insertBefore( form, root.firstChild );
3449
3450	// The workaround has to do additional checks after a getElementById
3451	// Which slows things down for other browsers (hence the branching)
3452	if ( document.getElementById( id ) ) {
3453		Expr.find.ID = function(match, context, isXML){
3454			if ( typeof context.getElementById !== "undefined" && !isXML ) {
3455				var m = context.getElementById(match[1]);
3456				return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : [];
3457			}
3458		};
3459
3460		Expr.filter.ID = function(elem, match){
3461			var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
3462			return elem.nodeType === 1 && node && node.nodeValue === match;
3463		};
3464	}
3465
3466	root.removeChild( form );
3467	root = form = null; // release memory in IE
3468})();
3469
3470(function(){
3471	// Check to see if the browser returns only elements
3472	// when doing getElementsByTagName("*")
3473
3474	// Create a fake element
3475	var div = document.createElement("div");
3476	div.appendChild( document.createComment("") );
3477
3478	// Make sure no comments are found
3479	if ( div.getElementsByTagName("*").length > 0 ) {
3480		Expr.find.TAG = function(match, context){
3481			var results = context.getElementsByTagName(match[1]);
3482
3483			// Filter out possible comments
3484			if ( match[1] === "*" ) {
3485				var tmp = [];
3486
3487				for ( var i = 0; results[i]; i++ ) {
3488					if ( results[i].nodeType === 1 ) {
3489						tmp.push( results[i] );
3490					}
3491				}
3492
3493				results = tmp;
3494			}
3495
3496			return results;
3497		};
3498	}
3499
3500	// Check to see if an attribute returns normalized href attributes
3501	div.innerHTML = "<a href='#'></a>";
3502	if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
3503			div.firstChild.getAttribute("href") !== "#" ) {
3504		Expr.attrHandle.href = function(elem){
3505			return elem.getAttribute("href", 2);
3506		};
3507	}
3508
3509	div = null; // release memory in IE
3510})();
3511
3512if ( document.querySelectorAll ) {
3513	(function(){
3514		var oldSizzle = Sizzle, div = document.createElement("div");
3515		div.innerHTML = "<p class='TEST'></p>";
3516
3517		// Safari can't handle uppercase or unicode characters when
3518		// in quirks mode.
3519		if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
3520			return;
3521		}
3522
3523		Sizzle = function(query, context, extra, seed){
3524			context = context || document;
3525
3526			// Only use querySelectorAll on non-XML documents
3527			// (ID selectors don't work in non-HTML documents)
3528			if ( !seed && context.nodeType === 9 && !isXML(context) ) {
3529				try {
3530					return makeArray( context.querySelectorAll(query), extra );
3531				} catch(e){}
3532			}
3533
3534			return oldSizzle(query, context, extra, seed);
3535		};
3536
3537		for ( var prop in oldSizzle ) {
3538			Sizzle[ prop ] = oldSizzle[ prop ];
3539		}
3540
3541		div = null; // release memory in IE
3542	})();
3543}
3544
3545(function(){
3546	var div = document.createElement("div");
3547
3548	div.innerHTML = "<div class='test e'></div><div class='test'></div>";
3549
3550	// Opera can't find a second classname (in 9.6)
3551	// Also, make sure that getElementsByClassName actually exists
3552	if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) {
3553		return;
3554	}
3555
3556	// Safari caches class attributes, doesn't catch changes (in 3.2)
3557	div.lastChild.className = "e";
3558
3559	if ( div.getElementsByClassName("e").length === 1 ) {
3560		return;
3561	}
3562
3563	Expr.order.splice(1, 0, "CLASS");
3564	Expr.find.CLASS = function(match, context, isXML) {
3565		if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
3566			return context.getElementsByClassName(match[1]);
3567		}
3568	};
3569
3570	div = null; // release memory in IE
3571})();
3572
3573function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
3574	for ( var i = 0, l = checkSet.length; i < l; i++ ) {
3575		var elem = checkSet[i];
3576		if ( elem ) {
3577			elem = elem[dir];
3578			var match = false;
3579
3580			while ( elem ) {
3581				if ( elem.sizcache === doneName ) {
3582					match = checkSet[elem.sizset];
3583					break;
3584				}
3585
3586				if ( elem.nodeType === 1 && !isXML ){
3587					elem.sizcache = doneName;
3588					elem.sizset = i;
3589				}
3590
3591				if ( elem.nodeName.toLowerCase() === cur ) {
3592					match = elem;
3593					break;
3594				}
3595
3596				elem = elem[dir];
3597			}
3598
3599			checkSet[i] = match;
3600		}
3601	}
3602}
3603
3604function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
3605	for ( var i = 0, l = checkSet.length; i < l; i++ ) {
3606		var elem = checkSet[i];
3607		if ( elem ) {
3608			elem = elem[dir];
3609			var match = false;
3610
3611			while ( elem ) {
3612				if ( elem.sizcache === doneName ) {
3613					match = checkSet[elem.sizset];
3614					break;
3615				}
3616
3617				if ( elem.nodeType === 1 ) {
3618					if ( !isXML ) {
3619						elem.sizcache = doneName;
3620						elem.sizset = i;
3621					}
3622					if ( typeof cur !== "string" ) {
3623						if ( elem === cur ) {
3624							match = true;
3625							break;
3626						}
3627
3628					} else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
3629						match = elem;
3630						break;
3631					}
3632				}
3633
3634				elem = elem[dir];
3635			}
3636
3637			checkSet[i] = match;
3638		}
3639	}
3640}
3641
3642var contains = document.compareDocumentPosition ? function(a, b){
3643	return !!(a.compareDocumentPosition(b) & 16);
3644} : function(a, b){
3645	return a !== b && (a.contains ? a.contains(b) : true);
3646};
3647
3648var isXML = function(elem){
3649	// documentElement is verified for cases where it doesn't yet exist
3650	// (such as loading iframes in IE - #4833)
3651	var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;
3652	return documentElement ? documentElement.nodeName !== "HTML" : false;
3653};
3654
3655var posProcess = function(selector, context){
3656	var tmpSet = [], later = "", match,
3657		root = context.nodeType ? [context] : context;
3658
3659	// Position selectors must be done after the filter
3660	// And so must :not(positional) so we move all PSEUDOs to the end
3661	while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
3662		later += match[0];
3663		selector = selector.replace( Expr.match.PSEUDO, "" );
3664	}
3665
3666	selector = Expr.relative[selector] ? selector + "*" : selector;
3667
3668	for ( var i = 0, l = root.length; i < l; i++ ) {
3669		Sizzle( selector, root[i], tmpSet );
3670	}
3671
3672	return Sizzle.filter( later, tmpSet );
3673};
3674
3675// EXPOSE
3676jQuery.find = Sizzle;
3677jQuery.expr = Sizzle.selectors;
3678jQuery.expr[":"] = jQuery.expr.filters;
3679jQuery.unique = Sizzle.uniqueSort;
3680jQuery.text = getText;
3681jQuery.isXMLDoc = isXML;
3682jQuery.contains = contains;
3683
3684return;
3685
3686window.Sizzle = Sizzle;
3687
3688})();
3689var runtil = /Until$/,
3690	rparentsprev = /^(?:parents|prevUntil|prevAll)/,
3691	// Note: This RegExp should be improved, or likely pulled from Sizzle
3692	rmultiselector = /,/,
3693	slice = Array.prototype.slice;
3694
3695// Implement the identical functionality for filter and not
3696var winnow = function( elements, qualifier, keep ) {
3697	if ( jQuery.isFunction( qualifier ) ) {
3698		return jQuery.grep(elements, function( elem, i ) {
3699			return !!qualifier.call( elem, i, elem ) === keep;
3700		});
3701
3702	} else if ( qualifier.nodeType ) {
3703		return jQuery.grep(elements, function( elem, i ) {
3704			return (elem === qualifier) === keep;
3705		});
3706
3707	} else if ( typeof qualifier === "string" ) {
3708		var filtered = jQuery.grep(elements, function( elem ) {
3709			return elem.nodeType === 1;
3710		});
3711
3712		if ( isSimple.test( qualifier ) ) {
3713			return jQuery.filter(qualifier, filtered, !keep);
3714		} else {
3715			qualifier = jQuery.filter( qualifier, filtered );
3716		}
3717	}
3718
3719	return jQuery.grep(elements, function( elem, i ) {
3720		return (jQuery.inArray( elem, qualifier ) >= 0) === keep;
3721	});
3722};
3723
3724jQuery.fn.extend({
3725	find: function( selector ) {
3726		var ret = this.pushStack( "", "find", selector ), length = 0;
3727
3728		for ( var i = 0, l = this.length; i < l; i++ ) {
3729			length = ret.length;
3730			jQuery.find( selector, this[i], ret );
3731
3732			if ( i > 0 ) {
3733				// Make sure that the results are unique
3734				for ( var n = length; n < ret.length; n++ ) {
3735					for ( var r = 0; r < length; r++ ) {
3736						if ( ret[r] === ret[n] ) {
3737							ret.splice(n--, 1);
3738							break;
3739						}
3740					}
3741				}
3742			}
3743		}
3744
3745		return ret;
3746	},
3747
3748	has: function( target ) {
3749		var targets = jQuery( target );
3750		return this.filter(function() {
3751			for ( var i = 0, l = targets.length; i < l; i++ ) {
3752				if ( jQuery.contains( this, targets[i] ) ) {
3753					return true;
3754				}
3755			}
3756		});
3757	},
3758
3759	not: function( selector ) {
3760		return this.pushStack( winnow(this, selector, false), "not", selector);
3761	},
3762
3763	filter: function( selector ) {
3764		return this.pushStack( winnow(this, selector, true), "filter", selector );
3765	},
3766
3767	is: function( selector ) {
3768		return !!selector && jQuery.filter( selector, this ).length > 0;
3769	},
3770
3771	closest: function( selectors, context ) {
3772		if ( jQuery.isArray( selectors ) ) {
3773			var ret = [], cur = this[0], match, matches = {}, selector;
3774
3775			if ( cur && selectors.length ) {
3776				for ( var i = 0, l = selectors.length; i < l; i++ ) {
3777					selector = selectors[i];
3778
3779					if ( !matches[selector] ) {
3780						matches[selector] = jQuery.expr.match.POS.test( selector ) ?
3781							jQuery( selector, context || this.context ) :
3782							selector;
3783					}
3784				}
3785
3786				while ( cur && cur.ownerDocument && cur !== context ) {
3787					for ( selector in matches ) {
3788						match = matches[selector];
3789
3790						if ( match.jquery ? match.index(cur) > -1 : jQuery(cur).is(match) ) {
3791							ret.push({ selector: selector, elem: cur });
3792							delete matches[selector];
3793						}
3794					}
3795					cur = cur.parentNode;
3796				}
3797			}
3798
3799			return ret;
3800		}
3801
3802		var pos = jQuery.expr.match.POS.test( selectors ) ?
3803			jQuery( selectors, context || this.context ) : null;
3804
3805		return this.map(function( i, cur ) {
3806			while ( cur && cur.ownerDocument && cur !== context ) {
3807				if ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selectors) ) {
3808					return cur;
3809				}
3810				cur = cur.parentNode;
3811			}
3812			return null;
3813		});
3814	},
3815
3816	// Determine the position of an element within
3817	// the matched set of elements
3818	index: function( elem ) {
3819		if ( !elem || typeof elem === "string" ) {
3820			return jQuery.inArray( this[0],
3821				// If it receives a string, the selector is used
3822				// If it receives nothing, the siblings are used
3823				elem ? jQuery( elem ) : this.parent().children() );
3824		}
3825		// Locate the position of the desired element
3826		return jQuery.inArray(
3827			// If it receives a jQuery object, the first element is used
3828			elem.jquery ? elem[0] : elem, this );
3829	},
3830
3831	add: function( selector, context ) {
3832		var set = typeof selector === "string" ?
3833				jQuery( selector, context || this.context ) :
3834				jQuery.makeArray( selector ),
3835			all = jQuery.merge( this.get(), set );
3836
3837		return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?
3838			all :
3839			jQuery.unique( all ) );
3840	},
3841
3842	andSelf: function() {
3843		return this.add( this.prevObject );
3844	}
3845});
3846
3847// A painfully simple check to see if an element is disconnected
3848// from a document (should be improved, where feasible).
3849function isDisconnected( node ) {
3850	return !node || !node.parentNode || node.parentNode.nodeType === 11;
3851}
3852
3853jQuery.each({
3854	parent: function( elem ) {
3855		var parent = elem.parentNode;
3856		return parent && parent.nodeType !== 11 ? parent : null;
3857	},
3858	parents: function( elem ) {
3859		return jQuery.dir( elem, "parentNode" );
3860	},
3861	parentsUntil: function( elem, i, until ) {
3862		return jQuery.dir( elem, "parentNode", until );
3863	},
3864	next: function( elem ) {
3865		return jQuery.nth( elem, 2, "nextSibling" );
3866	},
3867	prev: function( elem ) {
3868		return jQuery.nth( elem, 2, "previousSibling" );
3869	},
3870	nextAll: function( elem ) {
3871		return jQuery.dir( elem, "nextSibling" );
3872	},
3873	prevAll: function( elem ) {
3874		return jQuery.dir( elem, "previousSibling" );
3875	},
3876	nextUntil: function( elem, i, until ) {
3877		return jQuery.dir( elem, "nextSibling", until );
3878	},
3879	prevUntil: function( elem, i, until ) {
3880		return jQuery.dir( elem, "previousSibling", until );
3881	},
3882	siblings: function( elem ) {
3883		return jQuery.sibling( elem.parentNode.firstChild, elem );
3884	},
3885	children: function( elem ) {
3886		return jQuery.sibling( elem.firstChild );
3887	},
3888	contents: function( elem ) {
3889		return jQuery.nodeName( elem, "iframe" ) ?
3890			elem.contentDocument || elem.contentWindow.document :
3891			jQuery.makeArray( elem.childNodes );
3892	}
3893}, function( name, fn ) {
3894	jQuery.fn[ name ] = function( until, selector ) {
3895		var ret = jQuery.map( this, fn, until );
3896
3897		if ( !runtil.test( name ) ) {
3898			selector = until;
3899		}
3900
3901		if ( selector && typeof selector === "string" ) {
3902			ret = jQuery.filter( selector, ret );
3903		}
3904
3905		ret = this.length > 1 ? jQuery.unique( ret ) : ret;
3906
3907		if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {
3908			ret = ret.reverse();
3909		}
3910
3911		return this.pushStack( ret, name, slice.call(arguments).join(",") );
3912	};
3913});
3914
3915jQuery.extend({
3916	filter: function( expr, elems, not ) {
3917		if ( not ) {
3918			expr = ":not(" + expr + ")";
3919		}
3920
3921		return jQuery.find.matches(expr, elems);
3922	},
3923
3924	dir: function( elem, dir, until ) {
3925		var matched = [], cur = elem[dir];
3926		while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
3927			if ( cur.nodeType === 1 ) {
3928				matched.push( cur );
3929			}
3930			cur = cur[dir];
3931		}
3932		return matched;
3933	},
3934
3935	nth: function( cur, result, dir, elem ) {
3936		result = result || 1;
3937		var num = 0;
3938
3939		for ( ; cur; cur = cur[dir] ) {
3940			if ( cur.nodeType === 1 && ++num === result ) {
3941				break;
3942			}
3943		}
3944
3945		return cur;
3946	},
3947
3948	sibling: function( n, elem ) {
3949		var r = [];
3950
3951		for ( ; n; n = n.nextSibling ) {
3952			if ( n.nodeType === 1 && n !== elem ) {
3953				r.push( n );
3954			}
3955		}
3956
3957		return r;
3958	}
3959});
3960var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g,
3961	rleadingWhitespace = /^\s+/,
3962	rxhtmlTag = /(<([\w:]+)[^>]*?)\/>/g,
3963	rselfClosing = /^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,
3964	rtagName = /<([\w:]+)/,
3965	rtbody = /<tbody/i,
3966	rhtml = /<|&#?\w+;/,
3967	rnocache = /<script|<object|<embed|<option|<style/i,
3968	rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,  // checked="checked" or checked (html5)
3969	fcloseTag = function( all, front, tag ) {
3970		return rselfClosing.test( tag ) ?
3971			all :
3972			front + "></" + tag + ">";
3973	},
3974	wrapMap = {
3975		option: [ 1, "<select multiple='multiple'>", "</select>" ],
3976		legend: [ 1, "<fieldset>", "</fieldset>" ],
3977		thead: [ 1, "<table>", "</table>" ],
3978		tr: [ 2, "<table><tbody>", "</tbody></table>" ],
3979		td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
3980		col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
3981		area: [ 1, "<map>", "</map>" ],
3982		_default: [ 0, "", "" ]
3983	};
3984
3985wrapMap.optgroup = wrapMap.option;
3986wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
3987wrapMap.th = wrapMap.td;
3988
3989// IE can't serialize <link> and <script> tags normally
3990if ( !jQuery.support.htmlSerialize ) {
3991	wrapMap._default = [ 1, "div<div>", "</div>" ];
3992}
3993
3994jQuery.fn.extend({
3995	text: function( text ) {
3996		if ( jQuery.isFunction(text) ) {
3997			return this.each(function(i) {
3998				var self = jQuery(this);
3999				self.text( text.call(this, i, self.text()) );
4000			});
4001		}
4002
4003		if ( typeof text !== "object" && text !== undefined ) {
4004			return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
4005		}
4006
4007		return jQuery.text( this );
4008	},
4009
4010	wrapAll: function( html ) {
4011		if ( jQuery.isFunction( html ) ) {
4012			return this.each(function(i) {
4013				jQuery(this).wrapAll( html.call(this, i) );
4014			});
4015		}
4016
4017		if ( this[0] ) {
4018			// The elements to wrap the target around
4019			var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
4020
4021			if ( this[0].parentNode ) {
4022				wrap.insertBefore( this[0] );
4023			}
4024
4025			wrap.map(function() {
4026				var elem = this;
4027
4028				while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
4029					elem = elem.firstChild;
4030				}
4031
4032				return elem;
4033			}).append(this);
4034		}
4035
4036		return this;
4037	},
4038
4039	wrapInner: function( html ) {
4040		if ( jQuery.isFunction( html ) ) {
4041			return this.each(function(i) {
4042				jQuery(this).wrapInner( html.call(this, i) );
4043			});
4044		}
4045
4046		return this.each(function() {
4047			var self = jQuery( this ), contents = self.contents();
4048
4049			if ( contents.length ) {
4050				contents.wrapAll( html );
4051
4052			} else {
4053				self.append( html );
4054			}
4055		});
4056	},
4057
4058	wrap: function( html ) {
4059		return this.each(function() {
4060			jQuery( this ).wrapAll( html );
4061		});
4062	},
4063
4064	unwrap: function() {
4065		return this.parent().each(function() {
4066			if ( !jQuery.nodeName( this, "body" ) ) {
4067				jQuery( this ).replaceWith( this.childNodes );
4068			}
4069		}).end();
4070	},
4071
4072	append: function() {
4073		return this.domManip(arguments, true, function( elem ) {
4074			if ( this.nodeType === 1 ) {
4075				this.appendChild( elem );
4076			}
4077		});
4078	},
4079
4080	prepend: function() {
4081		return this.domManip(arguments, true, function( elem ) {
4082			if ( this.nodeType === 1 ) {
4083				this.insertBefore( elem, this.firstChild );
4084			}
4085		});
4086	},
4087
4088	before: function() {
4089		if ( this[0] && this[0].parentNode ) {
4090			return this.domManip(arguments, false, function( elem ) {
4091				this.parentNode.insertBefore( elem, this );
4092			});
4093		} else if ( arguments.length ) {
4094			var set = jQuery(arguments[0]);
4095			set.push.apply( set, this.toArray() );
4096			return this.pushStack( set, "before", arguments );
4097		}
4098	},
4099
4100	after: function() {
4101		if ( this[0] && this[0].parentNode ) {
4102			return this.domManip(arguments, false, function( elem ) {
4103				this.parentNode.insertBefore( elem, this.nextSibling );
4104			});
4105		} else if ( arguments.length ) {
4106			var set = this.pushStack( this, "after", arguments );
4107			set.push.apply( set, jQuery(arguments[0]).toArray() );
4108			return set;
4109		}
4110	},
4111
4112	// keepData is for internal use only--do not document
4113	remove: function( selector, keepData ) {
4114		for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
4115			if ( !selector || jQuery.filter( selector, [ elem ] ).length ) {
4116				if ( !keepData && elem.nodeType === 1 ) {
4117					jQuery.cleanData( elem.getElementsByTagName("*") );
4118					jQuery.cleanData( [ elem ] );
4119				}
4120
4121				if ( elem.parentNode ) {
4122					 elem.parentNode.removeChild( elem );
4123				}
4124			}
4125		}
4126
4127		return this;
4128	},
4129
4130	empty: function() {
4131		for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
4132			// Remove element nodes and prevent memory leaks
4133			if ( elem.nodeType === 1 ) {
4134				jQuery.cleanData( elem.getElementsByTagName("*") );
4135			}
4136
4137			// Remove any remaining nodes
4138			while ( elem.firstChild ) {
4139				elem.removeChild( elem.firstChild );
4140			}
4141		}
4142
4143		return this;
4144	},
4145
4146	clone: function( events ) {
4147		// Do the clone
4148		var ret = this.map(function() {
4149			if ( !jQuery.support.noCloneEvent && !jQuery.isXMLDoc(this) ) {
4150				// IE copies events bound via attachEvent when
4151				// using cloneNode. Calling detachEvent on the
4152				// clone will also remove the events from the orignal
4153				// In order to get around this, we use innerHTML.
4154				// Unfortunately, this means some modifications to
4155				// attributes in IE that are actually only stored
4156				// as properties will not be copied (such as the
4157				// the name attribute on an input).
4158				var html = this.outerHTML, ownerDocument = this.ownerDocument;
4159				if ( !html ) {
4160					var div = ownerDocument.createElement("div");
4161					div.appendChild( this.cloneNode(true) );
4162					html = div.innerHTML;
4163				}
4164
4165				return jQuery.clean([html.replace(rinlinejQuery, "")
4166					// Handle the case in IE 8 where action=/test/> self-closes a tag
4167					.replace(/=([^="'>\s]+\/)>/g, '="$1">')
4168					.replace(rleadingWhitespace, "")], ownerDocument)[0];
4169			} else {
4170				return this.cloneNode(true);
4171			}
4172		});
4173
4174		// Copy the events from the original to the clone
4175		if ( events === true ) {
4176			cloneCopyEvent( this, ret );
4177			cloneCopyEvent( this.find("*"), ret.find("*") );
4178		}
4179
4180		// Return the cloned set
4181		return ret;
4182	},
4183
4184	html: function( value ) {
4185		if ( value === undefined ) {
4186			return this[0] && this[0].nodeType === 1 ?
4187				this[0].innerHTML.replace(rinlinejQuery, "") :
4188				null;
4189
4190		// See if we can take a shortcut and just use innerHTML
4191		} else if ( typeof value === "string" && !rnocache.test( value ) &&
4192			(jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) &&
4193			!wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) {
4194
4195			value = value.replace(rxhtmlTag, fcloseTag);
4196
4197			try {
4198				for ( var i = 0, l = this.length; i < l; i++ ) {
4199					// Remove element nodes and prevent memory leaks
4200					if ( this[i].nodeType === 1 ) {
4201						jQuery.cleanData( this[i].getElementsByTagName("*") );
4202						this[i].innerHTML = value;
4203					}
4204				}
4205
4206			// If using innerHTML throws an exception, use the fallback method
4207			} catch(e) {
4208				this.empty().append( value );
4209			}
4210
4211		} else if ( jQuery.isFunction( value ) ) {
4212			this.each(function(i){
4213				var self = jQuery(this), old = self.html();
4214				self.empty().append(function(){
4215					return value.call( this, i, old );
4216				});
4217			});
4218
4219		} else {
4220			this.empty().append( value );
4221		}
4222
4223		return this;
4224	},
4225
4226	replaceWith: function( value ) {
4227		if ( this[0] && this[0].parentNode ) {
4228			// Make sure that the elements are removed from the DOM before they are inserted
4229			// this can help fix replacing a parent with child elements
4230			if ( jQuery.isFunction( value ) ) {
4231				return this.each(function(i) {
4232					var self = jQuery(this), old = self.html();
4233					self.replaceWith( value.call( this, i, old ) );
4234				});
4235			}
4236
4237			if ( typeof value !== "string" ) {
4238				value = jQuery(value).detach();
4239			}
4240
4241			return this.each(function() {
4242				var next = this.nextSibling, parent = this.parentNode;
4243
4244				jQuery(this).remove();
4245
4246				if ( next ) {
4247					jQuery(next).before( value );
4248				} else {
4249					jQuery(parent).append( value );
4250				}
4251			});
4252		} else {
4253			return this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value );
4254		}
4255	},
4256
4257	detach: function( selector ) {
4258		return this.remove( selector, true );
4259	},
4260
4261	domManip: function( args, table, callback ) {
4262		var results, first, value = args[0], scripts = [], fragment, parent;
4263
4264		// We can't cloneNode fragments that contain checked, in WebKit
4265		if ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === "string" && rchecked.test( value ) ) {
4266			return this.each(function() {
4267				jQuery(this).domManip( args, table, callback, true );
4268			});
4269		}
4270
4271		if ( jQuery.isFunction(value) ) {
4272			return this.each(function(i) {
4273				var self = jQuery(this);
4274				args[0] = value.call(this, i, table ? self.html() : undefined);
4275				self.domManip( args, table, callback );
4276			});
4277		}
4278
4279		if ( this[0] ) {
4280			parent = value && value.parentNode;
4281
4282			// If we're in a fragment, just use that instead of building a new one
4283			if ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) {
4284				results = { fragment: parent };
4285
4286			} else {
4287				results = buildFragment( args, this, scripts );
4288			}
4289
4290			fragment = results.fragment;
4291
4292			if ( fragment.childNodes.length === 1 ) {
4293				first = fragment = fragment.firstChild;
4294			} else {
4295				first = fragment.firstChild;
4296			}
4297
4298			if ( first ) {
4299				table = table && jQuery.nodeName( first, "tr" );
4300
4301				for ( var i = 0, l = this.length; i < l; i++ ) {
4302					callback.call(
4303						table ?
4304							root(this[i], first) :
4305							this[i],
4306						i > 0 || results.cacheable || this.length > 1  ?
4307							fragment.cloneNode(true) :
4308							fragment
4309					);
4310				}
4311			}
4312
4313			if ( scripts.length ) {
4314				jQuery.each( scripts, evalScript );
4315			}
4316		}
4317
4318		return this;
4319
4320		function root( elem, cur ) {
4321			return jQuery.nodeName(elem, "table") ?
4322				(elem.getElementsByTagName("tbody")[0] ||
4323				elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
4324				elem;
4325		}
4326	}
4327});
4328
4329function cloneCopyEvent(orig, ret) {
4330	var i = 0;
4331
4332	ret.each(function() {
4333		if ( this.nodeName !== (orig[i] && orig[i].nodeName) ) {
4334			return;
4335		}
4336
4337		var oldData = jQuery.data( orig[i++] ), curData = jQuery.data( this, oldData ), events = oldData && oldData.events;
4338
4339		if ( events ) {
4340			delete curData.handle;
4341			curData.events = {};
4342
4343			for ( var type in events ) {
4344				for ( var handler in events[ type ] ) {
4345					jQuery.event.add( this, type, events[ type ][ handler ], events[ type ][ handler ].data );
4346				}
4347			}
4348		}
4349	});
4350}
4351
4352function buildFragment( args, nodes, scripts ) {
4353	var fragment, cacheable, cacheresults,
4354		doc = (nodes && nodes[0] ? nodes[0].ownerDocument || nodes[0] : document);
4355
4356	// Only cache "small" (1/2 KB) strings that are associated with the main document
4357	// Cloning options loses the selected state, so don't cache them
4358	// IE 6 doesn't like it when you put <object> or <embed> elements in a fragment
4359	// Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache
4360	if ( args.length === 1 && typeof args[0] === "string" && args[0].length < 512 && doc === document &&
4361		!rnocache.test( args[0] ) && (jQuery.support.checkClone || !rchecked.test( args[0] )) ) {
4362
4363		cacheable = true;
4364		cacheresults = jQuery.fragments[ args[0] ];
4365		if ( cacheresults ) {
4366			if ( cacheresults !== 1 ) {
4367				fragment = cacheresults;
4368			}
4369		}
4370	}
4371
4372	if ( !fragment ) {
4373		fragment = doc.createDocumentFragment();
4374		jQuery.clean( args, doc, fragment, scripts );
4375	}
4376
4377	if ( cacheable ) {
4378		jQuery.fragments[ args[0] ] = cacheresults ? fragment : 1;
4379	}
4380
4381	return { fragment: fragment, cacheable: cacheable };
4382}
4383
4384jQuery.fragments = {};
4385
4386jQuery.each({
4387	appendTo: "append",
4388	prependTo: "prepend",
4389	insertBefore: "before",
4390	insertAfter: "after",
4391	replaceAll: "replaceWith"
4392}, function( name, original ) {
4393	jQuery.fn[ name ] = function( selector ) {
4394		var ret = [], insert = jQuery( selector ),
4395			parent = this.length === 1 && this[0].parentNode;
4396
4397		if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {
4398			insert[ original ]( this[0] );
4399			return this;
4400
4401		} else {
4402			for ( var i = 0, l = insert.length; i < l; i++ ) {
4403				var elems = (i > 0 ? this.clone(true) : this).get();
4404				jQuery.fn[ original ].apply( jQuery(insert[i]), elems );
4405				ret = ret.concat( elems );
4406			}
4407
4408			return this.pushStack( ret, name, insert.selector );
4409		}
4410	};
4411});
4412
4413jQuery.extend({
4414	clean: function( elems, context, fragment, scripts ) {
4415		context = context || document;
4416
4417		// !context.createElement fails in IE with an error but returns typeof 'object'
4418		if ( typeof context.createElement === "undefined" ) {
4419			context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
4420		}
4421
4422		var ret = [];
4423
4424		for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
4425			if ( typeof elem === "number" ) {
4426				elem += "";
4427			}
4428
4429			if ( !elem ) {
4430				continue;
4431			}
4432
4433			// Convert html string into DOM nodes
4434			if ( typeof elem === "string" && !rhtml.test( elem ) ) {
4435				elem = context.createTextNode( elem );
4436
4437			} else if ( typeof elem === "string" ) {
4438				// Fix "XHTML"-style tags in all browsers
4439				elem = elem.replace(rxhtmlTag, fcloseTag);
4440
4441				// Trim whitespace, otherwise indexOf won't work as expected
4442				var tag = (rtagName.exec( elem ) || ["", ""])[1].toLowerCase(),
4443					wrap = wrapMap[ tag ] || wrapMap._default,
4444					depth = wrap[0],
4445					div = context.createElement("div");
4446
4447				// Go to html and back, then peel off extra wrappers
4448				div.innerHTML = wrap[1] + elem + wrap[2];
4449
4450				// Move to the right depth
4451				while ( depth-- ) {
4452					div = div.lastChild;
4453				}
4454
4455				// Remove IE's autoinserted <tbody> from table fragments
4456				if ( !jQuery.support.tbody ) {
4457
4458					// String was a <table>, *may* have spurious <tbody>
4459					var hasBody = rtbody.test(elem),
4460						tbody = tag === "table" && !hasBody ?
4461							div.firstChild && div.firstChild.childNodes :
4462
4463							// String was a bare <thead> or <tfoot>
4464							wrap[1] === "<table>" && !hasBody ?
4465								div.childNodes :
4466								[];
4467
4468					for ( var j = tbody.length - 1; j >= 0 ; --j ) {
4469						if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) {
4470							tbody[ j ].parentNode.removeChild( tbody[ j ] );
4471						}
4472					}
4473
4474				}
4475
4476				// IE completely kills leading whitespace when innerHTML is used
4477				if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
4478					div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );
4479				}
4480
4481				elem = div.childNodes;
4482			}
4483
4484			if ( elem.nodeType ) {
4485				ret.push( elem );
4486			} else {
4487				ret = jQuery.merge( ret, elem );
4488			}
4489		}
4490
4491		if ( fragment ) {
4492			for ( var i = 0; ret[i]; i++ ) {
4493				if ( scripts && jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
4494					scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
4495
4496				} else {
4497					if ( ret[i].nodeType === 1 ) {
4498						ret.splice.apply( ret, [i + 1, 0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))) );
4499					}
4500					fragment.appendChild( ret[i] );
4501				}
4502			}
4503		}
4504
4505		return ret;
4506	},
4507
4508	cleanData: function( elems ) {
4509		var data, id, cache = jQuery.cache,
4510			special = jQuery.event.special,
4511			deleteExpando = jQuery.support.deleteExpando;
4512
4513		for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
4514			id = elem[ jQuery.expando ];
4515
4516			if ( id ) {
4517				data = cache[ id ];
4518
4519				if ( data.events ) {
4520					for ( var type in data.events ) {
4521						if ( special[ type ] ) {
4522							jQuery.event.remove( elem, type );
4523
4524						} else {
4525							removeEvent( elem, type, data.handle );
4526						}
4527					}
4528				}
4529
4530				if ( deleteExpando ) {
4531					delete elem[ jQuery.expando ];
4532
4533				} else if ( elem.removeAttribute ) {
4534					elem.removeAttribute( jQuery.expando );
4535				}
4536
4537				delete cache[ id ];
4538			}
4539		}
4540	}
4541});
4542// exclude the following css properties to add px
4543var rexclude = /z-?index|font-?weight|opacity|zoom|line-?height/i,
4544	ralpha = /alpha\([^)]*\)/,
4545	ropacity = /opacity=([^)]*)/,
4546	rfloat = /float/i,
4547	rdashAlpha = /-([a-z])/ig,
4548	rupper = /([A-Z])/g,
4549	rnumpx = /^-?\d+(?:px)?$/i,
4550	rnum = /^-?\d/,
4551
4552	cssShow = { position: "absolute", visibility: "hidden", display:"block" },
4553	cssWidth = [ "Left", "Right" ],
4554	cssHeight = [ "Top", "Bottom" ],
4555
4556	// cache check for defaultView.getComputedStyle
4557	getComputedStyle = document.defaultView && document.defaultView.getComputedStyle,
4558	// normalize float css property
4559	styleFloat = jQuery.support.cssFloat ? "cssFloat" : "styleFloat",
4560	fcamelCase = function( all, letter ) {
4561		return letter.toUpperCase();
4562	};
4563
4564jQuery.fn.css = function( name, value ) {
4565	return access( this, name, value, true, function( elem, name, value ) {
4566		if ( value === undefined ) {
4567			return jQuery.curCSS( elem, name );
4568		}
4569
4570		if ( typeof value === "number" && !rexclude.test(name) ) {
4571			value += "px";
4572		}
4573
4574		jQuery.style( elem, name, value );
4575	});
4576};
4577
4578jQuery.extend({
4579	style: function( elem, name, value ) {
4580		// don't set styles on text and comment nodes
4581		if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
4582			return undefined;
4583		}
4584
4585		// ignore negative width and height values #1599
4586		if ( (name === "width" || name === "height") && parseFloat(value) < 0 ) {
4587			value = undefined;
4588		}
4589
4590		var style = elem.style || elem, set = value !== undefined;
4591
4592		// IE uses filters for opacity
4593		if ( !jQuery.support.opacity && name === "opacity" ) {
4594			if ( set ) {
4595				// IE has trouble with opacity if it does not have layout
4596				// Force it by setting the zoom level
4597				style.zoom = 1;
4598
4599				// Set the alpha filter to set the opacity
4600				var opacity = parseInt( value, 10 ) + "" === "NaN" ? "" : "alpha(opacity=" + value * 100 + ")";
4601				var filter = style.filter || jQuery.curCSS( elem, "filter" ) || "";
4602				style.filter = ralpha.test(filter) ? filter.replace(ralpha, opacity) : opacity;
4603			}
4604
4605			return style.filter && style.filter.indexOf("opacity=") >= 0 ?
4606				(parseFloat( ropacity.exec(style.filter)[1] ) / 100) + "":
4607				"";
4608		}
4609
4610		// Make sure we're using the right name for getting the float value
4611		if ( rfloat.test( name ) ) {
4612			name = styleFloat;
4613		}
4614
4615		name = name.replace(rdashAlpha, fcamelCase);
4616
4617		if ( set ) {
4618			style[ name ] = value;
4619		}
4620
4621		return style[ name ];
4622	},
4623
4624	css: function( elem, name, force, extra ) {
4625		if ( name === "width" || name === "height" ) {
4626			var val, props = cssShow, which = name === "width" ? cssWidth : cssHeight;
4627
4628			function getWH() {
4629				val = name === "width" ? elem.offsetWidth : elem.offsetHeight;
4630
4631				if ( extra === "border" ) {
4632					return;
4633				}
4634
4635				jQuery.each( which, function() {
4636					if ( !extra ) {
4637						val -= parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0;
4638					}
4639
4640					if ( extra === "margin" ) {
4641						val += parseFloat(jQuery.curCSS( elem, "margin" + this, true)) || 0;
4642					} else {
4643						val -= parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0;
4644					}
4645				});
4646			}
4647
4648			if ( elem.offsetWidth !== 0 ) {
4649				getWH();
4650			} else {
4651				jQuery.swap( elem, props, getWH );
4652			}
4653
4654			return Math.max(0, Math.round(val));
4655		}
4656
4657		return jQuery.curCSS( elem, name, force );
4658	},
4659
4660	curCSS: function( elem, name, force ) {
4661		var ret, style = elem.style, filter;
4662
4663		// IE uses filters for opacity
4664		if ( !jQuery.support.opacity && name === "opacity" && elem.currentStyle ) {
4665			ret = ropacity.test(elem.currentStyle.filter || "") ?
4666				(parseFloat(RegExp.$1) / 100) + "" :
4667				"";
4668
4669			return ret === "" ?
4670				"1" :
4671				ret;
4672		}
4673
4674		// Make sure we're using the right name for getting the float value
4675		if ( rfloat.test( name ) ) {
4676			name = styleFloat;
4677		}
4678
4679		if ( !force && style && style[ name ] ) {
4680			ret = style[ name ];
4681
4682		} else if ( getComputedStyle ) {
4683
4684			// Only "float" is needed here
4685			if ( rfloat.test( name ) ) {
4686				name = "float";
4687			}
4688
4689			name = name.replace( rupper, "-$1" ).toLowerCase();
4690
4691			var defaultView = elem.ownerDocument.defaultView;
4692
4693			if ( !defaultView ) {
4694				return null;
4695			}
4696
4697			var computedStyle = defaultView.getComputedStyle( elem, null );
4698
4699			if ( computedStyle ) {
4700				ret = computedStyle.getPropertyValue( name );
4701			}
4702
4703			// We should always get a number back from opacity
4704			if ( name === "opacity" && ret === "" ) {
4705				ret = "1";
4706			}
4707
4708		} else if ( elem.currentStyle ) {
4709			var camelCase = name.replace(rdashAlpha, fcamelCase);
4710
4711			ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ];
4712
4713			// From the awesome hack by Dean Edwards
4714			// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
4715
4716			// If we're not dealing with a regular pixel number
4717			// but a number that has a weird ending, we need to convert it to pixels
4718			if ( !rnumpx.test( ret ) && rnum.test( ret ) ) {
4719				// Remember the original values
4720				var left = style.left, rsLeft = elem.runtimeStyle.left;
4721
4722				// Put in the new values to get a computed value out
4723				elem.runtimeStyle.left = elem.currentStyle.left;
4724				style.left = camelCase === "fontSize" ? "1em" : (ret || 0);
4725				ret = style.pixelLeft + "px";
4726
4727				// Revert the changed values
4728				style.left = left;
4729				elem.runtimeStyle.left = rsLeft;
4730			}
4731		}
4732
4733		return ret;
4734	},
4735
4736	// A method for quickly swapping in/out CSS properties to get correct calculations
4737	swap: function( elem, options, callback ) {
4738		var old = {};
4739
4740		// Remember the old values, and insert the new ones
4741		for ( var name in options ) {
4742			old[ name ] = elem.style[ name ];
4743			elem.style[ name ] = options[ name ];
4744		}
4745
4746		callback.call( elem );
4747
4748		// Revert the old values
4749		for ( var name in options ) {
4750			elem.style[ name ] = old[ name ];
4751		}
4752	}
4753});
4754
4755if ( jQuery.expr && jQuery.expr.filters ) {
4756	jQuery.expr.filters.hidden = function( elem ) {
4757		var width = elem.offsetWidth, height = elem.offsetHeight,
4758			skip = elem.nodeName.toLowerCase() === "tr";
4759
4760		return width === 0 && height === 0 && !skip ?
4761			true :
4762			width > 0 && height > 0 && !skip ?
4763				false :
4764				jQuery.curCSS(elem, "display") === "none";
4765	};
4766
4767	jQuery.expr.filters.visible = function( elem ) {
4768		return !jQuery.expr.filters.hidden( elem );
4769	};
4770}
4771var jsc = now(),
4772	rscript = /<script(.|\s)*?\/script>/gi,
4773	rselectTextarea = /select|textarea/i,
4774	rinput = /color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,
4775	jsre = /=\?(&|$)/,
4776	rquery = /\?/,
4777	rts = /(\?|&)_=.*?(&|$)/,
4778	rurl = /^(\w+:)?\/\/([^\/?#]+)/,
4779	r20 = /%20/g,
4780
4781	// Keep a copy of the old load method
4782	_load = jQuery.fn.load;
4783
4784jQuery.fn.extend({
4785	load: function( url, params, callback ) {
4786		if ( typeof url !== "string" ) {
4787			return _load.call( this, url );
4788
4789		// Don't do a request if no elements are being requested
4790		} else if ( !this.length ) {
4791			return this;
4792		}
4793
4794		var off = url.indexOf(" ");
4795		if ( off >= 0 ) {
4796			var selector = url.slice(off, url.length);
4797			url = url.slice(0, off);
4798		}
4799
4800		// Default to a GET request
4801		var type = "GET";
4802
4803		// If the second parameter was provided
4804		if ( params ) {
4805			// If it's a function
4806			if ( jQuery.isFunction( params ) ) {
4807				// We assume that it's the callback
4808				callback = params;
4809				params = null;
4810
4811			// Otherwise, build a param string
4812			} else if ( typeof params === "object" ) {
4813				params = jQuery.param( params, jQuery.ajaxSettings.traditional );
4814				type = "POST";
4815			}
4816		}
4817
4818		var self = this;
4819
4820		// Request the remote document
4821		jQuery.ajax({
4822			url: url,
4823			type: type,
4824			dataType: "html",
4825			data: params,
4826			complete: function( res, status ) {
4827				// If successful, inject the HTML into all the matched elements
4828				if ( status === "success" || status === "notmodified" ) {
4829					// See if a selector was specified
4830					self.html( selector ?
4831						// Create a dummy div to hold the results
4832						jQuery("<div />")
4833							// inject the contents of the document in, removing the scripts
4834							// to avoid any 'Permission Denied' errors in IE
4835							.append(res.responseText.replace(rscript, ""))
4836
4837							// Locate the specified elements
4838							.find(selector) :
4839
4840						// If not, just inject the full result
4841						res.responseText );
4842				}
4843
4844				if ( callback ) {
4845					self.each( callback, [res.responseText, status, res] );
4846				}
4847			}
4848		});
4849
4850		return this;
4851	},
4852
4853	serialize: function() {
4854		return jQuery.param(this.serializeArray());
4855	},
4856	serializeArray: function() {
4857		return this.map(function() {
4858			return this.elements ? jQuery.makeArray(this.elements) : this;
4859		})
4860		.filter(function() {
4861			return this.name && !this.disabled &&
4862				(this.checked || rselectTextarea.test(this.nodeName) ||
4863					rinput.test(this.type));
4864		})
4865		.map(function( i, elem ) {
4866			var val = jQuery(this).val();
4867
4868			return val == null ?
4869				null :
4870				jQuery.isArray(val) ?
4871					jQuery.map( val, function( val, i ) {
4872						return { name: elem.name, value: val };
4873					}) :
4874					{ name: elem.name, value: val };
4875		}).get();
4876	}
4877});
4878
4879// Attach a bunch of functions for handling common AJAX events
4880jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "), function( i, o ) {
4881	jQuery.fn[o] = function( f ) {
4882		return this.bind(o, f);
4883	};
4884});
4885
4886jQuery.extend({
4887
4888	get: function( url, data, callback, type ) {
4889		// shift arguments if data argument was omited
4890		if ( jQuery.isFunction( data ) ) {
4891			type = type || callback;
4892			callback = data;
4893			data = null;
4894		}
4895
4896		return jQuery.ajax({
4897			type: "GET",
4898			url: url,
4899			data: data,
4900			success: callback,
4901			dataType: type
4902		});
4903	},
4904
4905	getScript: function( url, callback ) {
4906		return jQuery.get(url, null, callback, "script");
4907	},
4908
4909	getJSON: function( url, data, callback ) {
4910		return jQuery.get(url, data, callback, "json");
4911	},
4912
4913	post: function( url, data, callback, type ) {
4914		// shift arguments if data argument was omited
4915		if ( jQuery.isFunction( data ) ) {
4916			type = type || callback;
4917			callback = data;
4918			data = {};
4919		}
4920
4921		return jQuery.ajax({
4922			type: "POST",
4923			url: url,
4924			data: data,
4925			success: callback,
4926			dataType: type
4927		});
4928	},
4929
4930	ajaxSetup: function( settings ) {
4931		jQuery.extend( jQuery.ajaxSettings, settings );
4932	},
4933
4934	ajaxSettings: {
4935		url: location.href,
4936		global: true,
4937		type: "GET",
4938		contentType: "application/x-www-form-urlencoded",
4939		processData: true,
4940		async: true,
4941		/*
4942		timeout: 0,
4943		data: null,
4944		username: null,
4945		password: null,
4946		traditional: false,
4947		*/
4948		// Create the request object; Microsoft failed to properly
4949		// implement the XMLHttpRequest in IE7 (can't request local files),
4950		// so we use the ActiveXObject when it is available
4951		// This function can be overriden by calling jQuery.ajaxSetup
4952		xhr: window.XMLHttpRequest && (window.location.protocol !== "file:" || !window.ActiveXObject) ?
4953			function() {
4954				return new window.XMLHttpRequest();
4955			} :
4956			function() {
4957				try {
4958					return new window.ActiveXObject("Microsoft.XMLHTTP");
4959				} catch(e) {}
4960			},
4961		accepts: {
4962			xml: "application/xml, text/xml",
4963			html: "text/html",
4964			script: "text/javascript, application/javascript",
4965			json: "application/json, text/javascript",
4966			text: "text/plain",
4967			_default: "*/*"
4968		}
4969	},
4970
4971	// Last-Modified header cache for next request
4972	lastModified: {},
4973	etag: {},
4974
4975	ajax: function( origSettings ) {
4976		var s = jQuery.extend(true, {}, jQuery.ajaxSettings, origSettings);
4977
4978		var jsonp, status, data,
4979			callbackContext = origSettings && origSettings.context || s,
4980			type = s.type.toUpperCase();
4981
4982		// convert data if not already a string
4983		if ( s.data && s.processData && typeof s.data !== "string" ) {
4984			s.data = jQuery.param( s.data, s.traditional );
4985		}
4986
4987		// Handle JSONP Parameter Callbacks
4988		if ( s.dataType === "jsonp" ) {
4989			if ( type === "GET" ) {
4990				if ( !jsre.test( s.url ) ) {
4991					s.url += (rquery.test( s.url ) ? "&" : "?") + (s.jsonp || "callback") + "=?";
4992				}
4993			} else if ( !s.data || !jsre.test(s.data) ) {
4994				s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
4995			}
4996			s.dataType = "json";
4997		}
4998
4999		// Build temporary JSONP function
5000		if ( s.dataType === "json" && (s.data && jsre.test(s.data) || jsre.test(s.url)) ) {
5001			jsonp = s.jsonpCallback || ("jsonp" + jsc++);
5002
5003			// Replace the =? sequence both in the query string and the data
5004			if ( s.data ) {
5005				s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");
5006			}
5007
5008			s.url = s.url.replace(jsre, "=" + jsonp + "$1");
5009
5010			// We need to make sure
5011			// that a JSONP style response is executed properly
5012			s.dataType = "script";
5013
5014			// Handle JSONP-style loading
5015			window[ jsonp ] = window[ jsonp ] || function( tmp ) {
5016				data = tmp;
5017				success();
5018				complete();
5019				// Garbage collect
5020				window[ jsonp ] = undefined;
5021
5022				try {
5023					delete window[ jsonp ];
5024				} catch(e) {}
5025
5026				if ( head ) {
5027					head.removeChild( script );
5028				}
5029			};
5030		}
5031
5032		if ( s.dataType === "script" && s.cache === null ) {
5033			s.cache = false;
5034		}
5035
5036		if ( s.cache === false && type === "GET" ) {
5037			var ts = now();
5038
5039			// try replacing _= if it is there
5040			var ret = s.url.replace(rts, "$1_=" + ts + "$2");
5041
5042			// if nothing was replaced, add timestamp to the end
5043			s.url = ret + ((ret === s.url) ? (rquery.test(s.url) ? "&" : "?") + "_=" + ts : "");
5044		}
5045
5046		// If data is available, append data to url for get requests
5047		if ( s.data && type === "GET" ) {
5048			s.url += (rquery.test(s.url) ? "&" : "?") + s.data;
5049		}
5050
5051		// Watch for a new set of requests
5052		if ( s.global && ! jQuery.active++ ) {
5053			jQuery.event.trigger( "ajaxStart" );
5054		}
5055
5056		// Matches an absolute URL, and saves the domain
5057		var parts = rurl.exec( s.url ),
5058			remote = parts && (parts[1] && parts[1] !== location.protocol || parts[2] !== location.host);
5059
5060		// If we're requesting a remote document
5061		// and trying to load JSON or Script with a GET
5062		if ( s.dataType === "script" && type === "GET" && remote ) {
5063			var head = document.getElementsByTagName("head")[0] || document.documentElement;
5064			var script = document.createElement("script");
5065			script.src = s.url;
5066			if ( s.scriptCharset ) {
5067				script.charset = s.scriptCharset;
5068			}
5069
5070			// Handle Script loading
5071			if ( !jsonp ) {
5072				var done = false;
5073
5074				// Attach handlers for all browsers
5075				script.onload = script.onreadystatechange = function() {
5076					if ( !done && (!this.readyState ||
5077							this.readyState === "loaded" || this.readyState === "complete") ) {
5078						done = true;
5079						success();
5080						complete();
5081
5082						// Handle memory leak in IE
5083						script.onload = script.onreadystatechange = null;
5084						if ( head && script.parentNode ) {
5085							head.removeChild( script );
5086						}
5087					}
5088				};
5089			}
5090
5091			// Use insertBefore instead of appendChild  to circumvent an IE6 bug.
5092			// This arises when a base node is used (#2709 and #4378).
5093			head.insertBefore( script, head.firstChild );
5094
5095			// We handle everything using the script element injection
5096			return undefined;
5097		}
5098
5099		var requestDone = false;
5100
5101		// Create the request object
5102		var xhr = s.xhr();
5103
5104		if ( !xhr ) {
5105			return;
5106		}
5107
5108		// Open the socket
5109		// Passing null username, generates a login popup on Opera (#2865)
5110		if ( s.username ) {
5111			xhr.open(type, s.url, s.async, s.username, s.password);
5112		} else {
5113			xhr.open(type, s.url, s.async);
5114		}
5115
5116		// Need an extra try/catch for cross domain requests in Firefox 3
5117		try {
5118			// Set the correct header, if data is being sent
5119			if ( s.data || origSettings && origSettings.contentType ) {
5120				xhr.setRequestHeader("Content-Type", s.contentType);
5121			}
5122
5123			// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
5124			if ( s.ifModified ) {
5125				if ( jQuery.lastModified[s.url] ) {
5126					xhr.setRequestHeader("If-Modified-Since", jQuery.lastModified[s.url]);
5127				}
5128
5129				if ( jQuery.etag[s.url] ) {
5130					xhr.setRequestHeader("If-None-Match", jQuery.etag[s.url]);
5131				}
5132			}
5133
5134			// Set header so the called script knows that it's an XMLHttpRequest
5135			// Only send the header if it's not a remote XHR
5136			if ( !remote ) {
5137				xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
5138			}
5139
5140			// Set the Accepts header for the server, depending on the dataType
5141			xhr.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ?
5142				s.accepts[ s.dataType ] + ", */*" :
5143				s.accepts._default );
5144		} catch(e) {}
5145
5146		// Allow custom headers/mimetypes and early abort
5147		if ( s.beforeSend && s.beforeSend.call(callbackContext, xhr, s) === false ) {
5148			// Handle the global AJAX counter
5149			if ( s.global && ! --jQuery.active ) {
5150				jQuery.event.trigger( "ajaxStop" );
5151			}
5152
5153			// close opended socket
5154			xhr.abort();
5155			return false;
5156		}
5157
5158		if ( s.global ) {
5159			trigger("ajaxSend", [xhr, s]);
5160		}
5161
5162		// Wait for a response to come back
5163		var onreadystatechange = xhr.onreadystatechange = function( isTimeout ) {
5164			// The request was aborted
5165			if ( !xhr || xhr.readyState === 0 || isTimeout === "abort" ) {
5166				// Opera doesn't call onreadystatechange before this point
5167				// so we simulate the call
5168				if ( !requestDone ) {
5169					complete();
5170				}
5171
5172				requestDone = true;
5173				if ( xhr ) {
5174					xhr.onreadystatechange = jQuery.noop;
5175				}
5176
5177			// The transfer is complete and the data is available, or the request timed out
5178			} else if ( !requestDone && xhr && (xhr.readyState === 4 || isTimeout === "timeout") ) {
5179				requestDone = true;
5180				xhr.onreadystatechange = jQuery.noop;
5181
5182				status = isTimeout === "timeout" ?
5183					"timeout" :
5184					!jQuery.httpSuccess( xhr ) ?
5185						"error" :
5186						s.ifModified && jQuery.httpNotModified( xhr, s.url ) ?
5187							"notmodified" :
5188							"success";
5189
5190				var errMsg;
5191
5192				if ( status === "success" ) {
5193					// Watch for, and catch, XML document parse errors
5194					try {
5195						// process the data (runs the xml through httpData regardless of callback)
5196						data = jQuery.httpData( xhr, s.dataType, s );
5197					} catch(err) {
5198						status = "parsererror";
5199						errMsg = err;
5200					}
5201				}
5202
5203				// Make sure that the request was successful or notmodified
5204				if ( status === "success" || status === "notmodified" ) {
5205					// JSONP handles its own success callback
5206					if ( !jsonp ) {
5207						success();
5208					}
5209				} else {
5210					jQuery.handleError(s, xhr, status, errMsg);
5211				}
5212
5213				// Fire the complete handlers
5214				complete();
5215
5216				if ( isTimeout === "timeout" ) {
5217					xhr.abort();
5218				}
5219
5220				// Stop memory leaks
5221				if ( s.async ) {
5222					xhr = null;
5223				}
5224			}
5225		};
5226
5227		// Override the abort handler, if we can (IE doesn't allow it, but that's OK)
5228		// Opera doesn't fire onreadystatechange at all on abort
5229		try {
5230			var oldAbort = xhr.abort;
5231			xhr.abort = function() {
5232				if ( xhr ) {
5233					oldAbort.call( xhr );
5234				}
5235
5236				onreadystatechange( "abort" );
5237			};
5238		} catch(e) { }
5239
5240		// Timeout checker
5241		if ( s.async && s.timeout > 0 ) {
5242			setTimeout(function() {
5243				// Check to see if the request is still happening
5244				if ( xhr && !requestDone ) {
5245					onreadystatechange( "timeout" );
5246				}
5247			}, s.timeout);
5248		}
5249
5250		// Send the data
5251		try {
5252			xhr.send( type === "POST" || type === "PUT" || type === "DELETE" ? s.data : null );
5253		} catch(e) {
5254			jQuery.handleError(s, xhr, null, e);
5255			// Fire the complete handlers
5256			complete();
5257		}
5258
5259		// firefox 1.5 doesn't fire statechange for sync requests
5260		if ( !s.async ) {
5261			onreadystatechange();
5262		}
5263
5264		function success() {
5265			// If a local callback was specified, fire it and pass it the data
5266			if ( s.success ) {
5267				s.success.call( callbackContext, data, status, xhr );
5268			}
5269
5270			// Fire the global callback
5271			if ( s.global ) {
5272				trigger( "ajaxSuccess", [xhr, s] );
5273			}
5274		}
5275
5276		function complete() {
5277			// Process result
5278			if ( s.complete ) {
5279				s.complete.call( callbackContext, xhr, status);
5280			}
5281
5282			// The request was completed
5283			if ( s.global ) {
5284				trigger( "ajaxComplete", [xhr, s] );
5285			}
5286
5287			// Handle the global AJAX counter
5288			if ( s.global && ! --jQuery.active ) {
5289				jQuery.event.trigger( "ajaxStop" );
5290			}
5291		}
5292
5293		function trigger(type, args) {
5294			(s.context ? jQuery(s.context) : jQuery.event).trigger(type, args);
5295		}
5296
5297		// return XMLHttpRequest to allow aborting the request etc.
5298		return xhr;
5299	},
5300
5301	handleError: function( s, xhr, status, e ) {
5302		// If a local callback was specified, fire it
5303		if ( s.error ) {
5304			s.error.call( s.context || s, xhr, status, e );
5305		}
5306
5307		// Fire the global callback
5308		if ( s.global ) {
5309			(s.context ? jQuery(s.context) : jQuery.event).trigger( "ajaxError", [xhr, s, e] );
5310		}
5311	},
5312
5313	// Counter for holding the number of active queries
5314	active: 0,
5315
5316	// Determines if an XMLHttpRequest was successful or not
5317	httpSuccess: function( xhr ) {
5318		try {
5319			// IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450
5320			return !xhr.status && location.protocol === "file:" ||
5321				// Opera returns 0 when status is 304
5322				( xhr.status >= 200 && xhr.status < 300 ) ||
5323				xhr.status === 304 || xhr.status === 1223 || xhr.status === 0;
5324		} catch(e) {}
5325
5326		return false;
5327	},
5328
5329	// Determines if an XMLHttpRequest returns NotModified
5330	httpNotModified: function( xhr, url ) {
5331		var lastModified = xhr.getResponseHeader("Last-Modified"),
5332			etag = xhr.getResponseHeader("Etag");
5333
5334		if ( lastModified ) {
5335			jQuery.lastModified[url] = lastModified;
5336		}
5337
5338		if ( etag ) {
5339			jQuery.etag[url] = etag;
5340		}
5341
5342		// Opera returns 0 when status is 304
5343		return xhr.status === 304 || xhr.status === 0;
5344	},
5345
5346	httpData: function( xhr, type, s ) {
5347		var ct = xhr.getResponseHeader("content-type") || "",
5348			xml = type === "xml" || !type && ct.indexOf("xml") >= 0,
5349			data = xml ? xhr.responseXML : xhr.responseText;
5350
5351		if ( xml && data.documentElement.nodeName === "parsererror" ) {
5352			jQuery.error( "parsererror" );
5353		}
5354
5355		// Allow a pre-filtering function to sanitize the response
5356		// s is checked to keep backwards compatibility
5357		if ( s && s.dataFilter ) {
5358			data = s.dataFilter( data, type );
5359		}
5360
5361		// The filter can actually parse the response
5362		if ( typeof data === "string" ) {
5363			// Get the JavaScript object, if JSON is used.
5364			if ( type === "json" || !type && ct.indexOf("json") >= 0 ) {
5365				data = jQuery.parseJSON( data );
5366
5367			// If the type is "script", eval it in global context
5368			} else if ( type === "script" || !type && ct.indexOf("javascript") >= 0 ) {
5369				jQuery.globalEval( data );
5370			}
5371		}
5372
5373		return data;
5374	},
5375
5376	// Serialize an array of form elements or a set of
5377	// key/values into a query string
5378	param: function( a, traditional ) {
5379		var s = [];
5380
5381		// Set traditional to true for jQuery <= 1.3.2 behavior.
5382		if ( traditional === undefined ) {
5383			traditional = jQuery.ajaxSettings.traditional;
5384		}
5385
5386		// If an array was passed in, assume that it is an array of form elements.
5387		if ( jQuery.isArray(a) || a.jquery ) {
5388			// Serialize the form elements
5389			jQuery.each( a, function() {
5390				add( this.name, this.value );
5391			});
5392
5393		} else {
5394			// If traditional, encode the "old" way (the way 1.3.2 or older
5395			// did it), otherwise encode params recursively.
5396			for ( var prefix in a ) {
5397				buildParams( prefix, a[prefix] );
5398			}
5399		}
5400
5401		// Return the resulting serialization
5402		return s.join("&").replace(r20, "+");
5403
5404		function buildParams( prefix, obj ) {
5405			if ( jQuery.isArray(obj) ) {
5406				// Serialize array item.
5407				jQuery.each( obj, function( i, v ) {
5408					if ( traditional || /\[\]$/.test( prefix ) ) {
5409						// Treat each array item as a scalar.
5410						add( prefix, v );
5411					} else {
5412						// If array item is non-scalar (array or object), encode its
5413						// numeric index to resolve deserialization ambiguity issues.
5414						// Note that rack (as of 1.0.0) can't currently deserialize
5415						// nested arrays properly, and attempting to do so may cause
5416						// a server error. Possible fixes are to modify rack's
5417						// deserialization algorithm or to provide an option or flag
5418						// to force array serialization to be shallow.
5419						buildParams( prefix + "[" + ( typeof v === "object" || jQuery.isArray(v) ? i : "" ) + "]", v );
5420					}
5421				});
5422
5423			} else if ( !traditional && obj != null && typeof obj === "object" ) {
5424				// Serialize object item.
5425				jQuery.each( obj, function( k, v ) {
5426					buildParams( prefix + "[" + k + "]", v );
5427				});
5428
5429			} else {
5430				// Serialize scalar item.
5431				add( prefix, obj );
5432			}
5433		}
5434
5435		function add( key, value ) {
5436			// If value is a function, invoke it and return its value
5437			value = jQuery.isFunction(value) ? value() : value;
5438			s[ s.length ] = encodeURIComponent(key) + "=" + encodeURIComponent(value);
5439		}
5440	}
5441});
5442var elemdisplay = {},
5443	rfxtypes = /toggle|show|hide/,
5444	rfxnum = /^([+-]=)?([\d+-.]+)(.*)$/,
5445	timerId,
5446	fxAttrs = [
5447		// height animations
5448		[ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],
5449		// width animations
5450		[ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
5451		// opacity animations
5452		[ "opacity" ]
5453	];
5454
5455jQuery.fn.extend({
5456	show: function( speed, callback ) {
5457		if ( speed || speed === 0) {
5458			return this.animate( genFx("show", 3), speed, callback);
5459
5460		} else {
5461			for ( var i = 0, l = this.length; i < l; i++ ) {
5462				var old = jQuery.data(this[i], "olddisplay");
5463
5464				this[i].style.display = old || "";
5465
5466				if ( jQuery.css(this[i], "display") === "none" ) {
5467					var nodeName = this[i].nodeName, display;
5468
5469					if ( elemdisplay[ nodeName ] ) {
5470						display = elemdisplay[ nodeName ];
5471
5472					} else {
5473						var elem = jQuery("<" + nodeName + " />").appendTo("body");
5474
5475						display = elem.css("display");
5476
5477						if ( display === "none" ) {
5478							display = "block";
5479						}
5480
5481						elem.remove();
5482
5483						elemdisplay[ nodeName ] = display;
5484					}
5485
5486					jQuery.data(this[i], "olddisplay", display);
5487				}
5488			}
5489
5490			// Set the display of the elements in a second loop
5491			// to avoid the constant reflow
5492			for ( var j = 0, k = this.length; j < k; j++ ) {
5493				this[j].style.display = jQuery.data(this[j], "olddisplay") || "";
5494			}
5495
5496			return this;
5497		}
5498	},
5499
5500	hide: function( speed, callback ) {
5501		if ( speed || speed === 0 ) {
5502			return this.animate( genFx("hide", 3), speed, callback);
5503
5504		} else {
5505			for ( var i = 0, l = this.length; i < l; i++ ) {
5506				var old = jQuery.data(this[i], "olddisplay");
5507				if ( !old && old !== "none" ) {
5508					jQuery.data(this[i], "olddisplay", jQuery.css(this[i], "display"));
5509				}
5510			}
5511
5512			// Set the display of the elements in a second loop
5513			// to avoid the constant reflow
5514			for ( var j = 0, k = this.length; j < k; j++ ) {
5515				this[j].style.display = "none";
5516			}
5517
5518			return this;
5519		}
5520	},
5521
5522	// Save the old toggle function
5523	_toggle: jQuery.fn.toggle,
5524
5525	toggle: function( fn, fn2 ) {
5526		var bool = typeof fn === "boolean";
5527
5528		if ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {
5529			this._toggle.apply( this, arguments );
5530
5531		} else if ( fn == null || bool ) {
5532			this.each(function() {
5533				var state = bool ? fn : jQuery(this).is(":hidden");
5534				jQuery(this)[ state ? "show" : "hide" ]();
5535			});
5536
5537		} else {
5538			this.animate(genFx("toggle", 3), fn, fn2);
5539		}
5540
5541		return this;
5542	},
5543
5544	fadeTo: function( speed, to, callback ) {
5545		return this.filter(":hidden").css("opacity", 0).show().end()
5546					.animate({opacity: to}, speed, callback);
5547	},
5548
5549	animate: function( prop, speed, easing, callback ) {
5550		var optall = jQuery.speed(speed, easing, callback);
5551
5552		if ( jQuery.isEmptyObject( prop ) ) {
5553			return this.each( optall.complete );
5554		}
5555
5556		return this[ optall.queue === false ? "each" : "queue" ](function() {
5557			var opt = jQuery.extend({}, optall), p,
5558				hidden = this.nodeType === 1 && jQuery(this).is(":hidden"),
5559				self = this;
5560
5561			for ( p in prop ) {
5562				var name = p.replace(rdashAlpha, fcamelCase);
5563
5564				if ( p !== name ) {
5565					prop[ name ] = prop[ p ];
5566					delete prop[ p ];
5567					p = name;
5568				}
5569
5570				if ( prop[p] === "hide" && hidden || prop[p] === "show" && !hidden ) {
5571					return opt.complete.call(this);
5572				}
5573
5574				if ( ( p === "height" || p === "width" ) && this.style ) {
5575					// Store display property
5576					opt.display = jQuery.css(this, "display");
5577
5578					// Make sure that nothing sneaks out
5579					opt.overflow = this.style.overflow;
5580				}
5581
5582				if ( jQuery.isArray( prop[p] ) ) {
5583					// Create (if needed) and add to specialEasing
5584					(opt.specialEasing = opt.specialEasing || {})[p] = prop[p][1];
5585					prop[p] = prop[p][0];
5586				}
5587			}
5588
5589			if ( opt.overflow != null ) {
5590				this.style.overflow = "hidden";
5591			}
5592
5593			opt.curAnim = jQuery.extend({}, prop);
5594
5595			jQuery.each( prop, function( name, val ) {
5596				var e = new jQuery.fx( self, opt, name );
5597
5598				if ( rfxtypes.test(val) ) {
5599					e[ val === "toggle" ? hidden ? "show" : "hide" : val ]( prop );
5600
5601				} else {
5602					var parts = rfxnum.exec(val),
5603						start = e.cur(true) || 0;
5604
5605					if ( parts ) {
5606						var end = parseFloat( parts[2] ),
5607							unit = parts[3] || "px";
5608
5609						// We need to compute starting value
5610						if ( unit !== "px" ) {
5611							self.style[ name ] = (end || 1) + unit;
5612							start = ((end || 1) / e.cur(true)) * start;
5613							self.style[ name ] = start + unit;
5614						}
5615
5616						// If a +=/-= token was provided, we're doing a relative animation
5617						if ( parts[1] ) {
5618							end = ((parts[1] === "-=" ? -1 : 1) * end) + start;
5619						}
5620
5621						e.custom( start, end, unit );
5622
5623					} else {
5624						e.custom( start, val, "" );
5625					}
5626				}
5627			});
5628
5629			// For JS strict compliance
5630			return true;
5631		});
5632	},
5633
5634	stop: function( clearQueue, gotoEnd ) {
5635		var timers = jQuery.timers;
5636
5637		if ( clearQueue ) {
5638			this.queue([]);
5639		}
5640
5641		this.each(function() {
5642			// go in reverse order so anything added to the queue during the loop is ignored
5643			for ( var i = timers.length - 1; i >= 0; i-- ) {
5644				if ( timers[i].elem === this ) {
5645					if (gotoEnd) {
5646						// force the next step to be the last
5647						timers[i](true);
5648					}
5649
5650					timers.splice(i, 1);
5651				}
5652			}
5653		});
5654
5655		// start the next in the queue if the last step wasn't forced
5656		if ( !gotoEnd ) {
5657			this.dequeue();
5658		}
5659
5660		return this;
5661	}
5662
5663});
5664
5665// Generate shortcuts for custom animations
5666jQuery.each({
5667	slideDown: genFx("show", 1),
5668	slideUp: genFx("hide", 1),
5669	slideToggle: genFx("toggle", 1),
5670	fadeIn: { opacity: "show" },
5671	fadeOut: { opacity: "hide" }
5672}, function( name, props ) {
5673	jQuery.fn[ name ] = function( speed, callback ) {
5674		return this.animate( props, speed, callback );
5675	};
5676});
5677
5678jQuery.extend({
5679	speed: function( speed, easing, fn ) {
5680		var opt = speed && typeof speed === "object" ? speed : {
5681			complete: fn || !fn && easing ||
5682				jQuery.isFunction( speed ) && speed,
5683			duration: speed,
5684			easing: fn && easing || easing && !jQuery.isFunction(easing) && easing
5685		};
5686
5687		opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
5688			jQuery.fx.speeds[opt.duration] || jQuery.fx.speeds._default;
5689
5690		// Queueing
5691		opt.old = opt.complete;
5692		opt.complete = function() {
5693			if ( opt.queue !== false ) {
5694				jQuery(this).dequeue();
5695			}
5696			if ( jQuery.isFunction( opt.old ) ) {
5697				opt.old.call( this );
5698			}
5699		};
5700
5701		return opt;
5702	},
5703
5704	easing: {
5705		linear: function( p, n, firstNum, diff ) {
5706			return firstNum + diff * p;
5707		},
5708		swing: function( p, n, firstNum, diff ) {
5709			return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
5710		}
5711	},
5712
5713	timers: [],
5714
5715	fx: function( elem, options, prop ) {
5716		this.options = options;
5717		this.elem = elem;
5718		this.prop = prop;
5719
5720		if ( !options.orig ) {
5721			options.orig = {};
5722		}
5723	}
5724
5725});
5726
5727jQuery.fx.prototype = {
5728	// Simple function for setting a style value
5729	update: function() {
5730		if ( this.options.step ) {
5731			this.options.step.call( this.elem, this.now, this );
5732		}
5733
5734		(jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );
5735
5736		// Set display property to block for height/width animations
5737		if ( ( this.prop === "height" || this.prop === "width" ) && this.elem.style ) {
5738			this.elem.style.display = "block";
5739		}
5740	},
5741
5742	// Get the current size
5743	cur: function( force ) {
5744		if ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) ) {
5745			return this.elem[ this.prop ];
5746		}
5747
5748		var r = parseFloat(jQuery.css(this.elem, this.prop, force));
5749		return r && r > -10000 ? r : parseFloat(jQuery.curCSS(this.elem, this.prop)) || 0;
5750	},
5751
5752	// Start an animation from one number to another
5753	custom: function( from, to, unit ) {
5754		this.startTime = now();
5755		this.start = from;
5756		this.end = to;
5757		this.unit = unit || this.unit || "px";
5758		this.now = this.start;
5759		this.pos = this.state = 0;
5760
5761		var self = this;
5762		function t( gotoEnd ) {
5763			return self.step(gotoEnd);
5764		}
5765
5766		t.elem = this.elem;
5767
5768		if ( t() && jQuery.timers.push(t) && !timerId ) {
5769			timerId = setInterval(jQuery.fx.tick, 13);
5770		}
5771	},
5772
5773	// Simple 'show' function
5774	show: function() {
5775		// Remember where we started, so that we can go back to it later
5776		this.options.orig[this.prop] = jQuery.style( this.elem, this.prop );
5777		this.options.show = true;
5778
5779		// Begin the animation
5780		// Make sure that we start at a small width/height to avoid any
5781		// flash of content
5782		this.custom(this.prop === "width" || this.prop === "height" ? 1 : 0, this.cur());
5783
5784		// Start by showing the element
5785		jQuery( this.elem ).show();
5786	},
5787
5788	// Simple 'hide' function
5789	hide: function() {
5790		// Remember where we started, so that we can go back to it later
5791		this.options.orig[this.prop] = jQuery.style( this.elem, this.prop );
5792		this.options.hide = true;
5793
5794		// Begin the animation
5795		this.custom(this.cur(), 0);
5796	},
5797
5798	// Each step of an animation
5799	step: function( gotoEnd ) {
5800		var t = now(), done = true;
5801
5802		if ( gotoEnd || t >= this.options.duration + this.startTime ) {
5803			this.now = this.end;
5804			this.pos = this.state = 1;
5805			this.update();
5806
5807			this.options.curAnim[ this.prop ] = true;
5808
5809			for ( var i in this.options.curAnim ) {
5810				if ( this.options.curAnim[i] !== true ) {
5811					done = false;
5812				}
5813			}
5814
5815			if ( done ) {
5816				if ( this.options.display != null ) {
5817					// Reset the overflow
5818					this.elem.style.overflow = this.options.overflow;
5819
5820					// Reset the display
5821					var old = jQuery.data(this.elem, "olddisplay");
5822					this.elem.style.display = old ? old : this.options.display;
5823
5824					if ( jQuery.css(this.elem, "display") === "none" ) {
5825						this.elem.style.display = "block";
5826					}
5827				}
5828
5829				// Hide the element if the "hide" operation was done
5830				if ( this.options.hide ) {
5831					jQuery(this.elem).hide();
5832				}
5833
5834				// Reset the properties, if the item has been hidden or shown
5835				if ( this.options.hide || this.options.show ) {
5836					for ( var p in this.options.curAnim ) {
5837						jQuery.style(this.elem, p, this.options.orig[p]);
5838					}
5839				}
5840
5841				// Execute the complete function
5842				this.options.complete.call( this.elem );
5843			}
5844
5845			return false;
5846
5847		} else {
5848			var n = t - this.startTime;
5849			this.state = n / this.options.duration;
5850
5851			// Perform the easing function, defaults to swing
5852			var specialEasing = this.options.specialEasing && this.options.specialEasing[this.prop];
5853			var defaultEasing = this.options.easing || (jQuery.easing.swing ? "swing" : "linear");
5854			this.pos = jQuery.easing[specialEasing || defaultEasing](this.state, n, 0, 1, this.options.duration);
5855			this.now = this.start + ((this.end - this.start) * this.pos);
5856
5857			// Perform the next step of the animation
5858			this.update();
5859		}
5860
5861		return true;
5862	}
5863};
5864
5865jQuery.extend( jQuery.fx, {
5866	tick: function() {
5867		var timers = jQuery.timers;
5868
5869		for ( var i = 0; i < timers.length; i++ ) {
5870			if ( !timers[i]() ) {
5871				timers.splice(i--, 1);
5872			}
5873		}
5874
5875		if ( !timers.length ) {
5876			jQuery.fx.stop();
5877		}
5878	},
5879
5880	stop: function() {
5881		clearInterval( timerId );
5882		timerId = null;
5883	},
5884
5885	speeds: {
5886		slow: 600,
5887 		fast: 200,
5888 		// Default speed
5889 		_default: 400
5890	},
5891
5892	step: {
5893		opacity: function( fx ) {
5894			jQuery.style(fx.elem, "opacity", fx.now);
5895		},
5896
5897		_default: function( fx ) {
5898			if ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) {
5899				fx.elem.style[ fx.prop ] = (fx.prop === "width" || fx.prop === "height" ? Math.max(0, fx.now) : fx.now) + fx.unit;
5900			} else {
5901				fx.elem[ fx.prop ] = fx.now;
5902			}
5903		}
5904	}
5905});
5906
5907if ( jQuery.expr && jQuery.expr.filters ) {
5908	jQuery.expr.filters.animated = function( elem ) {
5909		return jQuery.grep(jQuery.timers, function( fn ) {
5910			return elem === fn.elem;
5911		}).length;
5912	};
5913}
5914
5915function genFx( type, num ) {
5916	var obj = {};
5917
5918	jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function() {
5919		obj[ this ] = type;
5920	});
5921
5922	return obj;
5923}
5924if ( "getBoundingClientRect" in document.documentElement ) {
5925	jQuery.fn.offset = function( options ) {
5926		var elem = this[0];
5927
5928		if ( options ) {
5929			return this.each(function( i ) {
5930				jQuery.offset.setOffset( this, options, i );
5931			});
5932		}
5933
5934		if ( !elem || !elem.ownerDocument ) {
5935			return null;
5936		}
5937
5938		if ( elem === elem.ownerDocument.body ) {
5939			return jQuery.offset.bodyOffset( elem );
5940		}
5941
5942		var box = elem.getBoundingClientRect(), doc = elem.ownerDocument, body = doc.body, docElem = doc.documentElement,
5943			clientTop = docElem.clientTop || body.clientTop || 0, clientLeft = docElem.clientLeft || body.clientLeft || 0,
5944			top  = box.top  + (self.pageYOffset || jQuery.support.boxModel && docElem.scrollTop  || body.scrollTop ) - clientTop,
5945			left = box.left + (self.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft) - clientLeft;
5946
5947		return { top: top, left: left };
5948	};
5949
5950} else {
5951	jQuery.fn.offset = function( options ) {
5952		var elem = this[0];
5953
5954		if ( options ) {
5955			return this.each(function( i ) {
5956				jQuery.offset.setOffset( this, options, i );
5957			});
5958		}
5959
5960		if ( !elem || !elem.ownerDocument ) {
5961			return null;
5962		}
5963
5964		if ( elem === elem.ownerDocument.body ) {
5965			return jQuery.offset.bodyOffset( elem );
5966		}
5967
5968		jQuery.offset.initialize();
5969
5970		var offsetParent = elem.offsetParent, prevOffsetParent = elem,
5971			doc = elem.ownerDocument, computedStyle, docElem = doc.documentElement,
5972			body = doc.body, defaultView = doc.defaultView,
5973			prevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,
5974			top = elem.offsetTop, left = elem.offsetLeft;
5975
5976		while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {
5977			if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed" ) {
5978				break;
5979			}
5980
5981			computedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;
5982			top  -= elem.scrollTop;
5983			left -= elem.scrollLeft;
5984
5985			if ( elem === offsetParent ) {
5986				top  += elem.offsetTop;
5987				left += elem.offsetLeft;
5988
5989				if ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && /^t(able|d|h)$/i.test(elem.nodeName)) ) {
5990					top  += parseFloat( computedStyle.borderTopWidth  ) || 0;
5991					left += parseFloat( computedStyle.borderLeftWidth ) || 0;
5992				}
5993
5994				prevOffsetParent = offsetParent, offsetParent = elem.offsetParent;
5995			}
5996
5997			if ( jQuery.offset.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" ) {
5998				top  += parseFloat( computedStyle.borderTopWidth  ) || 0;
5999				left += parseFloat( computedStyle.borderLeftWidth ) || 0;
6000			}
6001
6002			prevComputedStyle = computedStyle;
6003		}
6004
6005		if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" ) {
6006			top  += body.offsetTop;
6007			left += body.offsetLeft;
6008		}
6009
6010		if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed" ) {
6011			top  += Math.max( docElem.scrollTop, body.scrollTop );
6012			left += Math.max( docElem.scrollLeft, body.scrollLeft );
6013		}
6014
6015		return { top: top, left: left };
6016	};
6017}
6018
6019jQuery.offset = {
6020	initialize: function() {
6021		var body = document.body, container = document.createElement("div"), innerDiv, checkDiv, table, td, bodyMarginTop = parseFloat( jQuery.curCSS(body, "marginTop", true) ) || 0,
6022			html = "<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";
6023
6024		jQuery.extend( container.style, { position: "absolute", top: 0, left: 0, margin: 0, border: 0, width: "1px", height: "1px", visibility: "hidden" } );
6025
6026		container.innerHTML = html;
6027		body.insertBefore( container, body.firstChild );
6028		innerDiv = container.firstChild;
6029		checkDiv = innerDiv.firstChild;
6030		td = innerDiv.nextSibling.firstChild.firstChild;
6031
6032		this.doesNotAddBorder = (checkDiv.offsetTop !== 5);
6033		this.doesAddBorderForTableAndCells = (td.offsetTop === 5);
6034
6035		checkDiv.style.position = "fixed", checkDiv.style.top = "20px";
6036		// safari subtracts parent border width here which is 5px
6037		this.supportsFixedPosition = (checkDiv.offsetTop === 20 || checkDiv.offsetTop === 15);
6038		checkDiv.style.position = checkDiv.style.top = "";
6039
6040		innerDiv.style.overflow = "hidden", innerDiv.style.position = "relative";
6041		this.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5);
6042
6043		this.doesNotIncludeMarginInBodyOffset = (body.offsetTop !== bodyMarginTop);
6044
6045		body.removeChild( container );
6046		body = container = innerDiv = checkDiv = table = td = null;
6047		jQuery.offset.initialize = jQuery.noop;
6048	},
6049
6050	bodyOffset: function( body ) {
6051		var top = body.offsetTop, left = body.offsetLeft;
6052
6053		jQuery.offset.initialize();
6054
6055		if ( jQuery.offset.doesNotIncludeMarginInBodyOffset ) {
6056			top  += parseFloat( jQuery.curCSS(body, "marginTop",  true) ) || 0;
6057			left += parseFloat( jQuery.curCSS(body, "marginLeft", true) ) || 0;
6058		}
6059
6060		return { top: top, left: left };
6061	},
6062
6063	setOffset: function( elem, options, i ) {
6064		// set position first, in-case top/left are set even on static elem
6065		if ( /static/.test( jQuery.curCSS( elem, "position" ) ) ) {
6066			elem.style.position = "relative";
6067		}
6068		var curElem   = jQuery( elem ),
6069			curOffset = curElem.offset(),
6070			curTop    = parseInt( jQuery.curCSS( elem, "top",  true ), 10 ) || 0,
6071			curLeft   = parseInt( jQuery.curCSS( elem, "left", true ), 10 ) || 0;
6072
6073		if ( jQuery.isFunction( options ) ) {
6074			options = options.call( elem, i, curOffset );
6075		}
6076
6077		var props = {
6078			top:  (options.top  - curOffset.top)  + curTop,
6079			left: (options.left - curOffset.left) + curLeft
6080		};
6081
6082		if ( "using" in options ) {
6083			options.using.call( elem, props );
6084		} else {
6085			curElem.css( props );
6086		}
6087	}
6088};
6089
6090
6091jQuery.fn.extend({
6092	position: function() {
6093		if ( !this[0] ) {
6094			return null;
6095		}
6096
6097		var elem = this[0],
6098
6099		// Get *real* offsetParent
6100		offsetParent = this.offsetParent(),
6101
6102		// Get correct offsets
6103		offset       = this.offset(),
6104		parentOffset = /^body|html$/i.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();
6105
6106		// Subtract element margins
6107		// note: when an element has margin: auto the offsetLeft and marginLeft
6108		// are the same in Safari causing offset.left to incorrectly be 0
6109		offset.top  -= parseFloat( jQuery.curCSS(elem, "marginTop",  true) ) || 0;
6110		offset.left -= parseFloat( jQuery.curCSS(elem, "marginLeft", true) ) || 0;
6111
6112		// Add offsetParent borders
6113		parentOffset.top  += parseFloat( jQuery.curCSS(offsetParent[0], "borderTopWidth",  true) ) || 0;
6114		parentOffset.left += parseFloat( jQuery.curCSS(offsetParent[0], "borderLeftWidth", true) ) || 0;
6115
6116		// Subtract the two offsets
6117		return {
6118			top:  offset.top  - parentOffset.top,
6119			left: offset.left - parentOffset.left
6120		};
6121	},
6122
6123	offsetParent: function() {
6124		return this.map(function() {
6125			var offsetParent = this.offsetParent || document.body;
6126			while ( offsetParent && (!/^body|html$/i.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static") ) {
6127				offsetParent = offsetParent.offsetParent;
6128			}
6129			return offsetParent;
6130		});
6131	}
6132});
6133
6134
6135// Create scrollLeft and scrollTop methods
6136jQuery.each( ["Left", "Top"], function( i, name ) {
6137	var method = "scroll" + name;
6138
6139	jQuery.fn[ method ] = function(val) {
6140		var elem = this[0], win;
6141
6142		if ( !elem ) {
6143			return null;
6144		}
6145
6146		if ( val !== undefined ) {
6147			// Set the scroll offset
6148			return this.each(function() {
6149				win = getWindow( this );
6150
6151				if ( win ) {
6152					win.scrollTo(
6153						!i ? val : jQuery(win).scrollLeft(),
6154						 i ? val : jQuery(win).scrollTop()
6155					);
6156
6157				} else {
6158					this[ method ] = val;
6159				}
6160			});
6161		} else {
6162			win = getWindow( elem );
6163
6164			// Return the scroll offset
6165			return win ? ("pageXOffset" in win) ? win[ i ? "pageYOffset" : "pageXOffset" ] :
6166				jQuery.support.boxModel && win.document.documentElement[ method ] ||
6167					win.document.body[ method ] :
6168				elem[ method ];
6169		}
6170	};
6171});
6172
6173function getWindow( elem ) {
6174	return ("scrollTo" in elem && elem.document) ?
6175		elem :
6176		elem.nodeType === 9 ?
6177			elem.defaultView || elem.parentWindow :
6178			false;
6179}
6180// Create innerHeight, innerWidth, outerHeight and outerWidth methods
6181jQuery.each([ "Height", "Width" ], function( i, name ) {
6182
6183	var type = name.toLowerCase();
6184
6185	// innerHeight and innerWidth
6186	jQuery.fn["inner" + name] = function() {
6187		return this[0] ?
6188			jQuery.css( this[0], type, false, "padding" ) :
6189			null;
6190	};
6191
6192	// outerHeight and outerWidth
6193	jQuery.fn["outer" + name] = function( margin ) {
6194		return this[0] ?
6195			jQuery.css( this[0], type, false, margin ? "margin" : "border" ) :
6196			null;
6197	};
6198
6199	jQuery.fn[ type ] = function( size ) {
6200		// Get window width or height
6201		var elem = this[0];
6202		if ( !elem ) {
6203			return size == null ? null : this;
6204		}
6205
6206		if ( jQuery.isFunction( size ) ) {
6207			return this.each(function( i ) {
6208				var self = jQuery( this );
6209				self[ type ]( size.call( this, i, self[ type ]() ) );
6210			});
6211		}
6212
6213		return ("scrollTo" in elem && elem.document) ? // does it walk and quack like a window?
6214			// Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
6215			elem.document.compatMode === "CSS1Compat" && elem.document.documentElement[ "client" + name ] ||
6216			elem.document.body[ "client" + name ] :
6217
6218			// Get document width or height
6219			(elem.nodeType === 9) ? // is it a document
6220				// Either scroll[Width/Height] or offset[Width/Height], whichever is greater
6221				Math.max(
6222					elem.documentElement["client" + name],
6223					elem.body["scroll" + name], elem.documentElement["scroll" + name],
6224					elem.body["offset" + name], elem.documentElement["offset" + name]
6225				) :
6226
6227				// Get or set width or height on the element
6228				size === undefined ?
6229					// Get width or height on the element
6230					jQuery.css( elem, type ) :
6231
6232					// Set the width or height on the element (default to pixels if value is unitless)
6233					this.css( type, typeof size === "string" ? size : size + "px" );
6234	};
6235
6236});
6237// Expose jQuery to the global object
6238window.jQuery = window.$ = jQuery;
6239
6240})(window);
6241