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