Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 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: 2009-03-17 18:35:18 $
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
});})();