PageSourceSearch

https://www.kla.tv/js/ui/jquery-ui.js?v=20180919b

js kla.tv collected 2026-09-24 09:00:00 UTC 365,673 bytes, 11,377 lines download raw bytes

1/*! jQuery UI - v1.8.24 - 2012-09-28
2* https://github.com/jquery/jquery-ui
3* Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.draggable.js, jquery.ui.droppable.js, jquery.ui.resizable.js, jquery.ui.selectable.js, jquery.ui.sortable.js, jquery.effects.core.js, jquery.effects.blind.js, jquery.effects.bounce.js, jquery.effects.clip.js, jquery.effects.drop.js, jquery.effects.explode.js, jquery.effects.fade.js, jquery.effects.fold.js, jquery.effects.highlight.js, jquery.effects.pulsate.js, jquery.effects.scale.js, jquery.effects.shake.js, jquery.effects.slide.js, jquery.effects.transfer.js, jquery.ui.accordion.js, jquery.ui.autocomplete.js, jquery.ui.button.js, jquery.ui.datepicker.js, jquery.ui.dialog.js, jquery.ui.position.js, jquery.ui.progressbar.js, jquery.ui.slider.js, jquery.ui.tabs.js
4* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */
5
6(function( $, undefined ) {
7
8// prevent duplicate loading
9// this is only a problem because we proxy existing functions
10// and we don't want to double proxy them
11$.ui = $.ui || {};
12if ( $.ui.version ) {
13	return;
14}
15
16$.extend( $.ui, {
17	version: "1.8.24",
18
19	keyCode: {
20		ALT: 18,
21		BACKSPACE: 8,
22		CAPS_LOCK: 20,
23		COMMA: 188,
24		COMMAND: 91,
25		COMMAND_LEFT: 91, // COMMAND
26		COMMAND_RIGHT: 93,
27		CONTROL: 17,
28		DELETE: 46,
29		DOWN: 40,
30		END: 35,
31		ENTER: 13,
32		ESCAPE: 27,
33		HOME: 36,
34		INSERT: 45,
35		LEFT: 37,
36		MENU: 93, // COMMAND_RIGHT
37		NUMPAD_ADD: 107,
38		NUMPAD_DECIMAL: 110,
39		NUMPAD_DIVIDE: 111,
40		NUMPAD_ENTER: 108,
41		NUMPAD_MULTIPLY: 106,
42		NUMPAD_SUBTRACT: 109,
43		PAGE_DOWN: 34,
44		PAGE_UP: 33,
45		PERIOD: 190,
46		RIGHT: 39,
47		SHIFT: 16,
48		SPACE: 32,
49		TAB: 9,
50		UP: 38,
51		WINDOWS: 91 // COMMAND
52	}
53});
54
55// plugins
56$.fn.extend({
57	propAttr: $.fn.prop || $.fn.attr,
58
59	_focus: $.fn.focus,
60	focus: function( delay, fn ) {
61		return typeof delay === "number" ?
62			this.each(function() {
63				var elem = this;
64				setTimeout(function() {
65					$( elem ).focus();
66					if ( fn ) {
67						fn.call( elem );
68					}
69				}, delay );
70			}) :
71			this._focus.apply( this, arguments );
72	},
73
74	scrollParent: function() {
75		var scrollParent;
76		if (($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
77			scrollParent = this.parents().filter(function() {
78				return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
79			}).eq(0);
80		} else {
81			scrollParent = this.parents().filter(function() {
82				return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
83			}).eq(0);
84		}
85
86		return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
87	},
88
89	zIndex: function( zIndex ) {
90		if ( zIndex !== undefined ) {
91			return this.css( "zIndex", zIndex );
92		}
93
94		if ( this.length ) {
95			var elem = $( this[ 0 ] ), position, value;
96			while ( elem.length && elem[ 0 ] !== document ) {
97				// Ignore z-index if position is set to a value where z-index is ignored by the browser
98				// This makes behavior of this function consistent across browsers
99				// WebKit always returns auto if the element is positioned
100				position = elem.css( "position" );
101				if ( position === "absolute" || position === "relative" || position === "fixed" ) {
102					// IE returns 0 when zIndex is not specified
103					// other browsers return a string
104					// we ignore the case of nested elements with an explicit value of 0
105					// <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
106					value = parseInt( elem.css( "zIndex" ), 10 );
107					if ( !isNaN( value ) && value !== 0 ) {
108						return value;
109					}
110				}
111				elem = elem.parent();
112			}
113		}
114
115		return 0;
116	},
117
118	disableSelection: function() {
119		return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
120			".ui-disableSelection", function( event ) {
121				event.preventDefault();
122			});
123	},
124
125	enableSelection: function() {
126		return this.unbind( ".ui-disableSelection" );
127	}
128});
129
130// support: jQuery <1.8
131if ( !$( "<a>" ).outerWidth( 1 ).jquery ) {
132	$.each( [ "Width", "Height" ], function( i, name ) {
133		var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
134			type = name.toLowerCase(),
135			orig = {
136				innerWidth: $.fn.innerWidth,
137				innerHeight: $.fn.innerHeight,
138				outerWidth: $.fn.outerWidth,
139				outerHeight: $.fn.outerHeight
140			};
141
142		function reduce( elem, size, border, margin ) {
143			$.each( side, function() {
144				size -= parseFloat( $.curCSS( elem, "padding" + this, true) ) || 0;
145				if ( border ) {
146					size -= parseFloat( $.curCSS( elem, "border" + this + "Width", true) ) || 0;
147				}
148				if ( margin ) {
149					size -= parseFloat( $.curCSS( elem, "margin" + this, true) ) || 0;
150				}
151			});
152			return size;
153		}
154
155		$.fn[ "inner" + name ] = function( size ) {
156			if ( size === undefined ) {
157				return orig[ "inner" + name ].call( this );
158			}
159
160			return this.each(function() {
161				$( this ).css( type, reduce( this, size ) + "px" );
162			});
163		};
164
165		$.fn[ "outer" + name] = function( size, margin ) {
166			if ( typeof size !== "number" ) {
167				return orig[ "outer" + name ].call( this, size );
168			}
169
170			return this.each(function() {
171				$( this).css( type, reduce( this, size, true, margin ) + "px" );
172			});
173		};
174	});
175}
176
177// selectors
178function focusable( element, isTabIndexNotNaN ) {
179	var nodeName = element.nodeName.toLowerCase();
180	if ( "area" === nodeName ) {
181		var map = element.parentNode,
182			mapName = map.name,
183			img;
184		if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
185			return false;
186		}
187		img = $( "img[usemap=#" + mapName + "]" )[0];
188		return !!img && visible( img );
189	}
190	return ( /input|select|textarea|button|object/.test( nodeName )
191		? !element.disabled
192		: "a" == nodeName
193			? element.href || isTabIndexNotNaN
194			: isTabIndexNotNaN)
195		// the element and all of its ancestors must be visible
196		&& visible( element );
197}
198
199function visible( element ) {
200	return !$( element ).parents().andSelf().filter(function() {
201		return $.curCSS( this, "visibility" ) === "hidden" ||
202			$.expr.filters.hidden( this );
203	}).length;
204}
205
206$.extend( $.expr[ ":" ], {
207	data: $.expr.createPseudo ?
208		$.expr.createPseudo(function( dataName ) {
209			return function( elem ) {
210				return !!$.data( elem, dataName );
211			};
212		}) :
213		// support: jQuery <1.8
214		function( elem, i, match ) {
215			return !!$.data( elem, match[ 3 ] );
216		},
217
218	focusable: function( element ) {
219		return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );
220	},
221
222	tabbable: function( element ) {
223		var tabIndex = $.attr( element, "tabindex" ),
224			isTabIndexNaN = isNaN( tabIndex );
225		return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );
226	}
227});
228
229// support
230$(function() {
231	var body = document.body,
232		div = body.appendChild( div = document.createElement( "div" ) );
233
234	// access offsetHeight before setting the style to prevent a layout bug
235	// in IE 9 which causes the elemnt to continue to take up space even
236	// after it is removed from the DOM (#8026)
237	div.offsetHeight;
238
239	$.extend( div.style, {
240		minHeight: "100px",
241		height: "auto",
242		padding: 0,
243		borderWidth: 0
244	});
245
246	$.support.minHeight = div.offsetHeight === 100;
247	$.support.selectstart = "onselectstart" in div;
248
249	// set display to none to avoid a layout bug in IE
250	// http://dev.jquery.com/ticket/4014
251	body.removeChild( div ).style.display = "none";
252});
253
254// jQuery <1.4.3 uses curCSS, in 1.4.3 - 1.7.2 curCSS = css, 1.8+ only has css
255if ( !$.curCSS ) {
256	$.curCSS = $.css;
257}
258
259
260
261
262
263// deprecated
264$.extend( $.ui, {
265	// $.ui.plugin is deprecated.  Use the proxy pattern instead.
266	plugin: {
267		add: function( module, option, set ) {
268			var proto = $.ui[ module ].prototype;
269			for ( var i in set ) {
270				proto.plugins[ i ] = proto.plugins[ i ] || [];
271				proto.plugins[ i ].push( [ option, set[ i ] ] );
272			}
273		},
274		call: function( instance, name, args ) {
275			var set = instance.plugins[ name ];
276			if ( !set || !instance.element[ 0 ].parentNode ) {
277				return;
278			}
279	
280			for ( var i = 0; i < set.length; i++ ) {
281				if ( instance.options[ set[ i ][ 0 ] ] ) {
282					set[ i ][ 1 ].apply( instance.element, args );
283				}
284			}
285		}
286	},
287	
288	// will be deprecated when we switch to jQuery 1.4 - use jQuery.contains()
289	contains: function( a, b ) {
290		return document.compareDocumentPosition ?
291			a.compareDocumentPosition( b ) & 16 :
292			a !== b && a.contains( b );
293	},
294	
295	// only used by resizable
296	hasScroll: function( el, a ) {
297	
298		//If overflow is hidden, the element might have extra content, but the user wants to hide it
299		if ( $( el ).css( "overflow" ) === "hidden") {
300			return false;
301		}
302	
303		var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
304			has = false;
305	
306		if ( el[ scroll ] > 0 ) {
307			return true;
308		}
309	
310		// TODO: determine which cases actually cause this to happen
311		// if the element doesn't have the scroll set, see if it's possible to
312		// set the scroll
313		el[ scroll ] = 1;
314		has = ( el[ scroll ] > 0 );
315		el[ scroll ] = 0;
316		return has;
317	},
318	
319	// these are odd functions, fix the API or move into individual plugins
320	isOverAxis: function( x, reference, size ) {
321		//Determines when x coordinate is over "b" element axis
322		return ( x > reference ) && ( x < ( reference + size ) );
323	},
324	isOver: function( y, x, top, left, height, width ) {
325		//Determines when x, y coordinates is over "b" element
326		return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width );
327	}
328});
329
330})( jQuery );
331
332(function( $, undefined ) {
333
334// jQuery 1.4+
335if ( $.cleanData ) {
336	var _cleanData = $.cleanData;
337	$.cleanData = function( elems ) {
338		for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
339			try {
340				$( elem ).triggerHandler( "remove" );
341			// http://bugs.jquery.com/ticket/8235
342			} catch( e ) {}
343		}
344		_cleanData( elems );
345	};
346} else {
347	var _remove = $.fn.remove;
348	$.fn.remove = function( selector, keepData ) {
349		return this.each(function() {
350			if ( !keepData ) {
351				if ( !selector || $.filter( selector, [ this ] ).length ) {
352					$( "*", this ).add( [ this ] ).each(function() {
353						try {
354							$( this ).triggerHandler( "remove" );
355						// http://bugs.jquery.com/ticket/8235
356						} catch( e ) {}
357					});
358				}
359			}
360			return _remove.call( $(this), selector, keepData );
361		});
362	};
363}
364
365$.widget = function( name, base, prototype ) {
366	var namespace = name.split( "." )[ 0 ],
367		fullName;
368	name = name.split( "." )[ 1 ];
369	fullName = namespace + "-" + name;
370
371	if ( !prototype ) {
372		prototype = base;
373		base = $.Widget;
374	}
375
376	// create selector for plugin
377	$.expr[ ":" ][ fullName ] = function( elem ) {
378		return !!$.data( elem, name );
379	};
380
381	$[ namespace ] = $[ namespace ] || {};
382	$[ namespace ][ name ] = function( options, element ) {
383		// allow instantiation without initializing for simple inheritance
384		if ( arguments.length ) {
385			this._createWidget( options, element );
386		}
387	};
388
389	var basePrototype = new base();
390	// we need to make the options hash a property directly on the new instance
391	// otherwise we'll modify the options hash on the prototype that we're
392	// inheriting from
393//	$.each( basePrototype, function( key, val ) {
394//		if ( $.isPlainObject(val) ) {
395//			basePrototype[ key ] = $.extend( {}, val );
396//		}
397//	});
398	basePrototype.options = $.extend( true, {}, basePrototype.options );
399	$[ namespace ][ name ].prototype = $.extend( true, basePrototype, {
400		namespace: namespace,
401		widgetName: name,
402		widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name,
403		widgetBaseClass: fullName
404	}, prototype );
405
406	$.widget.bridge( name, $[ namespace ][ name ] );
407};
408
409$.widget.bridge = function( name, object ) {
410	$.fn[ name ] = function( options ) {
411		var isMethodCall = typeof options === "string",
412			args = Array.prototype.slice.call( arguments, 1 ),
413			returnValue = this;
414
415		// allow multiple hashes to be passed on init
416		options = !isMethodCall && args.length ?
417			$.extend.apply( null, [ true, options ].concat(args) ) :
418			options;
419
420		// prevent calls to internal methods
421		if ( isMethodCall && options.charAt( 0 ) === "_" ) {
422			return returnValue;
423		}
424
425		if ( isMethodCall ) {
426			this.each(function() {
427				var instance = $.data( this, name ),
428					methodValue = instance && $.isFunction( instance[options] ) ?
429						instance[ options ].apply( instance, args ) :
430						instance;
431				// TODO: add this back in 1.9 and use $.error() (see #5972)
432//				if ( !instance ) {
433//					throw "cannot call methods on " + name + " prior to initialization; " +
434//						"attempted to call method '" + options + "'";
435//				}
436//				if ( !$.isFunction( instance[options] ) ) {
437//					throw "no such method '" + options + "' for " + name + " widget instance";
438//				}
439//				var methodValue = instance[ options ].apply( instance, args );
440				if ( methodValue !== instance && methodValue !== undefined ) {
441					returnValue = methodValue;
442					return false;
443				}
444			});
445		} else {
446			this.each(function() {
447				var instance = $.data( this, name );
448				if ( instance ) {
449					instance.option( options || {} )._init();
450				} else {
451					$.data( this, name, new object( options, this ) );
452				}
453			});
454		}
455
456		return returnValue;
457	};
458};
459
460$.Widget = function( options, element ) {
461	// allow instantiation without initializing for simple inheritance
462	if ( arguments.length ) {
463		this._createWidget( options, element );
464	}
465};
466
467$.Widget.prototype = {
468	widgetName: "widget",
469	widgetEventPrefix: "",
470	options: {
471		disabled: false
472	},
473	_createWidget: function( options, element ) {
474		// $.widget.bridge stores the plugin instance, but we do it anyway
475		// so that it's stored even before the _create function runs
476		$.data( element, this.widgetName, this );
477		this.element = $( element );
478		this.options = $.extend( true, {},
479			this.options,
480			this._getCreateOptions(),
481			options );
482
483		var self = this;
484		this.element.bind( "remove." + this.widgetName, function() {
485			self.destroy();
486		});
487
488		this._create();
489		this._trigger( "create" );
490		this._init();
491	},
492	_getCreateOptions: function() {
493		return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ];
494	},
495	_create: function() {},
496	_init: function() {},
497
498	destroy: function() {
499		this.element
500			.unbind( "." + this.widgetName )
501			.removeData( this.widgetName );
502		this.widget()
503			.unbind( "." + this.widgetName )
504			.removeAttr( "aria-disabled" )
505			.removeClass(
506				this.widgetBaseClass + "-disabled " +
507				"ui-state-disabled" );
508	},
509
510	widget: function() {
511		return this.element;
512	},
513
514	option: function( key, value ) {
515		var options = key;
516
517		if ( arguments.length === 0 ) {
518			// don't return a reference to the internal hash
519			return $.extend( {}, this.options );
520		}
521
522		if  (typeof key === "string" ) {
523			if ( value === undefined ) {
524				return this.options[ key ];
525			}
526			options = {};
527			options[ key ] = value;
528		}
529
530		this._setOptions( options );
531
532		return this;
533	},
534	_setOptions: function( options ) {
535		var self = this;
536		$.each( options, function( key, value ) {
537			self._setOption( key, value );
538		});
539
540		return this;
541	},
542	_setOption: function( key, value ) {
543		this.options[ key ] = value;
544
545		if ( key === "disabled" ) {
546			this.widget()
547				[ value ? "addClass" : "removeClass"](
548					this.widgetBaseClass + "-disabled" + " " +
549					"ui-state-disabled" )
550				.attr( "aria-disabled", value );
551		}
552
553		return this;
554	},
555
556	enable: function() {
557		return this._setOption( "disabled", false );
558	},
559	disable: function() {
560		return this._setOption( "disabled", true );
561	},
562
563	_trigger: function( type, event, data ) {
564		var prop, orig,
565			callback = this.options[ type ];
566
567		data = data || {};
568		event = $.Event( event );
569		event.type = ( type === this.widgetEventPrefix ?
570			type :
571			this.widgetEventPrefix + type ).toLowerCase();
572		// the original event may come from any element
573		// so we need to reset the target on the new event
574		event.target = this.element[ 0 ];
575
576		// copy original event properties over to the new event
577		orig = event.originalEvent;
578		if ( orig ) {
579			for ( prop in orig ) {
580				if ( !( prop in event ) ) {
581					event[ prop ] = orig[ prop ];
582				}
583			}
584		}
585
586		this.element.trigger( event, data );
587
588		return !( $.isFunction(callback) &&
589			callback.call( this.element[0], event, data ) === false ||
590			event.isDefaultPrevented() );
591	}
592};
593
594}
vendor: 2,391 bytes, lines 594-677
594)( jQuery );
595
596(function( $, undefined ) {
597
598var mouseHandled = false;
599$( document ).mouseup( function( e ) {
600	mouseHandled = false;
601});
602
603$.widget("ui.mouse", {
604	options: {
605		cancel: ':input,option',
606		distance: 1,
607		delay: 0
608	},
609	_mouseInit: function() {
610		var self = this;
611
612		this.element
613			.bind('mousedown.'+this.widgetName, function(event) {
614				return self._mouseDown(event);
615			})
616			.bind('click.'+this.widgetName, function(event) {
617				if (true === $.data(event.target, self.widgetName + '.preventClickEvent')) {
618				    $.removeData(event.target, self.widgetName + '.preventClickEvent');
619					event.stopImmediatePropagation();
620					return false;
621				}
622			});
623
624		this.started = false;
625	},
626
627	// TODO: make sure destroying one instance of mouse doesn't mess with
628	// other instances of mouse
629	_mouseDestroy: function() {
630		this.element.unbind('.'+this.widgetName);
631		if ( this._mouseMoveDelegate ) {
632			$(document)
633				.unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
634				.unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
635		}
636	},
637
638	_mouseDown: function(event) {
639		// don't let more than one widget handle mouseStart
640		if( mouseHandled ) { return };
641
642		// we may have missed mouseup (out of window)
643		(this._mouseStarted && this._mouseUp(event));
644
645		this._mouseDownEvent = event;
646
647		var self = this,
648			btnIsLeft = (event.which == 1),
649			// event.target.nodeName works around a bug in IE 8 with
650			// disabled inputs (#7620)
651			elIsCancel = (typeof this.options.cancel == "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false);
652		if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
653			return true;
654		}
655
656		this.mouseDelayMet = !this.options.delay;
657		if (!this.mouseDelayMet) {
658			this._mouseDelayTimer = setTimeout(function() {
659				self.mouseDelayMet = true;
660			}, this.options.delay);
661		}
662
663		if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
664			this._mouseStarted = (this._mouseStart(event) !== false);
665			if (!this._mouseStarted) {
666				event.preventDefault();
667				return true;
668			}
669		}
670
671		// Click event may never have fired (Gecko & Opera)
672		if (true === $.data(event.target, this.widgetName + '.preventClickEvent')) {
673			$.removeData(event.target, this.widgetName + '.preventClickEvent');
674		}
675
676		// these delegates are required to keep context
677		this._mouseMoveDelegate = function(event) {
678			return self._mouseMove(event);
679		};
680		this._mouseUpDelegate = function(event) {
681			return self._mouseUp(event);
682		};
683		$(document)
684			.bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
685			.bind('mouseup.'+this.widgetName, this._mouseUpDelegate);
686
687		event.preventDefault();
688		
689		mouseHandled = true;
690		return true;
691	},
692
693	_mouseMove: function(event) {
694		// IE mouseup check - mouseup happened when mouse was out of window
695		if ($.browser.msie && !(document.documentMode >= 9) && !event.button) {
696			return this._mouseUp(event);
697		}
698
699		if (this._mouseStarted) {
700			this._mouseDrag(event);
701			return event.preventDefault();
702		}
703
704		if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
705			this._mouseStarted =
706				(this._mouseStart(this._mouseDownEvent, event) !== false);
707			(this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
708		}
709
710		return !this._mouseStarted;
711	},
712
713	_mouseUp: function(event) {
714		$(document)
715			.unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
716			.unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
717
718		if (this._mouseStarted) {
719			this._mouseStarted = false;
720
721			if (event.target == this._mouseDownEvent.target) {
722			    $.data(event.target, this.widgetName + '.preventClickEvent', true);
723			}
724
725			this._mouseStop(event);
726		}
727
728		return false;
729	},
730
731	_mouseDistanceMet: function(event) {
732		return (Math.max(
733				Math.abs(this._mouseDownEvent.pageX - event.pageX),
734				Math.abs(this._mouseDownEvent.pageY - event.pageY)
735			) >= this.options.distance
736		);
737	},
738
739	_mouseDelayMet: function(event) {
740		return this.mouseDelayMet;
741	},
742
743	// These are placeholder methods, to be overriden by extending plugin
744	_mouseStart: function(event) {},
745	_mouseDrag: function(event) {},
746	_mouseStop: function(event) {},
747	_mouseCapture: function(event) { return true; }
748});
749
750})(jQuery);
751
752(function( $, undefined ) {
753
754$.widget("ui.draggable", $.ui.mouse, {
755	widgetEventPrefix: "drag",
756	options: {
757		addClasses: true,
758		appendTo: "parent",
759		axis: false,
760		connectToSortable: false,
761		containment: false,
762		cursor: "auto",
763		cursorAt: false,
764		grid: false,
765		handle: false,
766		helper: "original",
767		iframeFix: false,
768		opacity: false,
769		refreshPositions: false,
770		revert: false,
771		revertDuration: 500,
772		scope: "default",
773		scroll: true,
774		scrollSensitivity: 20,
775		scrollSpeed: 20,
776		snap: false,
777		snapMode: "both",
778		snapTolerance: 20,
779		stack: false,
780		zIndex: false
781	},
782	_create: function() {
783
784		if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position")))
785			this.element[0].style.position = 'relative';
786
787		(this.options.addClasses && this.element.addClass("ui-draggable"));
788		(this.options.disabled && this.element.addClass("ui-draggable-disabled"));
789
790		this._mouseInit();
791
792	},
793
794	destroy: function() {
795		if(!this.element.data('draggable')) return;
796		this.element
797			.removeData("draggable")
798			.unbind(".draggable")
799			.removeClass("ui-draggable"
800				+ " ui-draggable-dragging"
801				+ " ui-draggable-disabled");
802		this._mouseDestroy();
803
804		return this;
805	},
806
807	_mouseCapture: function(event) {
808
809		var o = this.options;
810
811		// among others, prevent a drag on a resizable-handle
812		if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle'))
813			return false;
814
815		//Quit if we're not on a valid handle
816		this.handle = this._getHandle(event);
817		if (!this.handle)
818			return false;
819		
820		if ( o.iframeFix ) {
821			$(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
822				$('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>')
823				.css({
824					width: this.offsetWidth+"px", height: this.offsetHeight+"px",
825					position: "absolute", opacity: "0.001", zIndex: 1000
826				})
827				.css($(this).offset())
828				.appendTo("body");
829			});
830		}
831
832		return true;
833
834	},
835
836	_mouseStart: function(event) {
837
838		var o = this.options;
839
840		//Create and append the visible helper
841		this.helper = this._createHelper(event);
842
843		this.helper.addClass("ui-draggable-dragging");
844
845		//Cache the helper size
846		this._cacheHelperProportions();
847
848		//If ddmanager is used for droppables, set the global draggable
849		if($.ui.ddmanager)
850			$.ui.ddmanager.current = this;
851
852		/*
853		 * - Position generation -
854		 * This block generates everything position related - it's the core of draggables.
855		 */
856
857		//Cache the margins of the original element
858		this._cacheMargins();
859
860		//Store the helper's css position
861		this.cssPosition = this.helper.css("position");
862		this.scrollParent = this.helper.scrollParent();
863
864		//The element's absolute position on the page minus margins
865		this.offset = this.positionAbs = this.element.offset();
866		this.offset = {
867			top: this.offset.top - this.margins.top,
868			left: this.offset.left - this.margins.left
869		};
870
871		$.extend(this.offset, {
872			click: { //Where the click happened, relative to the element
873				left: event.pageX - this.offset.left,
874				top: event.pageY - this.offset.top
875			},
876			parent: this._getParentOffset(),
877			relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
878		});
879
880		//Generate the original position
881		this.originalPosition = this.position = this._generatePosition(event);
882		this.originalPageX = event.pageX;
883		this.originalPageY = event.pageY;
884
885		//Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
886		(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
887
888		//Set a containment if given in the options
889		if(o.containment)
890			this._setContainment();
891
892		//Trigger event + callbacks
893		if(this._trigger("start", event) === false) {
894			this._clear();
895			return false;
896		}
897
898		//Recache the helper size
899		this._cacheHelperProportions();
900
901		//Prepare the droppable offsets
902		if ($.ui.ddmanager && !o.dropBehaviour)
903			$.ui.ddmanager.prepareOffsets(this, event);
904
905		
906		this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
907		
908		//If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003)
909		if ( $.ui.ddmanager ) $.ui.ddmanager.dragStart(this, event);
910		
911		return true;
912	},
913
914	_mouseDrag: function(event, noPropagation) {
915
916		//Compute the helpers position
917		this.position = this._generatePosition(event);
918		this.positionAbs = this._convertPositionTo("absolute");
919
920		//Call plugins and callbacks and use the resulting position if something is returned
921		if (!noPropagation) {
922			var ui = this._uiHash();
923			if(this._trigger('drag', event, ui) === false) {
924				this._mouseUp({});
925				return false;
926			}
927			this.position = ui.position;
928		}
929
930		if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
931		if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
932		if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
933
934		return false;
935	},
936
937	_mouseStop: function(event) {
938
939		//If we are using droppables, inform the manager about the drop
940		var dropped = false;
941		if ($.ui.ddmanager && !this.options.dropBehaviour)
942			dropped = $.ui.ddmanager.drop(this, event);
943
944		//if a drop comes from outside (a sortable)
945		if(this.dropped) {
946			dropped = this.dropped;
947			this.dropped = false;
948		}
949		
950		//if the original element is no longer in the DOM don't bother to continue (see #8269)
951		var element = this.element[0], elementInDom = false;
952		while ( element && (element = element.parentNode) ) {
953			if (element == document ) {
954				elementInDom = true;
955			}
956		}
957		if ( !elementInDom && this.options.helper === "original" )
958			return false;
959
960		if((this.options.revert == "invalid" && !dropped) || (this.options.revert == "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) {
961			var self = this;
962			$(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
963				if(self._trigger("stop", event) !== false) {
964					self._clear();
965				}
966			});
967		} else {
968			if(this._trigger("stop", event) !== false) {
969				this._clear();
970			}
971		}
972
973		return false;
974	},
975	
976	_mouseUp: function(event) {
977		//Remove frame helpers
978		$("div.ui-draggable-iframeFix").each(function() { 
979			this.parentNode.removeChild(this); 
980		});
981		
982		//If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003)
983		if( $.ui.ddmanager ) $.ui.ddmanager.dragStop(this, event);
984		
985		return $.ui.mouse.prototype._mouseUp.call(this, event);
986	},
987	
988	cancel: function() {
989		
990		if(this.helper.is(".ui-draggable-dragging")) {
991			this._mouseUp({});
992		} else {
993			this._clear();
994		}
995		
996		return this;
997		
998	},
999
1000	_getHandle: function(event) {
1001
1002		var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false;
1003		$(this.options.handle, this.element)
1004			.find("*")
1005			.andSelf()
1006			.each(function() {
1007				if(this == event.target) handle = true;
1008			});
1009
1010		return handle;
1011
1012	},
1013
1014	_createHelper: function(event) {
1015
1016		var o = this.options;
1017		var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone().removeAttr('id') : this.element);
1018
1019		if(!helper.parents('body').length)
1020			helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));
1021
1022		if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position")))
1023			helper.css("position", "absolute");
1024
1025		return helper;
1026
1027	},
1028
1029	_adjustOffsetFromHelper: function(obj) {
1030		if (typeof obj == 'string') {
1031			obj = obj.split(' ');
1032		}
1033		if ($.isArray(obj)) {
1034			obj = {left: +obj[0], top: +obj[1] || 0};
1035		}
1036		if ('left' in obj) {
1037			this.offset.click.left = obj.left + this.margins.left;
1038		}
1039		if ('right' in obj) {
1040			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
1041		}
1042		if ('top' in obj) {
1043			this.offset.click.top = obj.top + this.margins.top;
1044		}
1045		if ('bottom' in obj) {
1046			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
1047		}
1048	},
1049
1050	_getParentOffset: function() {
1051
1052		//Get the offsetParent and cache its position
1053		this.offsetParent = this.helper.offsetParent();
1054		var po = this.offsetParent.offset();
1055
1056		// This is a special case where we need to modify a offset calculated on start, since the following happened:
1057		// 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
1058		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
1059		//    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
1060		if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
1061			po.left += this.scrollParent.scrollLeft();
1062			po.top += this.scrollParent.scrollTop();
1063		}
1064
1065		if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
1066		|| (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
1067			po = { top: 0, left: 0 };
1068
1069		return {
1070			top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
1071			left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
1072		};
1073
1074	},
1075
1076	_getRelativeOffset: function() {
1077
1078		if(this.cssPosition == "relative") {
1079			var p = this.element.position();
1080			return {
1081				top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
1082				left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
1083			};
1084		} else {
1085			return { top: 0, left: 0 };
1086		}
1087
1088	},
1089
1090	_cacheMargins: function() {
1091		this.margins = {
1092			left: (parseInt(this.element.css("marginLeft"),10) || 0),
1093			top: (parseInt(this.element.css("marginTop"),10) || 0),
1094			right: (parseInt(this.element.css("marginRight"),10) || 0),
1095			bottom: (parseInt(this.element.css("marginBottom"),10) || 0)
1096		};
1097	},
1098
1099	_cacheHelperProportions: function() {
1100		this.helperProportions = {
1101			width: this.helper.outerWidth(),
1102			height: this.helper.outerHeight()
1103		};
1104	},
1105
1106	_setContainment: function() {
1107
1108		var o = this.options;
1109		if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
1110		if(o.containment == 'document' || o.containment == 'window') this.containment = [
1111			o.containment == 'document' ? 0 : $(window).scrollLeft() - this.offset.relative.left - this.offset.parent.left,
1112			o.containment == 'document' ? 0 : $(window).scrollTop() - this.offset.relative.top - this.offset.parent.top,
1113			(o.containment == 'document' ? 0 : $(window).scrollLeft()) + $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
1114			(o.containment == 'document' ? 0 : $(window).scrollTop()) + ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
1115		];
1116
1117		if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) {
1118		        var c = $(o.containment);
1119			var ce = c[0]; if(!ce) return;
1120			var co = c.offset();
1121			var over = ($(ce).css("overflow") != 'hidden');
1122
1123			this.containment = [
1124				(parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0),
1125				(parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0),
1126				(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left - this.margins.right,
1127				(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top  - this.margins.bottom
1128			];
1129			this.relative_container = c;
1130
1131		} else if(o.containment.constructor == Array) {
1132			this.containment = o.containment;
1133		}
1134
1135	},
1136
1137	_convertPositionTo: function(d, pos) {
1138
1139		if(!pos) pos = this.position;
1140		var mod = d == "absolute" ? 1 : -1;
1141		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
1142
1143		return {
1144			top: (
1145				pos.top																	// The absolute mouse position
1146				+ this.offset.relative.top * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
1147				+ this.offset.parent.top * mod											// The offsetParent's offset without borders (offset + border)
1148				- ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
1149			),
1150			left: (
1151				pos.left																// The absolute mouse position
1152				+ this.offset.relative.left * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
1153				+ this.offset.parent.left * mod											// The offsetParent's offset without borders (offset + border)
1154				- ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
1155			)
1156		};
1157
1158	},
1159
1160	_generatePosition: function(event) {
1161
1162		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
1163		var pageX = event.pageX;
1164		var pageY = event.pageY;
1165
1166		/*
1167		 * - Position constraining -
1168		 * Constrain the position to a mix of grid, containment.
1169		 */
1170
1171		if(this.originalPosition) { //If we are not dragging yet, we won't check for options
1172		         var containment;
1173		         if(this.containment) {
1174				 if (this.relative_container){
1175				     var co = this.relative_container.offset();
1176				     containment = [ this.containment[0] + co.left,
1177						     this.containment[1] + co.top,
1178						     this.containment[2] + co.left,
1179						     this.containment[3] + co.top ];
1180				 }
1181				 else {
1182				     containment = this.containment;
1183				 }
1184
1185				if(event.pageX - this.offset.click.left < containment[0]) pageX = containment[0] + this.offset.click.left;
1186				if(event.pageY - this.offset.click.top < containment[1]) pageY = containment[1] + this.offset.click.top;
1187				if(event.pageX - this.offset.click.left > containment[2]) pageX = containment[2] + this.offset.click.left;
1188				if(event.pageY - this.offset.click.top > containment[3]) pageY = containment[3] + this.offset.click.top;
1189			}
1190
1191			if(o.grid) {
1192				//Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950)
1193				var top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY;
1194				pageY = containment ? (!(top - this.offset.click.top < containment[1] || top - this.offset.click.top > containment[3]) ? top : (!(top - this.offset.click.top < containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
1195
1196				var left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX;
1197				pageX = containment ? (!(left - this.offset.click.left < containment[0] || left - this.offset.click.left > containment[2]) ? left : (!(left - this.offset.click.left < containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
1198			}
1199
1200		}
1201
1202		return {
1203			top: (
1204				pageY																// The absolute mouse position
1205				- this.offset.click.top													// Click offset (relative to the element)
1206				- this.offset.relative.top												// Only for relative positioned nodes: Relative offset from element to offset parent
1207				- this.offset.parent.top												// The offsetParent's offset without borders (offset + border)
1208				+ ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
1209			),
1210			left: (
1211				pageX																// The absolute mouse position
1212				- this.offset.click.left												// Click offset (relative to the element)
1213				- this.offset.relative.left												// Only for relative positioned nodes: Relative offset from element to offset parent
1214				- this.offset.parent.left												// The offsetParent's offset without borders (offset + border)
1215				+ ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
1216			)
1217		};
1218
1219	},
1220
1221	_clear: function() {
1222		this.helper.removeClass("ui-draggable-dragging");
1223		if(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove();
1224		//if($.ui.ddmanager) $.ui.ddmanager.current = null;
1225		this.helper = null;
1226		this.cancelHelperRemoval = false;
1227	},
1228
1229	// From now on bulk stuff - mainly helpers
1230
1231	_trigger: function(type, event, ui) {
1232		ui = ui || this._uiHash();
1233		$.ui.plugin.call(this, type, [event, ui]);
1234		if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins
1235		return $.Widget.prototype._trigger.call(this, type, event, ui);
1236	},
1237
1238	plugins: {},
1239
1240	_uiHash: function(event) {
1241		return {
1242			helper: this.helper,
1243			position: this.position,
1244			originalPosition: this.originalPosition,
1245			offset: this.positionAbs
1246		};
1247	}
1248
1249});
1250
1251$.extend($.ui.draggable, {
1252	version: "1.8.24"
1253});
1254
1255$.ui.plugin.add("draggable", "connectToSortable", {
1256	start: function(event, ui) {
1257
1258		var inst = $(this).data("draggable"), o = inst.options,
1259			uiSortable = $.extend({}, ui, { item: inst.element });
1260		inst.sortables = [];
1261		$(o.connectToSortable).each(function() {
1262			var sortable = $.data(this, 'sortable');
1263			if (sortable && !sortable.options.disabled) {
1264				inst.sortables.push({
1265					instance: sortable,
1266					shouldRevert: sortable.options.revert
1267				});
1268				sortable.refreshPositions();	// Call the sortable's refreshPositions at drag start to refresh the containerCache since the sortable container cache is used in drag and needs to be up to date (this will ensure it's initialised as well as being kept in step with any changes that might have happened on the page).
1269				sortable._trigger("activate", event, uiSortable);
1270			}
1271		});
1272
1273	},
1274	stop: function(event, ui) {
1275
1276		//If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
1277		var inst = $(this).data("draggable"),
1278			uiSortable = $.extend({}, ui, { item: inst.element });
1279
1280		$.each(inst.sortables, function() {
1281			if(this.instance.isOver) {
1282
1283				this.instance.isOver = 0;
1284
1285				inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
1286				this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
1287
1288				//The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid'
1289				if(this.shouldRevert) this.instance.options.revert = true;
1290
1291				//Trigger the stop of the sortable
1292				this.instance._mouseStop(event);
1293
1294				this.instance.options.helper = this.instance.options._helper;
1295
1296				//If the helper has been the original item, restore properties in the sortable
1297				if(inst.options.helper == 'original')
1298					this.instance.currentItem.css({ top: 'auto', left: 'auto' });
1299
1300			} else {
1301				this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
1302				this.instance._trigger("deactivate", event, uiSortable);
1303			}
1304
1305		});
1306
1307	},
1308	drag: function(event, ui) {
1309
1310		var inst = $(this).data("draggable"), self = this;
1311
1312		var checkPos = function(o) {
1313			var dyClick = this.offset.click.top, dxClick = this.offset.click.left;
1314			var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left;
1315			var itemHeight = o.height, itemWidth = o.width;
1316			var itemTop = o.top, itemLeft = o.left;
1317
1318			return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth);
1319		};
1320
1321		$.each(inst.sortables, function(i) {
1322			
1323			//Copy over some variables to allow calling the sortable's native _intersectsWith
1324			this.instance.positionAbs = inst.positionAbs;
1325			this.instance.helperProportions = inst.helperProportions;
1326			this.instance.offset.click = inst.offset.click;
1327			
1328			if(this.instance._intersectsWith(this.instance.containerCache)) {
1329
1330				//If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
1331				if(!this.instance.isOver) {
1332
1333					this.instance.isOver = 1;
1334					//Now we fake the start of dragging for the sortable instance,
1335					//by cloning the list group item, appending it to the sortable and using it as inst.currentItem
1336					//We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one)
1337					this.instance.currentItem = $(self).clone().removeAttr('id').appendTo(this.instance.element).data("sortable-item", true);
1338					this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
1339					this.instance.options.helper = function() { return ui.helper[0]; };
1340
1341					event.target = this.instance.currentItem[0];
1342					this.instance._mouseCapture(event, true);
1343					this.instance._mouseStart(event, true, true);
1344
1345					//Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
1346					this.instance.offset.click.top = inst.offset.click.top;
1347					this.instance.offset.click.left = inst.offset.click.left;
1348					this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
1349					this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
1350
1351					inst._trigger("toSortable", event);
1352					inst.dropped = this.instance.element; //draggable revert needs that
1353					//hack so receive/update callbacks work (mostly)
1354					inst.currentItem = inst.element;
1355					this.instance.fromOutside = inst;
1356
1357				}
1358
1359				//Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable
1360				if(this.instance.currentItem) this.instance._mouseDrag(event);
1361
1362			} else {
1363
1364				//If it doesn't intersect with the sortable, and it intersected before,
1365				//we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
1366				if(this.instance.isOver) {
1367
1368					this.instance.isOver = 0;
1369					this.instance.cancelHelperRemoval = true;
1370					
1371					//Prevent reverting on this forced stop
1372					this.instance.options.revert = false;
1373					
1374					// The out event needs to be triggered independently
1375					this.instance._trigger('out', event, this.instance._uiHash(this.instance));
1376					
1377					this.instance._mouseStop(event, true);
1378					this.instance.options.helper = this.instance.options._helper;
1379
1380					//Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
1381					this.instance.currentItem.remove();
1382					if(this.instance.placeholder) this.instance.placeholder.remove();
1383
1384					inst._trigger("fromSortable", event);
1385					inst.dropped = false; //draggable revert needs that
1386				}
1387
1388			};
1389
1390		});
1391
1392	}
1393});
1394
1395$.ui.plugin.add("draggable", "cursor", {
1396	start: function(event, ui) {
1397		var t = $('body'), o = $(this).data('draggable').options;
1398		if (t.css("cursor")) o._cursor = t.css("cursor");
1399		t.css("cursor", o.cursor);
1400	},
1401	stop: function(event, ui) {
1402		var o = $(this).data('draggable').options;
1403		if (o._cursor) $('body').css("cursor", o._cursor);
1404	}
1405});
1406
1407$.ui.plugin.add("draggable", "opacity", {
1408	start: function(event, ui) {
1409		var t = $(ui.helper), o = $(this).data('draggable').options;
1410		if(t.css("opacity")) o._opacity = t.css("opacity");
1411		t.css('opacity', o.opacity);
1412	},
1413	stop: function(event, ui) {
1414		var o = $(this).data('draggable').options;
1415		if(o._opacity) $(ui.helper).css('opacity', o._opacity);
1416	}
1417});
1418
1419$.ui.plugin.add("draggable", "scroll", {
1420	start: function(event, ui) {
1421		var i = $(this).data("draggable");
1422		if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset();
1423	},
1424	drag: function(event, ui) {
1425
1426		var i = $(this).data("draggable"), o = i.options, scrolled = false;
1427
1428		if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') {
1429
1430			if(!o.axis || o.axis != 'x') {
1431				if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
1432					i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
1433				else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity)
1434					i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
1435			}
1436
1437			if(!o.axis || o.axis != 'y') {
1438				if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
1439					i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
1440				else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity)
1441					i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
1442			}
1443
1444		} else {
1445
1446			if(!o.axis || o.axis != 'x') {
1447				if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
1448					scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
1449				else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
1450					scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
1451			}
1452
1453			if(!o.axis || o.axis != 'y') {
1454				if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
1455					scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
1456				else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
1457					scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
1458			}
1459
1460		}
1461
1462		if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
1463			$.ui.ddmanager.prepareOffsets(i, event);
1464
1465	}
1466});
1467
1468$.ui.plugin.add("draggable", "snap", {
1469	start: function(event, ui) {
1470
1471		var i = $(this).data("draggable"), o = i.options;
1472		i.snapElements = [];
1473
1474		$(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() {
1475			var $t = $(this); var $o = $t.offset();
1476			if(this != i.element[0]) i.snapElements.push({
1477				item: this,
1478				width: $t.outerWidth(), height: $t.outerHeight(),
1479				top: $o.top, left: $o.left
1480			});
1481		});
1482
1483	},
1484	drag: function(event, ui) {
1485
1486		var inst = $(this).data("draggable"), o = inst.options;
1487		var d = o.snapTolerance;
1488
1489		var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
1490			y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
1491
1492		for (var i = inst.snapElements.length - 1; i >= 0; i--){
1493
1494			var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width,
1495				t = inst.snapElements[i].top, b = t + inst.snapElements[i].height;
1496
1497			//Yes, I know, this is insane ;)
1498			if(!((l-d < x1 && x1 < r+d && t-d < y1 && y1 < b+d) || (l-d < x1 && x1 < r+d && t-d < y2 && y2 < b+d) || (l-d < x2 && x2 < r+d && t-d < y1 && y1 < b+d) || (l-d < x2 && x2 < r+d && t-d < y2 && y2 < b+d))) {
1499				if(inst.snapElements[i].snapping) (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
1500				inst.snapElements[i].snapping = false;
1501				continue;
1502			}
1503
1504			if(o.snapMode != 'inner') {
1505				var ts = Math.abs(t - y2) <= d;
1506				var bs = Math.abs(b - y1) <= d;
1507				var ls = Math.abs(l - x2) <= d;
1508				var rs = Math.abs(r - x1) <= d;
1509				if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
1510				if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
1511				if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
1512				if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
1513			}
1514
1515			var first = (ts || bs || ls || rs);
1516
1517			if(o.snapMode != 'outer') {
1518				var ts = Math.abs(t - y1) <= d;
1519				var bs = Math.abs(b - y2) <= d;
1520				var ls = Math.abs(l - x1) <= d;
1521				var rs = Math.abs(r - x2) <= d;
1522				if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
1523				if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
1524				if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
1525				if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
1526			}
1527
1528			if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first))
1529				(inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
1530			inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
1531
1532		};
1533
1534	}
1535});
1536
1537$.ui.plugin.add("draggable", "stack", {
1538	start: function(event, ui) {
1539
1540		var o = $(this).data("draggable").options;
1541
1542		var group = $.makeArray($(o.stack)).sort(function(a,b) {
1543			return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);
1544		});
1545		if (!group.length) { return; }
1546		
1547		var min = parseInt(group[0].style.zIndex) || 0;
1548		$(group).each(function(i) {
1549			this.style.zIndex = min + i;
1550		});
1551
1552		this[0].style.zIndex = min + group.length;
1553
1554	}
1555});
1556
1557$.ui.plugin.add("draggable", "zIndex", {
1558	start: function(event, ui) {
1559		var t = $(ui.helper), o = $(this).data("draggable").options;
1560		if(t.css("zIndex")) o._zIndex = t.css("zIndex");
1561		t.css('zIndex', o.zIndex);
1562	},
1563	stop: function(event, ui) {
1564		var o = $(this).data("draggable").options;
1565		if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex);
1566	}
1567});
1568
1569})(jQuery);
1570
1571(function( $, undefined ) {
1572
1573$.widget("ui.droppable", {
1574	widgetEventPrefix: "drop",
1575	options: {
1576		accept: '*',
1577		activeClass: false,
1578		addClasses: true,
1579		greedy: false,
1580		hoverClass: false,
1581		scope: 'default',
1582		tolerance: 'intersect'
1583	},
1584	_create: function() {
1585
1586		var o = this.options, accept = o.accept;
1587		this.isover = 0; this.isout = 1;
1588
1589		this.accept = $.isFunction(accept) ? accept : function(d) {
1590			return d.is(accept);
1591		};
1592
1593		//Store the droppable's proportions
1594		this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight };
1595
1596		// Add the reference and positions to the manager
1597		$.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || [];
1598		$.ui.ddmanager.droppables[o.scope].push(this);
1599
1600		(o.addClasses && this.element.addClass("ui-droppable"));
1601
1602	},
1603
1604	destroy: function() {
1605		var drop = $.ui.ddmanager.droppables[this.options.scope];
1606		for ( var i = 0; i < drop.length; i++ )
1607			if ( drop[i] == this )
1608				drop.splice(i, 1);
1609
1610		this.element
1611			.removeClass("ui-droppable ui-droppable-disabled")
1612			.removeData("droppable")
1613			.unbind(".droppable");
1614
1615		return this;
1616	},
1617
1618	_setOption: function(key, value) {
1619
1620		if(key == 'accept') {
1621			this.accept = $.isFunction(value) ? value : function(d) {
1622				return d.is(value);
1623			};
1624		}
1625		$.Widget.prototype._setOption.apply(this, arguments);
1626	},
1627
1628	_activate: function(event) {
1629		var draggable = $.ui.ddmanager.current;
1630		if(this.options.activeClass) this.element.addClass(this.options.activeClass);
1631		(draggable && this._trigger('activate', event, this.ui(draggable)));
1632	},
1633
1634	_deactivate: function(event) {
1635		var draggable = $.ui.ddmanager.current;
1636		if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
1637		(draggable && this._trigger('deactivate', event, this.ui(draggable)));
1638	},
1639
1640	_over: function(event) {
1641
1642		var draggable = $.ui.ddmanager.current;
1643		if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
1644
1645		if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
1646			if(this.options.hoverClass) this.element.addClass(this.options.hoverClass);
1647			this._trigger('over', event, this.ui(draggable));
1648		}
1649
1650	},
1651
1652	_out: function(event) {
1653
1654		var draggable = $.ui.ddmanager.current;
1655		if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
1656
1657		if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
1658			if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
1659			this._trigger('out', event, this.ui(draggable));
1660		}
1661
1662	},
1663
1664	_drop: function(event,custom) {
1665
1666		var draggable = custom || $.ui.ddmanager.current;
1667		if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element
1668
1669		var childrenIntersection = false;
1670		this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() {
1671			var inst = $.data(this, 'droppable');
1672			if(
1673				inst.options.greedy
1674				&& !inst.options.disabled
1675				&& inst.options.scope == draggable.options.scope
1676				&& inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element))
1677				&& $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)
1678			) { childrenIntersection = true; return false; }
1679		});
1680		if(childrenIntersection) return false;
1681
1682		if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
1683			if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
1684			if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
1685			this._trigger('drop', event, this.ui(draggable));
1686			return this.element;
1687		}
1688
1689		return false;
1690
1691	},
1692
1693	ui: function(c) {
1694		return {
1695			draggable: (c.currentItem || c.element),
1696			helper: c.helper,
1697			position: c.position,
1698			offset: c.positionAbs
1699		};
1700	}
1701
1702});
1703
1704$.extend($.ui.droppable, {
1705	version: "1.8.24"
1706});
1707
1708$.ui.intersect = function(draggable, droppable, toleranceMode) {
1709
1710	if (!droppable.offset) return false;
1711
1712	var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width,
1713		y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height;
1714	var l = droppable.offset.left, r = l + droppable.proportions.width,
1715		t = droppable.offset.top, b = t + droppable.proportions.height;
1716
1717	switch (toleranceMode) {
1718		case 'fit':
1719			return (l <= x1 && x2 <= r
1720				&& t <= y1 && y2 <= b);
1721			break;
1722		case 'intersect':
1723			return (l < x1 + (draggable.helperProportions.width / 2) // Right Half
1724				&& x2 - (draggable.helperProportions.width / 2) < r // Left Half
1725				&& t < y1 + (draggable.helperProportions.height / 2) // Bottom Half
1726				&& y2 - (draggable.helperProportions.height / 2) < b ); // Top Half
1727			break;
1728		case 'pointer':
1729			var draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left),
1730				draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top),
1731				isOver = $.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width);
1732			return isOver;
1733			break;
1734		case 'touch':
1735			return (
1736					(y1 >= t && y1 <= b) ||	// Top edge touching
1737					(y2 >= t && y2 <= b) ||	// Bottom edge touching
1738					(y1 < t && y2 > b)		// Surrounded vertically
1739				) && (
1740					(x1 >= l && x1 <= r) ||	// Left edge touching
1741					(x2 >= l && x2 <= r) ||	// Right edge touching
1742					(x1 < l && x2 > r)		// Surrounded horizontally
1743				);
1744			break;
1745		default:
1746			return false;
1747			break;
1748		}
1749
1750};
1751
1752/*
1753	This manager tracks offsets of draggables and droppables
1754*/
1755$.ui.ddmanager = {
1756	current: null,
1757	droppables: { 'default': [] },
1758	prepareOffsets: function(t, event) {
1759
1760		var m = $.ui.ddmanager.droppables[t.options.scope] || [];
1761		var type = event ? event.type : null; // workaround for #2317
1762		var list = (t.currentItem || t.element).find(":data(droppable)").andSelf();
1763
1764		droppablesLoop: for (var i = 0; i < m.length; i++) {
1765
1766			if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) continue;	//No disabled and non-accepted
1767			for (var j=0; j < list.length; j++) { if(list[j] == m[i].element[0]) { m[i].proportions.height = 0; continue droppablesLoop; } }; //Filter out elements in the current dragged item
1768			m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue; 									//If the element is not visible, continue
1769
1770			if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables
1771
1772			m[i].offset = m[i].element.offset();
1773			m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };
1774
1775		}
1776
1777	},
1778	drop: function(draggable, event) {
1779
1780		var dropped = false;
1781		$.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
1782
1783			if(!this.options) return;
1784			if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance))
1785				dropped = this._drop.call(this, event) || dropped;
1786
1787			if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
1788				this.isout = 1; this.isover = 0;
1789				this._deactivate.call(this, event);
1790			}
1791
1792		});
1793		return dropped;
1794
1795	},
1796	dragStart: function( draggable, event ) {
1797		//Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003)
1798		draggable.element.parents( ":not(body,html)" ).bind( "scroll.droppable", function() {
1799			if( !draggable.options.refreshPositions ) $.ui.ddmanager.prepareOffsets( draggable, event );
1800		});
1801	},
1802	drag: function(draggable, event) {
1803
1804		//If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
1805		if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event);
1806
1807		//Run through all droppables and check their positions based on specific tolerance options
1808		$.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
1809
1810			if(this.options.disabled || this.greedyChild || !this.visible) return;
1811			var intersects = $.ui.intersect(draggable, this, this.options.tolerance);
1812
1813			var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null);
1814			if(!c) return;
1815
1816			var parentInstance;
1817			if (this.options.greedy) {
1818				// find droppable parents with same scope
1819				var scope = this.options.scope;
1820				var parent = this.element.parents(':data(droppable)').filter(function () {
1821					return $.data(this, 'droppable').options.scope === scope;
1822				});
1823
1824				if (parent.length) {
1825					parentInstance = $.data(parent[0], 'droppable');
1826					parentInstance.greedyChild = (c == 'isover' ? 1 : 0);
1827				}
1828			}
1829
1830			// we just moved into a greedy child
1831			if (parentInstance && c == 'isover') {
1832				parentInstance['isover'] = 0;
1833				parentInstance['isout'] = 1;
1834				parentInstance._out.call(parentInstance, event);
1835			}
1836
1837			this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0;
1838			this[c == "isover" ? "_over" : "_out"].call(this, event);
1839
1840			// we just moved out of a greedy child
1841			if (parentInstance && c == 'isout') {
1842				parentInstance['isout'] = 0;
1843				parentInstance['isover'] = 1;
1844				parentInstance._over.call(parentInstance, event);
1845			}
1846		});
1847
1848	},
1849	dragStop: function( draggable, event ) {
1850		draggable.element.parents( ":not(body,html)" ).unbind( "scroll.droppable" );
1851		//Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003)
1852		if( !draggable.options.refreshPositions ) $.ui.ddmanager.prepareOffsets( draggable, event );
1853	}
1854};
1855
1856})(jQuery);
1857
1858(function( $, undefined ) {
1859
1860$.widget("ui.resizable", $.ui.mouse, {
1861	widgetEventPrefix: "resize",
1862	options: {
1863		alsoResize: false,
1864		animate: false,
1865		animateDuration: "slow",
1866		animateEasing: "swing",
1867		aspectRatio: false,
1868		autoHide: false,
1869		containment: false,
1870		ghost: false,
1871		grid: false,
1872		handles: "e,s,se",
1873		helper: false,
1874		maxHeight: null,
1875		maxWidth: null,
1876		minHeight: 10,
1877		minWidth: 10,
1878		zIndex: 1000
1879	},
1880	_create: function() {
1881
1882		var self = this, o = this.options;
1883		this.element.addClass("ui-resizable");
1884
1885		$.extend(this, {
1886			_aspectRatio: !!(o.aspectRatio),
1887			aspectRatio: o.aspectRatio,
1888			originalElement: this.element,
1889			_proportionallyResizeElements: [],
1890			_helper: o.helper || o.ghost || o.animate ? o.helper || 'ui-resizable-helper' : null
1891		});
1892
1893		//Wrap the element if it cannot hold child nodes
1894		if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {
1895
1896			//Create a wrapper element and set the wrapper to the new current internal element
1897			this.element.wrap(
1898				$('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({
1899					position: this.element.css('position'),
1900					width: this.element.outerWidth(),
1901					height: this.element.outerHeight(),
1902					top: this.element.css('top'),
1903					left: this.element.css('left')
1904				})
1905			);
1906
1907			//Overwrite the original this.element
1908			this.element = this.element.parent().data(
1909				"resizable", this.element.data('resizable')
1910			);
1911
1912			this.elementIsWrapper = true;
1913
1914			//Move margins to the wrapper
1915			this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") });
1916			this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
1917
1918			//Prevent Safari textarea resize
1919			this.originalResizeStyle = this.originalElement.css('resize');
1920			this.originalElement.css('resize', 'none');
1921
1922			//Push the actual element to our proportionallyResize internal array
1923			this._proportionallyResizeElements.push(this.originalElement.css({ position: 'static', zoom: 1, display: 'block' }));
1924
1925			// avoid IE jump (hard set the margin)
1926			this.originalElement.css({ margin: this.originalElement.css('margin') });
1927
1928			// fix handlers offset
1929			this._proportionallyResize();
1930
1931		}
1932
1933		this.handles = o.handles || (!$('.ui-resizable-handle', this.element).length ? "e,s,se" : { n: '.ui-resizable-n', e: '.ui-resizable-e', s: '.ui-resizable-s', w: '.ui-resizable-w', se: '.ui-resizable-se', sw: '.ui-resizable-sw', ne: '.ui-resizable-ne', nw: '.ui-resizable-nw' });
1934		if(this.handles.constructor == String) {
1935
1936			if(this.handles == 'all') this.handles = 'n,e,s,w,se,sw,ne,nw';
1937			var n = this.handles.split(","); this.handles = {};
1938
1939			for(var i = 0; i < n.length; i++) {
1940
1941				var handle = $.trim(n[i]), hname = 'ui-resizable-'+handle;
1942				var axis = $('<div class="ui-resizable-handle ' + hname + '"></div>');
1943
1944				// Apply zIndex to all handles - see #7960
1945				axis.css({ zIndex: o.zIndex });
1946
1947				//TODO : What's going on here?
1948				if ('se' == handle) {
1949					axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se');
1950				};
1951
1952				//Insert into internal handles object and append to element
1953				this.handles[handle] = '.ui-resizable-'+handle;
1954				this.element.append(axis);
1955			}
1956
1957		}
1958
1959		this._renderAxis = function(target) {
1960
1961			target = target || this.element;
1962
1963			for(var i in this.handles) {
1964
1965				if(this.handles[i].constructor == String)
1966					this.handles[i] = $(this.handles[i], this.element).show();
1967
1968				//Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
1969				if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {
1970
1971					var axis = $(this.handles[i], this.element), padWrapper = 0;
1972
1973					//Checking the correct pad and border
1974					padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
1975
1976					//The padding type i have to apply...
1977					var padPos = [ 'padding',
1978						/ne|nw|n/.test(i) ? 'Top' :
1979						/se|sw|s/.test(i) ? 'Bottom' :
1980						/^e$/.test(i) ? 'Right' : 'Left' ].join("");
1981
1982					target.css(padPos, padWrapper);
1983
1984					this._proportionallyResize();
1985
1986				}
1987
1988				//TODO: What's that good for? There's not anything to be executed left
1989				if(!$(this.handles[i]).length)
1990					continue;
1991
1992			}
1993		};
1994
1995		//TODO: make renderAxis a prototype function
1996		this._renderAxis(this.element);
1997
1998		this._handles = $('.ui-resizable-handle', this.element)
1999			.disableSelection();
2000
2001		//Matching axis name
2002		this._handles.mouseover(function() {
2003			if (!self.resizing) {
2004				if (this.className)
2005					var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
2006				//Axis, default = se
2007				self.axis = axis && axis[1] ? axis[1] : 'se';
2008			}
2009		});
2010
2011		//If we want to auto hide the elements
2012		if (o.autoHide) {
2013			this._handles.hide();
2014			$(this.element)
2015				.addClass("ui-resizable-autohide")
2016				.hover(function() {
2017					if (o.disabled) return;
2018					$(this).removeClass("ui-resizable-autohide");
2019					self._handles.show();
2020				},
2021				function(){
2022					if (o.disabled) return;
2023					if (!self.resizing) {
2024						$(this).addClass("ui-resizable-autohide");
2025						self._handles.hide();
2026					}
2027				});
2028		}
2029
2030		//Initialize the mouse interaction
2031		this._mouseInit();
2032
2033	},
2034
2035	destroy: function() {
2036
2037		this._mouseDestroy();
2038
2039		var _destroy = function(exp) {
2040			$(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
2041				.removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove();
2042		};
2043
2044		//TODO: Unwrap at same DOM position
2045		if (this.elementIsWrapper) {
2046			_destroy(this.element);
2047			var wrapper = this.element;
2048			wrapper.after(
2049				this.originalElement.css({
2050					position: wrapper.css('position'),
2051					width: wrapper.outerWidth(),
2052					height: wrapper.outerHeight(),
2053					top: wrapper.css('top'),
2054					left: wrapper.css('left')
2055				})
2056			).remove();
2057		}
2058
2059		this.originalElement.css('resize', this.originalResizeStyle);
2060		_destroy(this.originalElement);
2061
2062		return this;
2063	},
2064
2065	_mouseCapture: function(event) {
2066		var handle = false;
2067		for (var i in this.handles) {
2068			if ($(this.handles[i])[0] == event.target) {
2069				handle = true;
2070			}
2071		}
2072
2073		return !this.options.disabled && handle;
2074	},
2075
2076	_mouseStart: function(event) {
2077
2078		var o = this.options, iniPos = this.element.position(), el = this.element;
2079
2080		this.resizing = true;
2081		this.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() };
2082
2083		// bugfix for http://dev.jquery.com/ticket/1749
2084		if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) {
2085			el.css({ position: 'absolute', top: iniPos.top, left: iniPos.left });
2086		}
2087
2088		this._renderProxy();
2089
2090		var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top'));
2091
2092		if (o.containment) {
2093			curleft += $(o.containment).scrollLeft() || 0;
2094			curtop += $(o.containment).scrollTop() || 0;
2095		}
2096
2097		//Store needed variables
2098		this.offset = this.helper.offset();
2099		this.position = { left: curleft, top: curtop };
2100		this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
2101		this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
2102		this.originalPosition = { left: curleft, top: curtop };
2103		this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
2104		this.originalMousePosition = { left: event.pageX, top: event.pageY };
2105
2106		//Aspect Ratio
2107		this.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);
2108
2109	    var cursor = $('.ui-resizable-' + this.axis).css('cursor');
2110	    $('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor);
2111
2112		el.addClass("ui-resizable-resizing");
2113		this._propagate("start", event);
2114		return true;
2115	},
2116
2117	_mouseDrag: function(event) {
2118
2119		//Increase performance, avoid regex
2120		var el = this.helper, o = this.options, props = {},
2121			self = this, smp = this.originalMousePosition, a = this.axis;
2122
2123		var dx = (event.pageX-smp.left)||0, dy = (event.pageY-smp.top)||0;
2124		var trigger = this._change[a];
2125		if (!trigger) return false;
2126
2127		// Calculate the attrs that will be change
2128		var data = trigger.apply(this, [event, dx, dy]), ie6 = $.browser.msie && $.browser.version < 7, csdif = this.sizeDiff;
2129
2130		// Put this in the mouseDrag handler since the user can start pressing shift while resizing
2131		this._updateVirtualBoundaries(event.shiftKey);
2132		if (this._aspectRatio || event.shiftKey)
2133			data = this._updateRatio(data, event);
2134
2135		data = this._respectSize(data, event);
2136
2137		// plugins callbacks need to be called first
2138		this._propagate("resize", event);
2139
2140		el.css({
2141			top: this.position.top + "px", left: this.position.left + "px",
2142			width: this.size.width + "px", height: this.size.height + "px"
2143		});
2144
2145		if (!this._helper && this._proportionallyResizeElements.length)
2146			this._proportionallyResize();
2147
2148		this._updateCache(data);
2149
2150		// calling the user callback at the end
2151		this._trigger('resize', event, this.ui());
2152
2153		return false;
2154	},
2155
2156	_mouseStop: function(event) {
2157
2158		this.resizing = false;
2159		var o = this.options, self = this;
2160
2161		if(this._helper) {
2162			var pr = this._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
2163				soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
2164				soffsetw = ista ? 0 : self.sizeDiff.width;
2165
2166			var s = { width: (self.helper.width()  - soffsetw), height: (self.helper.height() - soffseth) },
2167				left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
2168				top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
2169
2170			if (!o.animate)
2171				this.element.css($.extend(s, { top: top, left: left }));
2172
2173			self.helper.height(self.size.height);
2174			self.helper.width(self.size.width);
2175
2176			if (this._helper && !o.animate) this._proportionallyResize();
2177		}
2178
2179		$('body').css('cursor', 'auto');
2180
2181		this.element.removeClass("ui-resizable-resizing");
2182
2183		this._propagate("stop", event);
2184
2185		if (this._helper) this.helper.remove();
2186		return false;
2187
2188	},
2189
2190    _updateVirtualBoundaries: function(forceAspectRatio) {
2191        var o = this.options, pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b;
2192
2193        b = {
2194            minWidth: isNumber(o.minWidth) ? o.minWidth : 0,
2195            maxWidth: isNumber(o.maxWidth) ? o.maxWidth : Infinity,
2196            minHeight: isNumber(o.minHeight) ? o.minHeight : 0,
2197            maxHeight: isNumber(o.maxHeight) ? o.maxHeight : Infinity
2198        };
2199
2200        if(this._aspectRatio || forceAspectRatio) {
2201            // We want to create an enclosing box whose aspect ration is the requested one
2202            // First, compute the "projected" size for each dimension based on the aspect ratio and other dimension
2203            pMinWidth = b.minHeight * this.aspectRatio;
2204            pMinHeight = b.minWidth / this.aspectRatio;
2205            pMaxWidth = b.maxHeight * this.aspectRatio;
2206            pMaxHeight = b.maxWidth / this.aspectRatio;
2207
2208            if(pMinWidth > b.minWidth) b.minWidth = pMinWidth;
2209            if(pMinHeight > b.minHeight) b.minHeight = pMinHeight;
2210            if(pMaxWidth < b.maxWidth) b.maxWidth = pMaxWidth;
2211            if(pMaxHeight < b.maxHeight) b.maxHeight = pMaxHeight;
2212        }
2213        this._vBoundaries = b;
2214    },
2215
2216	_updateCache: function(data) {
2217		var o = this.options;
2218		this.offset = this.helper.offset();
2219		if (isNumber(data.left)) this.position.left = data.left;
2220		if (isNumber(data.top)) this.position.top = data.top;
2221		if (isNumber(data.height)) this.size.height = data.height;
2222		if (isNumber(data.width)) this.size.width = data.width;
2223	},
2224
2225	_updateRatio: function(data, event) {
2226
2227		var o = this.options, cpos = this.position, csize = this.size, a = this.axis;
2228
2229		if (isNumber(data.height)) data.width = (data.height * this.aspectRatio);
2230		else if (isNumber(data.width)) data.height = (data.width / this.aspectRatio);
2231
2232		if (a == 'sw') {
2233			data.left = cpos.left + (csize.width - data.width);
2234			data.top = null;
2235		}
2236		if (a == 'nw') {
2237			data.top = cpos.top + (csize.height - data.height);
2238			data.left = cpos.left + (csize.width - data.width);
2239		}
2240
2241		return data;
2242	},
2243
2244	_respectSize: function(data, event) {
2245
2246		var el = this.helper, o = this._vBoundaries, pRatio = this._aspectRatio || event.shiftKey, a = this.axis,
2247				ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
2248					isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height);
2249
2250		if (isminw) data.width = o.minWidth;
2251		if (isminh) data.height = o.minHeight;
2252		if (ismaxw) data.width = o.maxWidth;
2253		if (ismaxh) data.height = o.maxHeight;
2254
2255		var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height;
2256		var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
2257
2258		if (isminw && cw) data.left = dw - o.minWidth;
2259		if (ismaxw && cw) data.left = dw - o.maxWidth;
2260		if (isminh && ch)	data.top = dh - o.minHeight;
2261		if (ismaxh && ch)	data.top = dh - o.maxHeight;
2262
2263		// fixing jump error on top/left - bug #2330
2264		var isNotwh = !data.width && !data.height;
2265		if (isNotwh && !data.left && data.top) data.top = null;
2266		else if (isNotwh && !data.top && data.left) data.left = null;
2267
2268		return data;
2269	},
2270
2271	_proportionallyResize: function() {
2272
2273		var o = this.options;
2274		if (!this._proportionallyResizeElements.length) return;
2275		var element = this.helper || this.element;
2276
2277		for (var i=0; i < this._proportionallyResizeElements.length; i++) {
2278
2279			var prel = this._proportionallyResizeElements[i];
2280
2281			if (!this.borderDif) {
2282				var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')],
2283					p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')];
2284
2285				this.borderDif = $.map(b, function(v, i) {
2286					var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0;
2287					return border + padding;
2288				});
2289			}
2290
2291			if ($.browser.msie && !(!($(element).is(':hidden') || $(element).parents(':hidden').length)))
2292				continue;
2293
2294			prel.css({
2295				height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,
2296				width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0
2297			});
2298
2299		};
2300
2301	},
2302
2303	_renderProxy: function() {
2304
2305		var el = this.element, o = this.options;
2306		this.elementOffset = el.offset();
2307
2308		if(this._helper) {
2309
2310			this.helper = this.helper || $('<div style="overflow:hidden;"></div>');
2311
2312			// fix ie6 offset TODO: This seems broken
2313			var ie6 = $.browser.msie && $.browser.version < 7, ie6offset = (ie6 ? 1 : 0),
2314			pxyoffset = ( ie6 ? 2 : -1 );
2315
2316			this.helper.addClass(this._helper).css({
2317				width: this.element.outerWidth() + pxyoffset,
2318				height: this.element.outerHeight() + pxyoffset,
2319				position: 'absolute',
2320				left: this.elementOffset.left - ie6offset +'px',
2321				top: this.elementOffset.top - ie6offset +'px',
2322				zIndex: ++o.zIndex //TODO: Don't modify option
2323			});
2324
2325			this.helper
2326				.appendTo("body")
2327				.disableSelection();
2328
2329		} else {
2330			this.helper = this.element;
2331		}
2332
2333	},
2334
2335	_change: {
2336		e: function(event, dx, dy) {
2337			return { width: this.originalSize.width + dx };
2338		},
2339		w: function(event, dx, dy) {
2340			var o = this.options, cs = this.originalSize, sp = this.originalPosition;
2341			return { left: sp.left + dx, width: cs.width - dx };
2342		},
2343		n: function(event, dx, dy) {
2344			var o = this.options, cs = this.originalSize, sp = this.originalPosition;
2345			return { top: sp.top + dy, height: cs.height - dy };
2346		},
2347		s: function(event, dx, dy) {
2348			return { height: this.originalSize.height + dy };
2349		},
2350		se: function(event, dx, dy) {
2351			return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
2352		},
2353		sw: function(event, dx, dy) {
2354			return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
2355		},
2356		ne: function(event, dx, dy) {
2357			return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
2358		},
2359		nw: function(event, dx, dy) {
2360			return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
2361		}
2362	},
2363
2364	_propagate: function(n, event) {
2365		$.ui.plugin.call(this, n, [event, this.ui()]);
2366		(n != "resize" && this._trigger(n, event, this.ui()));
2367	},
2368
2369	plugins: {},
2370
2371	ui: function() {
2372		return {
2373			originalElement: this.originalElement,
2374			element: this.element,
2375			helper: this.helper,
2376			position: this.position,
2377			size: this.size,
2378			originalSize: this.originalSize,
2379			originalPosition: this.originalPosition
2380		};
2381	}
2382
2383});
2384
2385$.extend($.ui.resizable, {
2386	version: "1.8.24"
2387});
2388
2389/*
2390 * Resizable Extensions
2391 */
2392
2393$.ui.plugin.add("resizable", "alsoResize", {
2394
2395	start: function (event, ui) {
2396		var self = $(this).data("resizable"), o = self.options;
2397
2398		var _store = function (exp) {
2399			$(exp).each(function() {
2400				var el = $(this);
2401				el.data("resizable-alsoresize", {
2402					width: parseInt(el.width(), 10), height: parseInt(el.height(), 10),
2403					left: parseInt(el.css('left'), 10), top: parseInt(el.css('top'), 10)
2404				});
2405			});
2406		};
2407
2408		if (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) {
2409			if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); }
2410			else { $.each(o.alsoResize, function (exp) { _store(exp); }); }
2411		}else{
2412			_store(o.alsoResize);
2413		}
2414	},
2415
2416	resize: function (event, ui) {
2417		var self = $(this).data("resizable"), o = self.options, os = self.originalSize, op = self.originalPosition;
2418
2419		var delta = {
2420			height: (self.size.height - os.height) || 0, width: (self.size.width - os.width) || 0,
2421			top: (self.position.top - op.top) || 0, left: (self.position.left - op.left) || 0
2422		},
2423
2424		_alsoResize = function (exp, c) {
2425			$(exp).each(function() {
2426				var el = $(this), start = $(this).data("resizable-alsoresize"), style = {}, 
2427					css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ['width', 'height'] : ['width', 'height', 'top', 'left'];
2428
2429				$.each(css, function (i, prop) {
2430					var sum = (start[prop]||0) + (delta[prop]||0);
2431					if (sum && sum >= 0)
2432						style[prop] = sum || null;
2433				});
2434
2435				el.css(style);
2436			});
2437		};
2438
2439		if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
2440			$.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); });
2441		}else{
2442			_alsoResize(o.alsoResize);
2443		}
2444	},
2445
2446	stop: function (event, ui) {
2447		$(this).removeData("resizable-alsoresize");
2448	}
2449});
2450
2451$.ui.plugin.add("resizable", "animate", {
2452
2453	stop: function(event, ui) {
2454		var self = $(this).data("resizable"), o = self.options;
2455
2456		var pr = self._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
2457					soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
2458						soffsetw = ista ? 0 : self.sizeDiff.width;
2459
2460		var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
2461					left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
2462						top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
2463
2464		self.element.animate(
2465			$.extend(style, top && left ? { top: top, left: left } : {}), {
2466				duration: o.animateDuration,
2467				easing: o.animateEasing,
2468				step: function() {
2469
2470					var data = {
2471						width: parseInt(self.element.css('width'), 10),
2472						height: parseInt(self.element.css('height'), 10),
2473						top: parseInt(self.element.css('top'), 10),
2474						left: parseInt(self.element.css('left'), 10)
2475					};
2476
2477					if (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height });
2478
2479					// propagating resize, and updating values for each animation step
2480					self._updateCache(data);
2481					self._propagate("resize", event);
2482
2483				}
2484			}
2485		);
2486	}
2487
2488});
2489
2490$.ui.plugin.add("resizable", "containment", {
2491
2492	start: function(event, ui) {
2493		var self = $(this).data("resizable"), o = self.options, el = self.element;
2494		var oc = o.containment,	ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
2495		if (!ce) return;
2496
2497		self.containerElement = $(ce);
2498
2499		if (/document/.test(oc) || oc == document) {
2500			self.containerOffset = { left: 0, top: 0 };
2501			self.containerPosition = { left: 0, top: 0 };
2502
2503			self.parentData = {
2504				element: $(document), left: 0, top: 0,
2505				width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight
2506			};
2507		}
2508
2509		// i'm a node, so compute top, left, right, bottom
2510		else {
2511			var element = $(ce), p = [];
2512			$([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); });
2513
2514			self.containerOffset = element.offset();
2515			self.containerPosition = element.position();
2516			self.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };
2517
2518			var co = self.containerOffset, ch = self.containerSize.height,	cw = self.containerSize.width,
2519						width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);
2520
2521			self.parentData = {
2522				element: ce, left: co.left, top: co.top, width: width, height: height
2523			};
2524		}
2525	},
2526
2527	resize: function(event, ui) {
2528		var self = $(this).data("resizable"), o = self.options,
2529				ps = self.containerSize, co = self.containerOffset, cs = self.size, cp = self.position,
2530				pRatio = self._aspectRatio || event.shiftKey, cop = { top:0, left:0 }, ce = self.containerElement;
2531
2532		if (ce[0] != document && (/static/).test(ce.css('position'))) cop = co;
2533
2534		if (cp.left < (self._helper ? co.left : 0)) {
2535			self.size.width = self.size.width + (self._helper ? (self.position.left - co.left) : (self.position.left - cop.left));
2536			if (pRatio) self.size.height = self.size.width / self.aspectRatio;
2537			self.position.left = o.helper ? co.left : 0;
2538		}
2539
2540		if (cp.top < (self._helper ? co.top : 0)) {
2541			self.size.height = self.size.height + (self._helper ? (self.position.top - co.top) : self.position.top);
2542			if (pRatio) self.size.width = self.size.height * self.aspectRatio;
2543			self.position.top = self._helper ? co.top : 0;
2544		}
2545
2546		self.offset.left = self.parentData.left+self.position.left;
2547		self.offset.top = self.parentData.top+self.position.top;
2548
2549		var woset = Math.abs( (self._helper ? self.offset.left - cop.left : (self.offset.left - cop.left)) + self.sizeDiff.width ),
2550					hoset = Math.abs( (self._helper ? self.offset.top - cop.top : (self.offset.top - co.top)) + self.sizeDiff.height );
2551
2552		var isParent = self.containerElement.get(0) == self.element.parent().get(0),
2553		    isOffsetRelative = /relative|absolute/.test(self.containerElement.css('position'));
2554
2555		if(isParent && isOffsetRelative) woset -= self.parentData.left;
2556
2557		if (woset + self.size.width >= self.parentData.width) {
2558			self.size.width = self.parentData.width - woset;
2559			if (pRatio) self.size.height = self.size.width / self.aspectRatio;
2560		}
2561
2562		if (hoset + self.size.height >= self.parentData.height) {
2563			self.size.height = self.parentData.height - hoset;
2564			if (pRatio) self.size.width = self.size.height * self.aspectRatio;
2565		}
2566	},
2567
2568	stop: function(event, ui){
2569		var self = $(this).data("resizable"), o = self.options, cp = self.position,
2570				co = self.containerOffset, cop = self.containerPosition, ce = self.containerElement;
2571
2572		var helper = $(self.helper), ho = helper.offset(), w = helper.outerWidth() - self.sizeDiff.width, h = helper.outerHeight() - self.sizeDiff.height;
2573
2574		if (self._helper && !o.animate && (/relative/).test(ce.css('position')))
2575			$(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
2576
2577		if (self._helper && !o.animate && (/static/).test(ce.css('position')))
2578			$(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
2579
2580	}
2581});
2582
2583$.ui.plugin.add("resizable", "ghost", {
2584
2585	start: function(event, ui) {
2586
2587		var self = $(this).data("resizable"), o = self.options, cs = self.size;
2588
2589		self.ghost = self.originalElement.clone();
2590		self.ghost
2591			.css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })
2592			.addClass('ui-resizable-ghost')
2593			.addClass(typeof o.ghost == 'string' ? o.ghost : '');
2594
2595		self.ghost.appendTo(self.helper);
2596
2597	},
2598
2599	resize: function(event, ui){
2600		var self = $(this).data("resizable"), o = self.options;
2601		if (self.ghost) self.ghost.css({ position: 'relative', height: self.size.height, width: self.size.width });
2602	},
2603
2604	stop: function(event, ui){
2605		var self = $(this).data("resizable"), o = self.options;
2606		if (self.ghost && self.helper) self.helper.get(0).removeChild(self.ghost.get(0));
2607	}
2608
2609});
2610
2611$.ui.plugin.add("resizable", "grid", {
2612
2613	resize: function(event, ui) {
2614		var self = $(this).data("resizable"), o = self.options, cs = self.size, os = self.originalSize, op = self.originalPosition, a = self.axis, ratio = o._aspectRatio || event.shiftKey;
2615		o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid;
2616		var ox = Math.round((cs.width - os.width) / (o.grid[0]||1)) * (o.grid[0]||1), oy = Math.round((cs.height - os.height) / (o.grid[1]||1)) * (o.grid[1]||1);
2617
2618		if (/^(se|s|e)$/.test(a)) {
2619			self.size.width = os.width + ox;
2620			self.size.height = os.height + oy;
2621		}
2622		else if (/^(ne)$/.test(a)) {
2623			self.size.width = os.width + ox;
2624			self.size.height = os.height + oy;
2625			self.position.top = op.top - oy;
2626		}
2627		else if (/^(sw)$/.test(a)) {
2628			self.size.width = os.width + ox;
2629			self.size.height = os.height + oy;
2630			self.position.left = op.left - ox;
2631		}
2632		else {
2633			self.size.width = os.width + ox;
2634			self.size.height = os.height + oy;
2635			self.position.top = op.top - oy;
2636			self.position.left = op.left - ox;
2637		}
2638	}
2639
2640});
2641
2642var num = function(v) {
2643	return parseInt(v, 10) || 0;
2644};
2645
2646var isNumber = function(value) {
2647	return !isNaN(parseInt(value, 10));
2648};
2649
2650})(jQuery);
2651
2652(function( $, undefined ) {
2653
2654$.widget("ui.selectable", $.ui.mouse, {
2655	options: {
2656		appendTo: 'body',
2657		autoRefresh: true,
2658		distance: 0,
2659		filter: '*',
2660		tolerance: 'touch'
2661	},
2662	_create: function() {
2663		var self = this;
2664
2665		this.element.addClass("ui-selectable");
2666
2667		this.dragged = false;
2668
2669		// cache selectee children based on filter
2670		var selectees;
2671		this.refresh = function() {
2672			selectees = $(self.options.filter, self.element[0]);
2673			selectees.addClass("ui-selectee");
2674			selectees.each(function() {
2675				var $this = $(this);
2676				var pos = $this.offset();
2677				$.data(this, "selectable-item", {
2678					element: this,
2679					$element: $this,
2680					left: pos.left,
2681					top: pos.top,
2682					right: pos.left + $this.outerWidth(),
2683					bottom: pos.top + $this.outerHeight(),
2684					startselected: false,
2685					selected: $this.hasClass('ui-selected'),
2686					selecting: $this.hasClass('ui-selecting'),
2687					unselecting: $this.hasClass('ui-unselecting')
2688				});
2689			});
2690		};
2691		this.refresh();
2692
2693		this.selectees = selectees.addClass("ui-selectee");
2694
2695		this._mouseInit();
2696
2697		this.helper = $("<div class='ui-selectable-helper'></div>");
2698	},
2699
2700	destroy: function() {
2701		this.selectees
2702			.removeClass("ui-selectee")
2703			.removeData("selectable-item");
2704		this.element
2705			.removeClass("ui-selectable ui-selectable-disabled")
2706			.removeData("selectable")
2707			.unbind(".selectable");
2708		this._mouseDestroy();
2709
2710		return this;
2711	},
2712
2713	_mouseStart: function(event) {
2714		var self = this;
2715
2716		this.opos = [event.pageX, event.pageY];
2717
2718		if (this.options.disabled)
2719			return;
2720
2721		var options = this.options;
2722
2723		this.selectees = $(options.filter, this.element[0]);
2724
2725		this._trigger("start", event);
2726
2727		$(options.appendTo).append(this.helper);
2728		// position helper (lasso)
2729		this.helper.css({
2730			"left": event.clientX,
2731			"top": event.clientY,
2732			"width": 0,
2733			"height": 0
2734		});
2735
2736		if (options.autoRefresh) {
2737			this.refresh();
2738		}
2739
2740		this.selectees.filter('.ui-selected').each(function() {
2741			var selectee = $.data(this, "selectable-item");
2742			selectee.startselected = true;
2743			if (!event.metaKey && !event.ctrlKey) {
2744				selectee.$element.removeClass('ui-selected');
2745				selectee.selected = false;
vendor: 4,195 bytes, lines 2746-2884
2746				selectee.$element.addClass('ui-unselecting');
2747				selectee.unselecting = true;
2748				// selectable UNSELECTING callback
2749				self._trigger("unselecting", event, {
2750					unselecting: selectee.element
2751				});
2752			}
2753		});
2754
2755		$(event.target).parents().andSelf().each(function() {
2756			var selectee = $.data(this, "selectable-item");
2757			if (selectee) {
2758				var doSelect = (!event.metaKey && !event.ctrlKey) || !selectee.$element.hasClass('ui-selected');
2759				selectee.$element
2760					.removeClass(doSelect ? "ui-unselecting" : "ui-selected")
2761					.addClass(doSelect ? "ui-selecting" : "ui-unselecting");
2762				selectee.unselecting = !doSelect;
2763				selectee.selecting = doSelect;
2764				selectee.selected = doSelect;
2765				// selectable (UN)SELECTING callback
2766				if (doSelect) {
2767					self._trigger("selecting", event, {
2768						selecting: selectee.element
2769					});
2770				} else {
2771					self._trigger("unselecting", event, {
2772						unselecting: selectee.element
2773					});
2774				}
2775				return false;
2776			}
2777		});
2778
2779	},
2780
2781	_mouseDrag: function(event) {
2782		var self = this;
2783		this.dragged = true;
2784
2785		if (this.options.disabled)
2786			return;
2787
2788		var options = this.options;
2789
2790		var x1 = this.opos[0], y1 = this.opos[1], x2 = event.pageX, y2 = event.pageY;
2791		if (x1 > x2) { var tmp = x2; x2 = x1; x1 = tmp; }
2792		if (y1 > y2) { var tmp = y2; y2 = y1; y1 = tmp; }
2793		this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1});
2794
2795		this.selectees.each(function() {
2796			var selectee = $.data(this, "selectable-item");
2797			//prevent helper from being selected if appendTo: selectable
2798			if (!selectee || selectee.element == self.element[0])
2799				return;
2800			var hit = false;
2801			if (options.tolerance == 'touch') {
2802				hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
2803			} else if (options.tolerance == 'fit') {
2804				hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
2805			}
2806
2807			if (hit) {
2808				// SELECT
2809				if (selectee.selected) {
2810					selectee.$element.removeClass('ui-selected');
2811					selectee.selected = false;
2812				}
2813				if (selectee.unselecting) {
2814					selectee.$element.removeClass('ui-unselecting');
2815					selectee.unselecting = false;
2816				}
2817				if (!selectee.selecting) {
2818					selectee.$element.addClass('ui-selecting');
2819					selectee.selecting = true;
2820					// selectable SELECTING callback
2821					self._trigger("selecting", event, {
2822						selecting: selectee.element
2823					});
2824				}
2825			} else {
2826				// UNSELECT
2827				if (selectee.selecting) {
2828					if ((event.metaKey || event.ctrlKey) && selectee.startselected) {
2829						selectee.$element.removeClass('ui-selecting');
2830						selectee.selecting = false;
2831						selectee.$element.addClass('ui-selected');
2832						selectee.selected = true;
2833					} else {
2834						selectee.$element.removeClass('ui-selecting');
2835						selectee.selecting = false;
2836						if (selectee.startselected) {
2837							selectee.$element.addClass('ui-unselecting');
2838							selectee.unselecting = true;
2839						}
2840						// selectable UNSELECTING callback
2841						self._trigger("unselecting", event, {
2842							unselecting: selectee.element
2843						});
2844					}
2845				}
2846				if (selectee.selected) {
2847					if (!event.metaKey && !event.ctrlKey && !selectee.startselected) {
2848						selectee.$element.removeClass('ui-selected');
2849						selectee.selected = false;
2850
2851						selectee.$element.addClass('ui-unselecting');
2852						selectee.unselecting = true;
2853						// selectable UNSELECTING callback
2854						self._trigger("unselecting", event, {
2855							unselecting: selectee.element
2856						});
2857					}
2858				}
2859			}
2860		});
2861
2862		return false;
2863	},
2864
2865	_mouseStop: function(event) {
2866		var self = this;
2867
2868		this.dragged = false;
2869
2870		var options = this.options;
2871
2872		$('.ui-unselecting', this.element[0]).each(function() {
2873			var selectee = $.data(this, "selectable-item");
2874			selectee.$element.removeClass('ui-unselecting');
2875			selectee.unselecting = false;
2876			selectee.startselected = false;
2877			self._trigger("unselected", event, {
2878				unselected: selectee.element
2879			});
2880		});
2881		$('.ui-selecting', this.element[0]).each(function() {
2882			var selectee = $.data(this, "selectable-item");
2883			selectee.$element.removeClass('ui-selecting').addClass('ui-selected');
2884			selectee.selecting = false;
2885			selectee.selected = true;
2886			selectee.startselected = true;
2887			self._trigger("selected", event, {
2888				selected: selectee.element
2889			});
2890		});
2891		this._trigger("stop", event);
2892
2893		this.helper.remove();
2894
2895		return false;
2896	}
2897
2898});
2899
2900$.extend($.ui.selectable, {
2901	version: "1.8.24"
2902});
2903
2904})(jQuery);
2905
2906(function( $, undefined ) {
2907
2908$.widget("ui.sortable", $.ui.mouse, {
2909	widgetEventPrefix: "sort",
2910	ready: false,
2911	options: {
2912		appendTo: "parent",
2913		axis: false,
2914		connectWith: false,
2915		containment: false,
2916		cursor: 'auto',
2917		cursorAt: false,
2918		dropOnEmpty: true,
2919		forcePlaceholderSize: false,
2920		forceHelperSize: false,
2921		grid: false,
2922		handle: false,
2923		helper: "original",
2924		items: '> *',
2925		opacity: false,
2926		placeholder: false,
2927		revert: false,
2928		scroll: true,
2929		scrollSensitivity: 20,
2930		scrollSpeed: 20,
2931		scope: "default",
2932		tolerance: "intersect",
2933		zIndex: 1000
2934	},
2935	_create: function() {
2936
2937		var o = this.options;
2938		this.containerCache = {};
2939		this.element.addClass("ui-sortable");
2940
2941		//Get the items
2942		this.refresh();
2943
2944		//Let's determine if the items are being displayed horizontally
2945		this.floating = this.items.length ? o.axis === 'x' || (/left|right/).test(this.items[0].item.css('float')) || (/inline|table-cell/).test(this.items[0].item.css('display')) : false;
2946
2947		//Let's determine the parent's offset
2948		this.offset = this.element.offset();
2949
2950		//Initialize mouse events for interaction
2951		this._mouseInit();
2952		
2953		//We're ready to go
2954		this.ready = true
2955
2956	},
2957
2958	destroy: function() {
2959		$.Widget.prototype.destroy.call( this );
2960		this.element
2961			.removeClass("ui-sortable ui-sortable-disabled");
2962		this._mouseDestroy();
2963
2964		for ( var i = this.items.length - 1; i >= 0; i-- )
2965			this.items[i].item.removeData(this.widgetName + "-item");
2966
2967		return this;
2968	},
2969
2970	_setOption: function(key, value){
2971		if ( key === "disabled" ) {
2972			this.options[ key ] = value;
2973	
2974			this.widget()
2975				[ value ? "addClass" : "removeClass"]( "ui-sortable-disabled" );
2976		} else {
2977			// Don't call widget base _setOption for disable as it adds ui-state-disabled class
2978			$.Widget.prototype._setOption.apply(this, arguments);
2979		}
2980	},
2981
2982	_mouseCapture: function(event, overrideHandle) {
2983		var that = this;
2984
2985		if (this.reverting) {
2986			return false;
2987		}
2988
2989		if(this.options.disabled || this.options.type == 'static') return false;
2990
2991		//We have to refresh the items data once first
2992		this._refreshItems(event);
2993
2994		//Find out if the clicked node (or one of its parents) is a actual item in this.items
2995		var currentItem = null, self = this, nodes = $(event.target).parents().each(function() {
2996			if($.data(this, that.widgetName + '-item') == self) {
2997				currentItem = $(this);
2998				return false;
2999			}
3000		});
3001		if($.data(event.target, that.widgetName + '-item') == self) currentItem = $(event.target);
3002
3003		if(!currentItem) return false;
3004		if(this.options.handle && !overrideHandle) {
3005			var validHandle = false;
3006
3007			$(this.options.handle, currentItem).find("*").andSelf().each(function() { if(this == event.target) validHandle = true; });
3008			if(!validHandle) return false;
3009		}
3010
3011		this.currentItem = currentItem;
3012		this._removeCurrentsFromItems();
3013		return true;
3014
3015	},
3016
3017	_mouseStart: function(event, overrideHandle, noActivation) {
3018
3019		var o = this.options, self = this;
3020		this.currentContainer = this;
3021
3022		//We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
3023		this.refreshPositions();
3024
3025		//Create and append the visible helper
3026		this.helper = this._createHelper(event);
3027
3028		//Cache the helper size
3029		this._cacheHelperProportions();
3030
3031		/*
3032		 * - Position generation -
3033		 * This block generates everything position related - it's the core of draggables.
3034		 */
3035
3036		//Cache the margins of the original element
3037		this._cacheMargins();
3038
3039		//Get the next scrolling parent
3040		this.scrollParent = this.helper.scrollParent();
3041
3042		//The element's absolute position on the page minus margins
3043		this.offset = this.currentItem.offset();
3044		this.offset = {
3045			top: this.offset.top - this.margins.top,
3046			left: this.offset.left - this.margins.left
3047		};
3048
3049		$.extend(this.offset, {
3050			click: { //Where the click happened, relative to the element
3051				left: event.pageX - this.offset.left,
3052				top: event.pageY - this.offset.top
3053			},
3054			parent: this._getParentOffset(),
3055			relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
3056		});
3057
3058		// Only after we got the offset, we can change the helper's position to absolute
3059		// TODO: Still need to figure out a way to make relative sorting possible
3060		this.helper.css("position", "absolute");
3061		this.cssPosition = this.helper.css("position");
3062		
3063		//Generate the original position
3064		this.originalPosition = this._generatePosition(event);
3065		this.originalPageX = event.pageX;
3066		this.originalPageY = event.pageY;
3067
3068		//Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
3069		(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
3070
3071		//Cache the former DOM position
3072		this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };
3073
3074		//If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way
3075		if(this.helper[0] != this.currentItem[0]) {
3076			this.currentItem.hide();
3077		}
3078
3079		//Create the placeholder
3080		this._createPlaceholder();
3081
3082		//Set a containment if given in the options
3083		if(o.containment)
3084			this._setContainment();
3085
3086		if(o.cursor) { // cursor option
3087			if ($('body').css("cursor")) this._storedCursor = $('body').css("cursor");
3088			$('body').css("cursor", o.cursor);
3089		}
3090
3091		if(o.opacity) { // opacity option
3092			if (this.helper.css("opacity")) this._storedOpacity = this.helper.css("opacity");
3093			this.helper.css("opacity", o.opacity);
3094		}
3095
3096		if(o.zIndex) { // zIndex option
3097			if (this.helper.css("zIndex")) this._storedZIndex = this.helper.css("zIndex");
3098			this.helper.css("zIndex", o.zIndex);
3099		}
3100
3101		//Prepare scrolling
3102		if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML')
3103			this.overflowOffset = this.scrollParent.offset();
3104
3105		//Call callbacks
3106		this._trigger("start", event, this._uiHash());
3107
3108		//Recache the helper size
3109		if(!this._preserveHelperProportions)
3110			this._cacheHelperProportions();
3111
3112
3113		//Post 'activate' events to possible containers
3114		if(!noActivation) {
3115			 for (var i = this.containers.length - 1; i >= 0; i--) { this.containers[i]._trigger("activate", event, self._uiHash(this)); }
3116		}
3117
3118		//Prepare possible droppables
3119		if($.ui.ddmanager)
3120			$.ui.ddmanager.current = this;
3121
3122		if ($.ui.ddmanager && !o.dropBehaviour)
3123			$.ui.ddmanager.prepareOffsets(this, event);
3124
3125		this.dragging = true;
3126
3127		this.helper.addClass("ui-sortable-helper");
3128		this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
3129		return true;
3130
3131	},
3132
3133	_mouseDrag: function(event) {
3134
3135		//Compute the helpers position
3136		this.position = this._generatePosition(event);
3137		this.positionAbs = this._convertPositionTo("absolute");
3138
3139		if (!this.lastPositionAbs) {
3140			this.lastPositionAbs = this.positionAbs;
3141		}
3142
3143		//Do scrolling
3144		if(this.options.scroll) {
3145			var o = this.options, scrolled = false;
3146			if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') {
3147
3148				if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
3149					this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
3150				else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity)
3151					this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
3152
3153				if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
3154					this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
3155				else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity)
3156					this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
3157
3158			} else {
3159
3160				if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
3161					scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
3162				else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
3163					scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
3164
3165				if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
3166					scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
3167				else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
3168					scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
3169
3170			}
3171
3172			if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
3173				$.ui.ddmanager.prepareOffsets(this, event);
3174		}
3175
3176		//Regenerate the absolute position used for position checks
3177		this.positionAbs = this._convertPositionTo("absolute");
3178
3179		//Set the helper position
3180		if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
3181		if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
3182
3183		//Rearrange
3184		for (var i = this.items.length - 1; i >= 0; i--) {
3185
3186			//Cache variables and intersection, continue if no intersection
3187			var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item);
3188			if (!intersection) continue;
3189
3190			// Only put the placeholder inside the current Container, skip all
3191			// items form other containers. This works because when moving
3192			// an item from one container to another the
3193			// currentContainer is switched before the placeholder is moved.
3194			//
3195			// Without this moving items in "sub-sortables" can cause the placeholder to jitter
3196			// beetween the outer and inner container.
3197			if (item.instance !== this.currentContainer) continue;
3198
3199			if (itemElement != this.currentItem[0] //cannot intersect with itself
3200				&&	this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before
3201				&&	!$.ui.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked
3202				&& (this.options.type == 'semi-dynamic' ? !$.ui.contains(this.element[0], itemElement) : true)
3203				//&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container
3204			) {
3205
3206				this.direction = intersection == 1 ? "down" : "up";
3207
3208				if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) {
3209					this._rearrange(event, item);
3210				} else {
3211					break;
3212				}
3213
3214				this._trigger("change", event, this._uiHash());
3215				break;
3216			}
3217		}
3218
3219		//Post events to containers
3220		this._contactContainers(event);
3221
3222		//Interconnect with droppables
3223		if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
3224
3225		//Call callbacks
3226		this._trigger('sort', event, this._uiHash());
3227
3228		this.lastPositionAbs = this.positionAbs;
3229		return false;
3230
3231	},
3232
3233	_mouseStop: function(event, noPropagation) {
3234
3235		if(!event) return;
3236
3237		//If we are using droppables, inform the manager about the drop
3238		if ($.ui.ddmanager && !this.options.dropBehaviour)
3239			$.ui.ddmanager.drop(this, event);
3240
3241		if(this.options.revert) {
3242			var self = this;
3243			var cur = self.placeholder.offset();
3244
3245			self.reverting = true;
3246
3247			$(this.helper).animate({
3248				left: cur.left - this.offset.parent.left - self.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft),
3249				top: cur.top - this.offset.parent.top - self.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop)
3250			}, parseInt(this.options.revert, 10) || 500, function() {
3251				self._clear(event);
3252			});
3253		} else {
3254			this._clear(event, noPropagation);
3255		}
3256
3257		return false;
3258
3259	},
3260
3261	cancel: function() {
3262
3263		var self = this;
3264
3265		if(this.dragging) {
3266
3267			this._mouseUp({ target: null });
3268
3269			if(this.options.helper == "original")
3270				this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
3271			else
3272				this.currentItem.show();
3273
3274			//Post deactivating events to containers
3275			for (var i = this.containers.length - 1; i >= 0; i--){
3276				this.containers[i]._trigger("deactivate", null, self._uiHash(this));
3277				if(this.containers[i].containerCache.over) {
3278					this.containers[i]._trigger("out", null, self._uiHash(this));
3279					this.containers[i].containerCache.over = 0;
3280				}
3281			}
3282
3283		}
3284
3285		if (this.placeholder) {
3286			//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
3287			if(this.placeholder[0].parentNode) this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
3288			if(this.options.helper != "original" && this.helper && this.helper[0].parentNode) this.helper.remove();
3289
3290			$.extend(this, {
3291				helper: null,
3292				dragging: false,
3293				reverting: false,
3294				_noFinalSort: null
3295			});
3296
3297			if(this.domPosition.prev) {
3298				$(this.domPosition.prev).after(this.currentItem);
3299			} else {
3300				$(this.domPosition.parent).prepend(this.currentItem);
3301			}
3302		}
3303
3304		return this;
3305
3306	},
3307
3308	serialize: function(o) {
3309
3310		var items = this._getItemsAsjQuery(o && o.connected);
3311		var str = []; o = o || {};
3312
3313		$(items).each(function() {
3314			var res = ($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
3315			if(res) str.push((o.key || res[1]+'[]')+'='+(o.key && o.expression ? res[1] : res[2]));
3316		});
3317
3318		if(!str.length && o.key) {
3319			str.push(o.key + '=');
3320		}
3321
3322		return str.join('&');
3323
3324	},
3325
3326	toArray: function(o) {
3327
3328		var items = this._getItemsAsjQuery(o && o.connected);
3329		var ret = []; o = o || {};
3330
3331		items.each(function() { ret.push($(o.item || this).attr(o.attribute || 'id') || ''); });
3332		return ret;
3333
3334	},
3335
3336	/* Be careful with the following core functions */
3337	_intersectsWith: function(item) {
3338
3339		var x1 = this.positionAbs.left,
3340			x2 = x1 + this.helperProportions.width,
3341			y1 = this.positionAbs.top,
3342			y2 = y1 + this.helperProportions.height;
3343
3344		var l = item.left,
3345			r = l + item.width,
3346			t = item.top,
3347			b = t + item.height;
3348
3349		var dyClick = this.offset.click.top,
3350			dxClick = this.offset.click.left;
3351
3352		var isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r;
3353
3354		if(	   this.options.tolerance == "pointer"
3355			|| this.options.forcePointerForContainers
3356			|| (this.options.tolerance != "pointer" && this.helperProportions[this.floating ? 'width' : 'height'] > item[this.floating ? 'width' : 'height'])
3357		) {
3358			return isOverElement;
3359		} else {
3360
3361			return (l < x1 + (this.helperProportions.width / 2) // Right Half
3362				&& x2 - (this.helperProportions.width / 2) < r // Left Half
3363				&& t < y1 + (this.helperProportions.height / 2) // Bottom Half
3364				&& y2 - (this.helperProportions.height / 2) < b ); // Top Half
3365
3366		}
3367	},
3368
3369	_intersectsWithPointer: function(item) {
3370
3371		var isOverElementHeight = (this.options.axis === 'x') || $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
3372			isOverElementWidth = (this.options.axis === 'y') || $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
3373			isOverElement = isOverElementHeight && isOverElementWidth,
3374			verticalDirection = this._getDragVerticalDirection(),
3375			horizontalDirection = this._getDragHorizontalDirection();
3376
3377		if (!isOverElement)
3378			return false;
3379
3380		return this.floating ?
3381			( ((horizontalDirection && horizontalDirection == "right") || verticalDirection == "down") ? 2 : 1 )
3382			: ( verticalDirection && (verticalDirection == "down" ? 2 : 1) );
3383
3384	},
3385
3386	_intersectsWithSides: function(item) {
3387
3388		var isOverBottomHalf = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),
3389			isOverRightHalf = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
3390			verticalDirection = this._getDragVerticalDirection(),
3391			horizontalDirection = this._getDragHorizontalDirection();
3392
3393		if (this.floating && horizontalDirection) {
3394			return ((horizontalDirection == "right" && isOverRightHalf) || (horizontalDirection == "left" && !isOverRightHalf));
3395		} else {
3396			return verticalDirection && ((verticalDirection == "down" && isOverBottomHalf) || (verticalDirection == "up" && !isOverBottomHalf));
3397		}
3398
3399	},
3400
3401	_getDragVerticalDirection: function() {
3402		var delta = this.positionAbs.top - this.lastPositionAbs.top;
3403		return delta != 0 && (delta > 0 ? "down" : "up");
3404	},
3405
3406	_getDragHorizontalDirection: function() {
3407		var delta = this.positionAbs.left - this.lastPositionAbs.left;
3408		return delta != 0 && (delta > 0 ? "right" : "left");
3409	},
3410
3411	refresh: function(event) {
3412		this._refreshItems(event);
3413		this.refreshPositions();
3414		return this;
3415	},
3416
3417	_connectWith: function() {
3418		var options = this.options;
3419		return options.connectWith.constructor == String
3420			? [options.connectWith]
3421			: options.connectWith;
3422	},
3423	
3424	_getItemsAsjQuery: function(connected) {
3425
3426		var self = this;
3427		var items = [];
3428		var queries = [];
3429		var connectWith = this._connectWith();
3430
3431		if(connectWith && connected) {
3432			for (var i = connectWith.length - 1; i >= 0; i--){
3433				var cur = $(connectWith[i]);
3434				for (var j = cur.length - 1; j >= 0; j--){
3435					var inst = $.data(cur[j], this.widgetName);
3436					if(inst && inst != this && !inst.options.disabled) {
3437						queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), inst]);
3438					}
3439				};
3440			};
3441		}
3442
3443		queries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), this]);
3444
3445		for (var i = queries.length - 1; i >= 0; i--){
3446			queries[i][0].each(function() {
3447				items.push(this);
3448			});
3449		};
3450
3451		return $(items);
3452
3453	},
3454
3455	_removeCurrentsFromItems: function() {
3456
3457		var list = this.currentItem.find(":data(" + this.widgetName + "-item)");
3458
3459		for (var i=0; i < this.items.length; i++) {
3460
3461			for (var j=0; j < list.length; j++) {
3462				if(list[j] == this.items[i].item[0])
3463					this.items.splice(i,1);
3464			};
3465
3466		};
3467
3468	},
3469
3470	_refreshItems: function(event) {
3471
3472		this.items = [];
3473		this.containers = [this];
3474		var items = this.items;
3475		var self = this;
3476		var queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]];
3477		var connectWith = this._connectWith();
3478
3479		if(connectWith && this.ready) { //Shouldn't be run the first time through due to massive slow-down
3480			for (var i = connectWith.length - 1; i >= 0; i--){
3481				var cur = $(connectWith[i]);
3482				for (var j = cur.length - 1; j >= 0; j--){
3483					var inst = $.data(cur[j], this.widgetName);
3484					if(inst && inst != this && !inst.options.disabled) {
3485						queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
3486						this.containers.push(inst);
3487					}
3488				};
3489			};
3490		}
3491
3492		for (var i = queries.length - 1; i >= 0; i--) {
3493			var targetData = queries[i][1];
3494			var _queries = queries[i][0];
3495
3496			for (var j=0, queriesLength = _queries.length; j < queriesLength; j++) {
3497				var item = $(_queries[j]);
3498
3499				item.data(this.widgetName + '-item', targetData); // Data for target checking (mouse manager)
3500
3501				items.push({
3502					item: item,
3503					instance: targetData,
3504					width: 0, height: 0,
3505					left: 0, top: 0
3506				});
3507			};
3508		};
3509
3510	},
3511
3512	refreshPositions: function(fast) {
3513
3514		//This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
3515		if(this.offsetParent && this.helper) {
3516			this.offset.parent = this._getParentOffset();
3517		}
3518
3519		for (var i = this.items.length - 1; i >= 0; i--){
3520			var item = this.items[i];
3521
3522			//We ignore calculating positions of all connected containers when we're not over them
3523			if(item.instance != this.currentContainer && this.currentContainer && item.item[0] != this.currentItem[0])
3524				continue;
3525
3526			var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
3527
3528			if (!fast) {
3529				item.width = t.outerWidth();
3530				item.height = t.outerHeight();
3531			}
3532
3533			var p = t.offset();
3534			item.left = p.left;
3535			item.top = p.top;
3536		};
3537
3538		if(this.options.custom && this.options.custom.refreshContainers
3538) {
3539			this.options.custom.refreshContainers.call(this);
3540		} else {
3541			for (var i = this.containers.length - 1; i >= 0; i--){
3542				var p = this.containers[i].element.offset();
3543				this.containers[i].containerCache.left = p.left;
3544				this.containers[i].containerCache.top = p.top;
3545				this.containers[i].containerCache.width	= this.containers[i].element.outerWidth();
3546				this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
3547			};
3548		}
3549
3550		return this;
3551	},
3552
3553	_createPlaceholder: function(that) {
3554
3555		var self = that || this, o = self.options;
3556
3557		if(!o.placeholder || o.placeholder.constructor == String) {
3558			var className = o.placeholder;
3559			o.placeholder = {
3560				element: function() {
3561
3562					var el = $(document.createElement(self.currentItem[0].nodeName))
3563						.addClass(className || self.currentItem[0].className+" ui-sortable-placeholder")
3564						.removeClass("ui-sortable-helper")[0];
3565
3566					if(!className)
3567						el.style.visibility = "hidden";
3568
3569					return el;
3570				},
3571				update: function(container, p) {
3572
3573					// 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
3574					// 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
3575					if(className && !o.forcePlaceholderSize) return;
3576
3577					//If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item
3578					if(!p.height()) { p.height(self.currentItem.innerHeight() - parseInt(self.currentItem.css('paddingTop')||0, 10) - parseInt(self.currentItem.css('paddingBottom')||0, 10)); };
3579					if(!p.width()) { p.width(self.currentItem.innerWidth() - parseInt(self.currentItem.css('paddingLeft')||0, 10) - parseInt(self.currentItem.css('paddingRight')||0, 10)); };
3580				}
3581			};
3582		}
3583
3584		//Create the placeholder
3585		self.placeholder = $(o.placeholder.element.call(self.element, self.currentItem));
3586
3587		//Append it after the actual current item
3588		self.currentItem.after(self.placeholder);
3589
3590		//Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
3591		o.placeholder.update(self, self.placeholder);
3592
3593	},
3594
3595	_contactContainers: function(event) {
3596		
3597		// get innermost container that intersects with item 
3598		var innermostContainer = null, innermostIndex = null;		
3599		
3600		
3601		for (var i = this.containers.length - 1; i >= 0; i--){
3602
3603			// never consider a container that's located within the item itself 
3604			if($.ui.contains(this.currentItem[0], this.containers[i].element[0]))
3605				continue;
3606
3607			if(this._intersectsWith(this.containers[i].containerCache)) {
3608
3609				// if we've already found a container and it's more "inner" than this, then continue 
3610				if(innermostContainer && $.ui.contains(this.containers[i].element[0], innermostContainer.element[0]))
3611					continue;
3612
3613				innermostContainer = this.containers[i]; 
3614				innermostIndex = i;
3615					
3616			} else {
3617				// container doesn't intersect. trigger "out" event if necessary 
3618				if(this.containers[i].containerCache.over) {
3619					this.containers[i]._trigger("out", event, this._uiHash(this));
3620					this.containers[i].containerCache.over = 0;
3621				}
3622			}
3623
3624		}
3625		
3626		// if no intersecting containers found, return 
3627		if(!innermostContainer) return; 
3628
3629		// move the item into the container if it's not there already
3630		if(this.containers.length === 1) {
3631			this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
3632			this.containers[innermostIndex].containerCache.over = 1;
3633		} else if(this.currentContainer != this.containers[innermostIndex]) {
3634
3635			//When entering a new container, we will find the item with the least distance and append our item near it
3636			var dist = 10000; var itemWithLeastDistance = null; var base = this.positionAbs[this.containers[innermostIndex].floating ? 'left' : 'top'];
3637			for (var j = this.items.length - 1; j >= 0; j--) {
3638				if(!$.ui.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) continue;
3639				var cur = this.containers[innermostIndex].floating ? this.items[j].item.offset().left : this.items[j].item.offset().top;
3640				if(Math.abs(cur - base) < dist) {
3641					dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j];
3642					this.direction = (cur - base > 0) ? 'down' : 'up';
3643				}
3644			}
3645
3646			if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled
3647				return;
3648
3649			this.currentContainer = this.containers[innermostIndex];
3650			itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true);
3651			this._trigger("change", event, this._uiHash());
3652			this.containers[innermostIndex]._trigger("change", event, this._uiHash(this));
3653
3654			//Update the placeholder
3655			this.options.placeholder.update(this.currentContainer, this.placeholder);
3656
3657			this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
3658			this.containers[innermostIndex].containerCache.over = 1;
3659		} 
3660	
3661		
3662	},
3663
3664	_createHelper: function(event) {
3665
3666		var o = this.options;
3667		var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper == 'clone' ? this.currentItem.clone() : this.currentItem);
3668
3669		if(!helper.parents('body').length) //Add the helper to the DOM if that didn't happen already
3670			$(o.appendTo != 'parent' ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);
3671
3672		if(helper[0] == this.currentItem[0])
3673			this._storedCSS = { width: this.currentItem[0].style.width, height: this.currentItem[0].style.height, position: this.currentItem.css("position"), top: this.currentItem.css("top"), left
3673: this.currentItem.css("left") };
3674
3675		if(helper[0].style.width == '' || o.forceHelperSize) helper.width(this.currentItem.width());
3676		if(helper[0].style.height == '' || o.forceHelperSize) helper.height(this.currentItem.height());
3677
3678		return helper;
3679
3680	},
3681
3682	_adjustOffsetFromHelper: function(obj) {
3683		if (typeof obj == 'string') {
3684			obj = obj.split(' ');
3685		}
3686		if ($.isArray(obj)) {
3687			obj = {left: +obj[0], top: +obj[1] || 0};
3688		}
3689		if ('left' in obj) {
3690			this.offset.click.left = obj.left + this.margins.left;
3691		}
3692		if ('right' in obj) {
3693			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
3694		}
3695		if ('top' in obj) {
3696			this.offset.click.top = obj.top + this.margins.top;
3697		}
3698		if ('bottom' in obj) {
3699			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
3700		}
3701	},
3702
3703	_getParentOffset: function() {
3704
3705
3706		//Get the offsetParent and cache its position
3707		this.offsetParent = this.helper.offsetParent();
3708		var po = this.offsetParent.offset();
3709
3710		// This is a special case where we need to modify a offset calculated on start, since the following happened:
3711		// 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
3712		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
3713		//    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
3714		if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
3715			po.left += this.scrollParent.scrollLeft();
3716			po.top += this.scrollParent.scrollTop();
3717		}
3718
3719		if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
3720		|| (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
3721			po = { top: 0, left: 0 };
3722
3723		return {
3724			top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
3725			left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
3726		};
3727
3728	},
3729
3730	_getRelativeOffset: function() {
3731
3732		if(this.cssPosition == "relative") {
3733			var p = this.currentItem.position();
3734			return {
3735				top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
3736				left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
3737			};
3738		} else {
3739			return { top: 0, left: 0 };
3740		}
3741
3742	},
3743
3744	_cacheMargins: function() {
3745		this.margins = {
3746			left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),
3747			top: (parseInt(this.currentItem.css("marginTop"),10) || 0)
3748		};
3749	},
3750
3751	_cacheHelperProportions: function() {
3752		this.helperProportions = {
3753			width: this.helper.outerWidth(),
3754			height: this.helper.outerHeight()
3755		};
3756	},
3757
3758	_setContainment: function() {
3759
3760		var o = this.options;
3761		if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
3762		if(o.containment == 'document' || o.containment == 'window') this.containment = [
3763			0 - this.offset.relative.left - this.offset.parent.left,
3764			0 - this.offset.relative.top - this.offset.parent.top,
3765			$(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
3766			($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
3767		];
3768
3769		if(!(/^(document|window|parent)$/).test(o.containment)) {
3770			var ce = $(o.containment)[0];
3771			var co = $(o.containment).offset();
3772			var over = ($(ce).css("overflow") != 'hidden');
3773
3774			this.containment = [
3775				co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
3776				co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
3777				co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left,
3778				co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),
377810) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top
3779			];
3780		}
3781
3782	},
3783
3784	_convertPositionTo: function(d, pos) {
3785
3786		if(!pos) pos = this.position;
3787		var mod = d == "absolute" ? 1 : -1;
3788		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
3789
3790		return {
3791			top: (
3792				pos.top																	// The absolute mouse position
3793				+ this.offset.relative.top * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
3794				+ this.offset.parent.top * mod											// The offsetParent's offset without borders (offset + border)
3795				- ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
3796			),
3797			left: (
3798				pos.left																// The absolute mouse position
3799				+ this.offset.relative.left * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
3800				+ this.offset.parent.left * mod											// The offsetParent's offset without borders (offset + border)
3801				- ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
3802			)
3803		};
3804
3805	},
3806
3807	_generatePosition: function(event) {
3808
3809		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
3810
3811		// This is another very weird special case that only happens for relative elements:
3812		// 1. If the css position is relative
3813		// 2. and the scroll parent is the document or similar to the offset parent
3814		// we have to refresh the relative offset during the scroll so there are no jumps
3815		if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) {
3816			this.offset.relative = this._getRelativeOffset();
3817		}
3818
3819		var pageX = event.pageX;
3820		var pageY = event.pageY;
3821
3822		/*
3823		 * - Position constraining -
3824		 * Constrain the position to a mix of grid, containment.
3825		 */
3826
3827		if(this.originalPosition) { //If we are not dragging yet, we won't check for options
3828
3829			if(this.containment) {
3830				if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
3831				if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
3832				if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
3833				if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
3834			}
3835
3836			if(o.grid) {
3837				var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
3838				pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
3839
3840				var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
3841				pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
3842			}
3843
3844		}
3845
3846		return {
3847			top: (
3848				pageY																// The absolute mouse position
3849				- this.offset.click.top													// Click offset (relative to the element)
3850				- this.offset.relative.top												// Only for relative positioned nodes: Relative offset from element to offset parent
3851				- this.offset.parent.top												// The offsetParent's offset without borders (offset + border)
3852				+ ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
3853			),
3854			left: (
3855				pageX																// The absolute mouse position
3856				- this.offset.click.left												// Click offset (relative to the element)
3857				- this.offset.relative.left												// Only for relative positioned nodes: Relative offset from element to offset parent
3858				- this.offset.parent.left												// The offsetParent's offset without borders (offset + border)
3859				+ ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
3860			)
3861		};
3862
3863	},
3864
3865	_rearrange: function(event, i, a, hardRefresh) {
3866
3867		a ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction == 'down' ? i.item[0] : i.item[0].nextSibling));
3868
3869		//Various things done here to improve the performance:
3870		// 1. we create a setTimeout, that calls refreshPositions
3871		// 2. on the instance, we have a counter variable, that get's higher after every append
3872		// 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
3873		// 4. this lets only the last addition to the timeout stack through
3874		this.counter = this.counter ? ++this.counter : 1;
3875		var self = this, counter = this.counter;
3876
3877		window.setTimeout(function() {
3878			if(counter == self.counter) self.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
3879		},0);
3880
3881	},
3882
3883	_clear: function(event, noPropagation) {
3884
3885		this.reverting = false;
3886		// We delay all events that have to be triggered to after the point where the placeholder has been removed and
3887		// everything else normalized again
3888		var delayedTriggers = [], self = this;
3889
3890		// We first have to update the dom position of the actual currentItem
3891		// Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
3892		if(!this._noFinalSort && this.currentItem.parent().length) this.placeholder.before(this.currentItem);
3893		this._noFinalSort = null;
3894
3895		if(this.helper[0] == this.currentItem[0]) {
3896			for(var i in this._storedCSS) {
3897				if(this._storedCSS[i] == 'auto' || this._storedCSS[i] == 'static') this._storedCSS[i] = '';
3898			}
3899			this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
3900		} else {
3901			this.currentItem.show();
3902		}
3903
3904		if(this.fromOutside && !noPropagation) delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });
3905		if((this.fromOutside || this.domPosition.prev != this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent != this.currentItem.parent()[0]) && !noPropagation) delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed
3906
3907		// Check if the items Container has Changed and trigger appropriate
3908		// events.
3909		if (this !== this.currentContainer) {
3910			if(!noPropagation) {
3911				delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
3912				delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); };  }).call(this, this.currentContainer));
3913				delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this));  }; }).call(this, this.currentContainer));
3914			}
3915		}
3916
3917		//Post events to containers
3918		for (var i = this.containers.length - 1; i >= 0; i--){
3919			if(!noPropagation) delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
3920			if(this.containers[i].containerCache.over) {
3921				delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
3922				this.containers[i].containerCache.over = 0;
3923			}
3924		}
3925
3926		//Do what was originally in plugins
3927		if(this._storedCursor) $('body').css("cursor", this._storedCursor); //Reset cursor
3928		if(this._storedOpacity) this.helper.css("opacity", this._storedOpacity); //Reset opacity
3929		if(this._storedZIndex) this.helper.css("zIndex", this._storedZIndex == 'auto' ? '' : this._storedZIndex); //Reset z-index
3930
3931		this.dragging = false;
3932		if(this.cancelHelperRemoval) {
3933			if(!noPropagation) {
3934				this._trigger("beforeStop", event, this._uiHash());
3935				for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
3936				this._trigger("stop", event, this._uiHash());
3937			}
3938
3939			this.fromOutside = false;
3940			return false;
3941		}
3942
3943		if(!noPropagation) this._trigger("beforeStop", event, this._uiHash());
3944
3945		//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
3946		this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
3947
3948		if(this.helper[0] != this.currentItem[0]) this.helper.remove(); this.helper = null;
3949
3950		if(!noPropagation) {
3951			for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
3952			this._trigger("stop", event, this._uiHash());
3953		}
3954
3955		this.fromOutside = false;
3956		return true;
3957
3958	},
3959
3960	_trigger: function() {
3961		if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
3962			this.cancel();
3963		}
3964	},
3965
3966	_uiHash: function(inst) {
3967		var self = inst || this;
3968		return {
3969			helper: self.helper,
3970			placeholder: self.placeholder || $([]),
3971			position: self.position,
3972			originalPosition: self.originalPosition,
3973			offset: self.positionAbs,
3974			item: self.currentItem,
3975			sender: inst ? inst.element : null
3976		};
3977	}
3978
3979});
3980
3981$.extend($.ui.sortable, {
3982	version: "1.8.24"
3983});
3984
3985})(jQuery);
3986
3987;jQuery.effects || (function($, undefined) {
3988
3989$.effects = {};
3990
3991
3992
3993/******************************************************************************/
3994/****************************** COLOR ANIMATIONS ******************************/
3995/******************************************************************************/
3996
3997// override the animation for color styles
3998$.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor',
3999	'borderRightColor', 'borderTopColor', 'borderColor', 'color', 'outlineColor'],
4000function(i, attr) {
4001	$.fx.step[attr] = function(fx) {
4002		if (!fx.colorInit) {
4003			fx.start = getColor(fx.elem, attr);
4004			fx.end = getRGB(fx.end);
4005			fx.colorInit = true;
4006		}
4007
4008		fx.elem.style[attr] = 'rgb(' +
4009			Math.max(Math.min(parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0], 10), 255), 0) + ',' +
4010			Math.max(Math.min(parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1], 10), 255), 0) + ',' +
4011			Math.max(Math.min(parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2], 10), 255), 0) + ')';
4012	};
4013});
4014
4015// Color Conversion functions from highlightFade
4016// By Blair Mitchelmore
4017// http://jquery.offput.ca/highlightFade/
4018
4019// Parse strings looking for color tuples [255,255,255]
4020function getRGB(color) {
4021		var result;
4022
4023		// Check if we're already dealing with an array of colors
4024		if ( color && color.constructor == Array && color.length == 3 )
4025				return color;
4026
4027		// Look for rgb(num,num,num)
4028		if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color))
4029				return [parseInt(result[1],10), parseInt(result[2],10), parseInt(result[3],10)];
4030
4031		// Look for rgb(num%,num%,num%)
4032		if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color))
4033				return [parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55];
4034
4035		// Look for #a0b1c2
4036		if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color))
4037				return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)];
4038
4039		// Look for #fff
4040		if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color))
4041				return [parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)];
4042
4043		// Look for rgba(0, 0, 0, 0) == transparent in Safari 3
4044		if (result = /rgba\(0, 0, 0, 0\)/.exec(color))
4045				return colors['transparent'];
4046
4047		// Otherwise, we're most likely dealing with a named color
4048		return colors[$.trim(color).toLowerCase()];
4049}
4050
4051function getColor(elem, attr) {
4052		var color;
4053
4054		do {
4055				// jQuery <1.4.3 uses curCSS, in 1.4.3 - 1.7.2 curCSS = css, 1.8+ only has css
4056				color = ($.curCSS || $.css)(elem, attr);
4057
4058				// Keep going until we find an element that has color, or we hit the body
4059				if ( color != '' && color != 'transparent' || $.nodeName(elem, "body") )
4060						break;
4061
4062				attr = "backgroundColor";
4063		} while ( elem = elem.parentNode );
4064
4065		return getRGB(color);
4066};
4067
4068// Some named colors to work with
4069// From Interface by Stefan Petre
4070// http://interface.eyecon.ro/
4071
4072var colors = {
4073	aqua:[0,255,255],
4074	azure:[240,255,255],
4075	beige:[245,245,220],
4076	black:[0,0,0],
4077	blue:[0,0,255],
4078	brown:[165,42,42],
4079	cyan:[0,255,255],
4080	darkblue:[0,0,139],
4081	darkcyan:[0,139,139],
4082	darkgrey:[169,169,169],
4083	darkgreen:[0,100,0],
4084	darkkhaki:[189,183,107],
4085	darkmagenta:[139,0,139],
4086	darkolivegreen:[85,107,47],
4087	darkorange:[255,140,0],
4088	darkorchid:[153,50,204],
4089	darkred:[139,0,0],
4090	darksalmon:[233,150,122],
4091	darkviolet:[148,0,211],
4092	fuchsia:[255,0,255],
4093	gold:[255,215,0],
4094	green:[0,128,0],
4095	indigo:[75,0,130],
4096	khaki:[240,230,140],
4097	lightblue:[173,216,230],
4098	lightcyan:[224,255,255],
4099	lightgreen:[144,238,144],
4100	lightgrey:[211,211,211],
4101	lightpink:[255,182,193],
4102	lightyellow:[255,255,224],
4103	lime:[0,255,0],
4104	magenta:[255,0,255],
4105	maroon:[128,0,0],
4106	navy:[0,0,128],
4107	olive:[128,128,0],
4108	orange:[255,165,0],
4109	pink:[255,192,203],
4110	purple:[128,0,128],
4111	violet:[128,0,128],
4112	red:[255,0,0],
4113	silver:[192,192,192],
4114	white:[255,255,255],
4115	yellow:[255,255,0],
4116	transparent: [255,255,255]
4117};
4118
4119
4120
4121/******************************************************************************/
4122/****************************** CLASS ANIMATIONS ******************************/
4123/******************************************************************************/
4124
4125var classAnimationActions = ['add', 'remove', 'toggle'],
4126	shorthandStyles = {
4127		border: 1,
4128		borderBottom: 1,
4129		borderColor: 1,
4130		borderLeft: 1,
4131		borderRight: 1,
4132		borderTop: 1,
4133		borderWidth: 1,
4134		margin: 1,
4135		padding: 1
4136	};
4137
4138function getElementStyles() {
4139	var style = document.defaultView
4140			? document.defaultView.getComputedStyle(this, null)
4141			: this.currentStyle,
4142		newStyle = {},
4143		key,
4144		camelCase;
4145
4146	// webkit enumerates style porperties
4147	if (style && style.length && style[0] && style[style[0]]) {
4148		var len = style.length;
4149		while (len--) {
4150			key = style[len];
4151			if (typeof style[key] == 'string') {
4152				camelCase = key.replace(/\-(\w)/g, function(all, letter){
4153					return letter.toUpperCase();
4154				});
4155				newStyle[camelCase] = style[key];
4156			}
4157		}
4158	} else {
4159		for (key in style) {
4160			if (typeof style[key] === 'string') {
4161				newStyle[key] = style[key];
4162			}
4163		}
4164	}
4165	
4166	return newStyle;
4167}
4168
4169function filterStyles(styles) {
4170	var name, value;
4171	for (name in styles) {
4172		value = styles[name];
4173		if (
4174			// ignore null and undefined values
4175			value == null ||
4176			// ignore functions (when does this occur?)
4177			$.isFunction(value) ||
4178			// shorthand styles that need to be expanded
4179			name in shorthandStyles ||
4180			// ignore scrollbars (break in IE)
4181			(/scrollbar/).test(name) ||
4182
4183			// only colors or values that can be converted to numbers
4184			(!(/color/i).test(name) && isNaN(parseFloat(value)))
4185		) {
4186			delete styles[name];
4187		}
4188	}
4189	
4190	return styles;
4191}
4192
4193function styleDifference(oldStyle, newStyle) {
4194	var diff = { _: 0 }, // http://dev.jquery.com/ticket/5459
4195		name;
4196
4197	for (name in newStyle) {
4198		if (oldStyle[name] != newStyle[name]) {
4199			diff[name] = newStyle[name];
4200		}
4201	}
4202
4203	return diff;
4204}
4205
4206$.effects.animateClass = function(value, duration, easing, callback) {
4207	if ($.isFunction(easing)) {
4208		callback = easing;
4209		easing = null;
4210	}
4211
4212	return this.queue(function() {
4213		var that = $(this),
4214			originalStyleAttr = that.attr('style') || ' ',
4215			originalStyle = filterStyles(getElementStyles.call(this)),
4216			newStyle,
4217			className = that.attr('class') || "";
4218
4219		$.each(classAnimationActions, function(i, action) {
4220			if (value[action]) {
4221				that[action + 'Class'](value[action]);
4222			}
4223		});
4224		newStyle = filterStyles(getElementStyles.call(this));
4225		that.attr('class', className);
4226
4227		that.animate(styleDifference(originalStyle, newStyle), {
4228			queue: false,
4229			duration: duration,
4230			easing: easing,
4231			complete: function() {
4232				$.each(classAnimationActions, function(i, action) {
4233					if (value[action]) { that[action + 'Class'](value[action]); }
4234				});
4235				// work around bug in IE by clearing the cssText before setting it
4236				if (typeof that.attr('style') == 'object') {
4237					that.attr('style').cssText = '';
4238					that.attr('style').cssText = originalStyleAttr;
4239				} else {
4240					that.attr('style', originalStyleAttr);
4241				}
4242				if (callback) { callback.apply(this, arguments); }
4243				$.dequeue( this );
4244			}
4245		});
4246	});
4247};
4248
4249$.fn.extend({
4250	_addClass: $.fn.addClass,
4251	addClass: function(classNames, speed, easing, callback) {
4252		return speed ? $.effects.animateClass.apply(this, [{ add: classNames },speed,easing,callback]) : this._addClass(classNames);
4253	},
4254
4255	_removeClass: $.fn.removeClass,
4256	removeClass: function(classNames,speed,easing,callback) {
4257		return speed ? $.effects.animateClass.apply(this, [{ remove: classNames },speed,easing,callback]) : this._removeClass(classNames);
4258	},
4259
4260	_toggleClass: $.fn.toggleClass,
4261	toggleClass: function(classNames, force, speed, easing, callback) {
4262		if ( typeof force == "boolean" || force === undefined ) {
4263			if ( !speed ) {
4264				// without speed parameter;
4265				return this._toggleClass(classNames, force);
4266			} else {
4267				return $.effects.animateClass.apply(this, [(force?{add:classNames}:{remove:classNames}),speed,easing,callback]);
4268			}
4269		} else {
4270			// without switch parameter;
4271			return $.effects.animateClass.apply(this, [{ toggle: classNames },force,speed,easing]);
4272		}
4273	},
4274
4275	switchClass: function(remove,add,speed,easing,callback) {
4276		return $.effects.animateClass.apply(this, [{ add: add, remove: remove },speed,easing,callback]);
4277	}
4278});
4279
4280
4281
4282/******************************************************************************/
4283/*********************************** EFFECTS **********************************/
4284/******************************************************************************/
4285
4286$.extend($.effects, {
4287	version: "1.8.24",
4288
4289	// Saves a set of properties in a data storage
4290	save: function(element, set) {
4291		for(var i=0; i < set.length; i++) {
4292			if(set[i] !== null) element.data("ec.storage."+set[i], element[0].style[set[i]]);
4293		}
4294	},
4295
4296	// Restores a set of previously saved properties from a data storage
4297	restore: function(element, set) {
4298		for(var i=0; i < set.length; i++) {
4299			if(set[i] !== null) element.css(set[i], element.data("ec.storage."+set[i]));
4300		}
4301	},
4302
4303	setMode: function(el, mode) {
4304		if (mode == 'toggle') mode = el.is(':hidden') ? 'show' : 'hide'; // Set for toggle
4305		return mode;
4306	},
4307
4308	getBaseline: function(origin, original) { // Translates a [top,left] array into a baseline value
4309		// this should be a little more flexible in the future to handle a string & hash
4310		var y, x;
4311		switch (origin[0]) {
4312			case 'top': y = 0; break;
4313			case 'middle': y = 0.5; break;
4314			case 'bottom': y = 1; break;
4315			default: y = origin[0] / original.height;
4316		};
4317		switch (origin[1]) {
4318			case 'left': x = 0; break;
4319			case 'center': x = 0.5; break;
4320			case 'right': x = 1; break;
4321			default: x = origin[1] / original.width;
4322		};
4323		return {x: x, y: y};
4324	},
4325
4326	// Wraps the element around a wrapper that copies position properties
4327	createWrapper: function(element) {
4328
4329		// if the element is already wrapped, return it
4330		if (element.parent().is('.ui-effects-wrapper')) {
4331			return element.parent();
4332		}
4333
4334		// wrap the element
4335		var props = {
4336				width: element.outerWidth(true),
4337				height: element.outerHeight(true),
4338				'float': element.css('float')
4339			},
4340			wrapper = $('<div></div>')
4341				.addClass('ui-effects-wrapper')
4342				.css({
4343					fontSize: '100%',
4344					background: 'transparent',
4345					border: 'none',
4346					margin: 0,
4347					padding: 0
4348				}),
4349			active = document.activeElement;
4350
4351		// support: Firefox
4352		// Firefox incorrectly exposes anonymous content
4353		// https://bugzilla.mozilla.org/show_bug.cgi?id=561664
4354		try {
4355			active.id;
4356		} catch( e ) {
4357			active = document.body;
4358		}
4359
4360		element.wrap( wrapper );
4361
4362		// Fixes #7595 - Elements lose focus when wrapped.
4363		if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
4364			$( active ).focus();
4365		}
4366		
4367		wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually loose the reference to the wrapped element
4368
4369		// transfer positioning properties to the wrapper
4370		if (element.css('position') == 'static') {
4371			wrapper.css({ position: 'relative' });
4372			element.css({ position: 'relative' });
4373		} else {
4374			$.extend(props, {
4375				position: element.css('position'),
4376				zIndex: element.css('z-index')
4377			});
4378			$.each(['top', 'left', 'bottom', 'right'], function(i, pos) {
4379				props[pos] = element.css(pos);
4380				if (isNaN(parseInt(props[pos], 10))) {
4381					props[pos] = 'auto';
4382				}
4383			});
4384			element.css({position: 'relative', top: 0, left: 0, right: 'auto', bottom: 'auto' });
4385		}
4386
4387		return wrapper.css(props).show();
4388	},
4389
4390	removeWrapper: function(element) {
4391		var parent,
4392			active = document.activeElement;
4393		
4394		if (element.parent().is('.ui-effects-wrapper')) {
4395			parent = element.parent().replaceWith(element);
4396			// Fixes #7595 - Elements lose focus when wrapped.
4397			if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
4398				$( active ).focus();
4399			}
4400			return parent;
4401		}
4402			
4403		return element;
4404	},
4405
4406	setTransition: function(element, list, factor, value) {
4407		value = value || {};
4408		$.each(list, function(i, x){
4409			var unit = element.cssUnit(x);
4410			if (unit[0] > 0) value[x] = unit[0] * factor + unit[1];
4411		});
4412		return value;
4413	}
4414});
4415
4416
4417function _normalizeArguments(effect, options, speed, callback) {
4418	// shift params for method overloading
4419	if (typeof effect == 'object') {
4420		callback = options;
4421		speed = null;
4422		options = effect;
4423		effect = options.effect;
4424	}
4425	if ($.isFunction(options)) {
4426		callback = options;
4427		speed = null;
4428		options = {};
4429	}
4430        if (typeof options == 'number' || $.fx.speeds[options]) {
4431		callback = speed;
4432		speed = options;
4433		options = {};
4434	}
4435	if ($.isFunction(speed)) {
4436		callback = speed;
4437		speed = null;
4438	}
4439
4440	options = options || {};
4441
4442	speed = speed || options.duration;
4443	speed = $.fx.off ? 0 : typeof speed == 'number'
4444		? speed : speed in $.fx.speeds ? $.fx.speeds[speed] : $.fx.speeds._default;
4445
4446	callback = callback || options.complete;
4447
4448	return [effect, options, speed, callback];
4449}
4450
4451function standardSpeed( speed ) {
4452	// valid standard speeds
4453	if ( !speed || typeof speed === "number" || $.fx.speeds[ speed ] ) {
4454		return true;
4455	}
4456	
4457	// invalid strings - treat as "normal" speed
4458	if ( typeof speed === "string" && !$.effects[ speed ] ) {
4459		return true;
4460	}
4461	
4462	return false;
4463}
4464
4465$.fn.extend({
4466	effect: function(effect, options, speed, callback) {
4467		var args = _normalizeArguments.apply(this, arguments),
4468			// TODO: make effects take actual parameters instead of a hash
4469			args2 = {
4470				options: args[1],
4471				duration: args[2],
4472				callback: args[3]
4473			},
4474			mode = args2.options.mode,
4475			effectMethod = $.effects[effect];
4476		
4477		if ( $.fx.off || !effectMethod ) {
4478			// delegate to the original method (e.g., .show()) if possible
4479			if ( mode ) {
4480				return this[ mode ]( args2.duration, args2.callback );
4481			} else {
4482				return this.each(function() {
4483					if ( args2.callback ) {
4484						args2.callback.call( this );
4485					}
4486				});
4487			}
4488		}
4489		
4490		return effectMethod.call(this, args2);
4491	},
4492
4493	_show: $.fn.show,
4494	show: function(speed) {
4495		if ( standardSpeed( speed ) ) {
4496			return this._show.apply(this, arguments);
4497		} else {
4498			var args = _normalizeArguments.apply(this, arguments);
4499			args[1].mode = 'show';
4500			return this.effect.apply(this, args);
4501		}
4502	},
4503
4504	_hide: $.fn.hide,
4505	hide: function(speed) {
4506		if ( standardSpeed( speed ) ) {
4507			return this._hide.apply(this, arguments);
4508		} else {
4509			var args = _normalizeArguments.apply(this, arguments);
4510			args[1].mode = 'hide';
4511			return this.effect.apply(this, args);
4512		}
4513	},
4514
4515	// jQuery core overloads toggle and creates _toggle
4516	__toggle: $.fn.toggle,
4517	toggle: function(speed) {
4518		if ( standardSpeed( speed ) || typeof speed === "boolean" || $.isFunction( speed ) ) {
4519			return this.__toggle.apply(this, arguments);
4520		} else {
4521			var args = _normalizeArguments.apply(this, arguments);
4522			args[1].mode = 'toggle';
4523			return this.effect.apply(this, args);
4524		}
4525	},
4526
4527	// helper functions
4528	cssUnit: function(key) {
4529		var style = this.css(key), val = [];
4530		$.each( ['em','px','%','pt'], function(i, unit){
4531			if(style.indexOf(unit) > 0)
4532				val = [parseFloat(style), unit];
4533		});
4534		return val;
4535	}
4536});
4537
4538
4539
4540/******************************************************************************/
4541/*********************************** EASING ***********************************/
4542/******************************************************************************/
4543
4544// based on easing equations from Robert Penner (http://www.robertpenner.com/easing)
4545
4546var baseEasings = {};
4547
4548$.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) {
4549	baseEasings[ name ] = function( p ) {
4550		return Math.pow( p, i + 2 );
4551	};
4552});
4553
4554$.extend( baseEasings, {
4555	Sine: function ( p ) {
4556		return 1 - Math.cos( p * Math.PI / 2 );
4557	},
4558	Circ: function ( p ) {
4559		return 1 - Math.sqrt( 1 - p * p );
4560	},
4561	Elastic: function( p ) {
4562		return p === 0 || p === 1 ? p :
4563			-Math.pow( 2, 8 * (p - 1) ) * Math.sin( ( (p - 1) * 80 - 7.5 ) * Math.PI / 15 );
4564	},
4565	Back: function( p ) {
4566		return p * p * ( 3 * p - 2 );
4567	},
4568	Bounce: function ( p ) {
4569		var pow2,
4570			bounce = 4;
4571
4572		while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {}
4573		return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 );
4574	}
4575});
4576
4577$.each( baseEasings, function( name, easeIn ) {
4578	$.easing[ "easeIn" + name ] = easeIn;
4579	$.easing[ "easeOut" + name ] = function( p ) {
4580		return 1 - easeIn( 1 - p );
4581	};
4582	$.easing[ "easeInOut" + name ] = function( p ) {
4583		return p < .5 ?
4584			easeIn( p * 2 ) / 2 :
4585			easeIn( p * -2 + 2 ) / -2 + 1;
4586	};
4587});
4588
4589})(jQuery);
4590
4591(function( $, undefined ) {
4592
4593$.effects.blind = function(o) {
4594
4595	return this.queue(function() {
4596
4597		// Create element
4598		var el = $(this), props = ['position','top','bottom','left','right'];
4599
4600		// Set options
4601		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
4602		var direction = o.options.direction || 'vertical'; // Default direction
4603
4604		// Adjust
4605		$.effects.save(el, props); el.show(); // Save & Show
4606		var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
4607		var ref = (direction == 'vertical') ? 'height' : 'width';
4608		var distance = (direction == 'vertical') ? wrapper.height() : wrapper.width();
4609		if(mode == 'show') wrapper.css(ref, 0); // Shift
4610
4611		// Animation
4612		var animation = {};
4613		animation[ref] = mode == 'show' ? distance : 0;
4614
4615		// Animate
4616		wrapper.animate(animation, o.duration, o.options.easing, function() {
4617			if(mode == 'hide') el.hide(); // Hide
4618			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
4619			if(o.callback) o.callback.apply(el[0], arguments); // Callback
4620			el.dequeue();
4621		});
4622
4623	});
4624
4625};
4626
4627})(jQuery);
4628
4629(function( $, undefined ) {
4630
4631$.effects.bounce = function(o) {
4632
4633	return this.queue(function() {
4634
4635		// Create element
4636		var el = $(this), props = ['position','top','bottom','left','right'];
4637
4638		// Set options
4639		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
4640		var direction = o.options.direction || 'up'; // Default direction
4641		var distance = o.options.distance || 20; // Default distance
4642		var times = o.options.times || 5; // Default # of times
4643		var speed = o.duration || 250; // Default speed per bounce
4644		if (/show|hide/.test(mode)) props.push('opacity'); // Avoid touching opacity to prevent clearType and PNG issues in IE
4645
4646		// Adjust
4647		$.effects.save(el, props); el.show(); // Save & Show
4648		$.effects.createWrapper(el); // Create Wrapper
4649		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
4650		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
4651		var distance = o.options.distance || (ref == 'top' ? el.outerHeight(true) / 3 : el.outerWidth(true) / 3);
4652		if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift
4653		if (mode == 'hide') distance = distance / (times * 2);
4654		if (mode != 'hide') times--;
4655
4656		// Animate
4657		if (mode == 'show') { // Show Bounce
4658			var animation = {opacity: 1};
4659			animation[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
4660			el.animate(animation, speed / 2, o.options.easing);
4661			distance = distance / 2;
4662			times--;
4663		};
4664		for (var i = 0; i < times; i++) { // Bounces
4665			var animation1 = {}, animation2 = {};
4666			animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
4667			animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
4668			el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing);
4669			distance = (mode == 'hide') ? distance * 2 : distance / 2;
4670		};
4671		if (mode == 'hide') { // Last Bounce
4672			var animation = {opacity: 0};
4673			animation[ref] = (motion == 'pos' ? '-=' : '+=')  + distance;
4674			el.animate(animation, speed / 2, o.options.easing, function(){
4675				el.hide(); // Hide
4676				$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
4677				if(o.callback) o.callback.apply(this, arguments); // Callback
4678			});
4679		} else {
4680			var animation1 = {}, animation2 = {};
4681			animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
4682			animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
4683			el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing, function(){
4684				$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
4685				if(o.callback) o.callback.apply(this, arguments); // Callback
4686			});
4687		};
4688		el.queue('fx', function() { el.dequeue(); });
4689		el.dequeue();
4690	});
4691
4692};
4693
4694})(jQuery);
4695
4696(function( $, undefined ) {
4697
4698$.effects.clip = function(o) {
4699
4700	return this.queue(function() {
4701
4702		// Create element
4703		var el = $(this), props = ['position','top','bottom','left','right','height','width'];
4704
4705		// Set options
4706		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
4707		var direction = o.options.direction || 'vertical'; // Default direction
4708
4709		// Adjust
4710		$.effects.save(el, props); el.show(); // Save & Show
4711		var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
4712		var animate = el[0].tagName == 'IMG' ? wrapper : el;
4713		var ref = {
4714			size: (direction == 'vertical') ? 'height' : 'width',
4715			position: (direction == 'vertical') ? 'top' : 'left'
4716		};
4717		var distance = (direction == 'vertical') ? animate.height() : animate.width();
4718		if(mode == 'show') { animate.css(ref.size, 0); animate.css(ref.position, distance / 2); } // Shift
4719
4720		// Animation
4721		var animation = {};
4722		animation[ref.size] = mode == 'show' ? distance : 0;
4723		animation[ref.position] = mode == 'show' ? 0 : distance / 2;
4724
4725		// Animate
4726		animate.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
4727			if(mode == 'hide') el.hide(); // Hide
4728			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
4729			if(o.callback) o.callback.apply(el[0], arguments); // Callback
4730			el.dequeue();
4731		}});
4732
4733	});
4734
4735};
4736
4737})(jQuery);
4738
4739(function( $, undefined ) {
4740
4741$.effects.drop = function(o) {
4742
4743	return this.queue(function() {
4744
4745		// Create element
4746		var el = $(this), props = ['position','top','bottom','left','right','opacity'];
4747
4748		// Set options
4749		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
4750		var direction = o.options.direction || 'left'; // Default Direction
4751
4752		// Adjust
4753		$.effects.save(el, props); el.show(); // Save & Show
4754		$.effects.createWrapper(el); // Create Wrapper
4755		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
4756		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
4757		var distance = o.options.distance || (ref == 'top' ? el.outerHeight( true ) / 2 : el.outerWidth( true ) / 2);
4758		if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift
4759
4760		// Animation
4761		var animation = {opacity: mode == 'show' ? 1 : 0};
4762		animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
4763
4764		// Animate
4765		el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
4766			if(mode == 'hide') el.hide(); // Hide
4767			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
4768			if(o.callback) o.callback.apply(this, arguments); // Callback
4769			el.dequeue();
4770		}});
4771
4772	});
4773
4774};
4775
4776})(jQuery);
4777
4778(function( $, undefined ) {
4779
4780$.effects.explode = function(o) {
4781
4782	return this.queue(function() {
4783
4784	var rows = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;
4785	var cells = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;
4786
4787	o.options.mode = o.options.mode == 'toggle' ? ($(this).is(':visible') ? 'hide' : 'show') : o.options.mode;
4788	var el = $(this).show().css('visibility', 'hidden');
4789	var offset = el.offset();
4790
4791	//Substract the margins - not fixing the problem yet.
4792	offset.top -= parseInt(el.css("marginTop"),10) || 0;
4793	offset.left -= parseInt(el.css("marginLeft"),10) || 0;
4794
4795	var width = el.outerWidth(true);
4796	var height = el.outerHeight(true);
4797
4798	for(var i=0;i<rows;i++) { // =
4799		for(var j=0;j<cells;j++) { // ||
4800			el
4801				.clone()
4802				.appendTo('body')
4803				.wrap('<div></div>')
4804				.css({
4805					position: 'absolute',
4806					visibility: 'visible',
4807					left: -j*(width/cells),
4808					top: -i*(height/rows)
4809				})
4810				.parent()
4811				.addClass('ui-effects-explode')
4812				.css({
4813					position: 'absolute',
4814					overflow: 'hidden',
4815					width: width/cells,
4816					height: height/rows,
4817					left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? (j-Math.floor(cells/2))*(width/cells) : 0),
4818					top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? (i-Math.floor(rows/2))*(height/rows) : 0),
4819					opacity: o.options.mode == 'show' ? 0 : 1
4820				}).animate({
4821					left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? 0 : (j-Math.floor(cells/2))*(width/cells)),
4822					top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? 0 : (i-Math.floor(rows/2))*(height/rows)),
4823					opacity: o.options.mode == 'show' ? 1 : 0
4824				}, o.duration || 500);
4825		}
4826	}
4827
4828	// Set a timeout, to call the callback approx. when the other animations have finished
4829	setTimeout(function() {
4830
4831		o.options.mode == 'show' ? el.css({ visibility: 'visible' }) : el.css({ visibility: 'visible' }).hide();
4832				if(o.callback) o.callback.apply(el[0]); // Callback
4833				el.dequeue();
4834
4835				$('div.ui-effects-explode').remove();
4836
4837	}, o.duration || 500);
4838
4839
4840	});
4841
4842};
4843
4844})(jQuery);
4845
4846(function( $, undefined ) {
4847
4848$.effects.fade = function(o) {
4849	return this.queue(function() {
4850		var elem = $(this),
4851			mode = $.effects.setMode(elem, o.options.mode || 'hide');
4852
4853		elem.animate({ opacity: mode }, {
4854			queue: false,
4855			duration: o.duration,
4856			easing: o.options.easing,
4857			complete: function() {
4858				(o.callback && o.callback.apply(this, arguments));
4859				elem.dequeue();
4860			}
4861		});
4862	});
4863};
4864
4865})(jQuery);
4866
4867(function( $, undefined ) {
4868
4869$.effects.fold = function(o) {
4870
4871	return this.queue(function() {
4872
4873		// Create element
4874		var el = $(this), props = ['position','top','bottom','left','right'];
4875
4876		// Set options
4877		var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
4878		var size = o.options.size || 15; // Default fold size
4879		var horizFirst = !(!o.options.horizFirst); // Ensure a boolean value
4880		var duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2;
4881
4882		// Adjust
4883		$.effects.save(el, props); el.show(); // Save & Show
4884		var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
4885		var widthFirst = ((mode == 'show') != horizFirst);
4886		var ref = widthFirst ? ['width', 'height'] : ['height', 'width'];
4887		var distance = widthFirst ? [wrapper.width(), wrapper.height()] : [wrapper.height(), wrapper.width()];
4888		var percent = /([0-9]+)%/.exec(size);
4889		if(percent) size = parseInt(percent[1],10) / 100 * distance[mode == 'hide' ? 0 : 1];
4890		if(mode == 'show') wrapper.css(horizFirst ? {height: 0, width: size} : {height: size, width: 0}); // Shift
4891
4892		// Animation
4893		var animation1 = {}, animation2 = {};
4894		animation1[ref[0]] = mode == 'show' ? distance[0] : size;
4895		animation2[ref[1]] = mode == 'show' ? distance[1] : 0;
4896
4897		// Animate
4898		wrapper.animate(animation1, duration, o.options.easing)
4899		.animate(animation2, duration, o.options.easing, function() {
4900			if(mode == 'hide') el.hide(); // Hide
4901			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
4902			if(o.callback) o.callback.apply(el[0], arguments); // Callback
4903			el.dequeue();
4904		});
4905
4906	});
4907
4908};
4909
4910})(jQuery);
4911
4912(function( $, undefined ) {
4913
4914$.effects.highlight = function(o) {
4915	return this.queue(function() {
4916		var elem = $(this),
4917			props = ['backgroundImage', 'backgroundColor', 'opacity'],
4918			mode = $.effects.setMode(elem, o.options.mode || 'show'),
4919			animation = {
4920				backgroundColor: elem.css('backgroundColor')
4921			};
4922
4923		if (mode == 'hide') {
4924			animation.opacity = 0;
4925		}
4926
4927		$.effects.save(elem, props);
4928		elem
4929			.show()
4930			.css({
4931				backgroundImage: 'none',
4932				backgroundColor: o.options.color || '#ffff99'
4933			})
4934			.animate(animation, {
4935				queue: false,
4936				duration: o.duration,
4937				easing: o.options.easing,
4938				complete: function() {
4939					(mode == 'hide' && elem.hide());
4940					$.effects.restore(elem, props);
4941					(mode == 'show' && !$.support.opacity && this.style.removeAttribute('filter'));
4942					(o.callback && o.callback.apply(this, arguments));
4943					elem.dequeue();
4944				}
4945			});
4946	});
4947};
4948
4949})(jQuery);
4950
4951(function( $, undefined ) {
4952
4953$.effects.pulsate = function(o) {
4954	return this.queue(function() {
4955		var elem = $(this),
4956			mode = $.effects.setMode(elem, o.options.mode || 'show'),
4957			times = ((o.options.times || 5) * 2) - 1,
4958			duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2,
4959			isVisible = elem.is(':visible'),
4960			animateTo = 0;
4961
4962		if (!isVisible) {
4963			elem.css('opacity', 0).show();
4964			animateTo = 1;
4965		}
4966
4967		if ((mode == 'hide' && isVisible) || (mode == 'show' && !isVisible)) {
4968			times--;
4969		}
4970
4971		for (var i = 0; i < times; i++) {
4972			elem.animate({ opacity: animateTo }, duration, o.options.easing);
4973			animateTo = (animateTo + 1) % 2;
4974		}
4975
4976		elem.animate({ opacity: animateTo }, duration, o.options.easing, function() {
4977			if (animateTo == 0) {
4978				elem.hide();
4979			}
4980			(o.callback && o.callback.apply(this, arguments));
4981		});
4982
4983		elem
4984			.queue('fx', function() { elem.dequeue(); })
4985			.dequeue();
4986	});
4987};
4988
4989})(jQuery);
4990
4991(function( $, undefined ) {
4992
4993$.effects.puff = function(o) {
4994	return this.queue(function() {
4995		var elem = $(this),
4996			mode = $.effects.setMode(elem, o.options.mode || 'hide'),
4997			percent = parseInt(o.options.percent, 10) || 150,
4998			factor = percent / 100,
4999			original = { height: elem.height(), width: elem.width() };
5000
5001		$.extend(o.options, {
5002			fade: true,
5003			mode: mode,
5004			percent: mode == 'hide' ? percent : 100,
5005			from: mode == 'hide'
5006				? original
5007				: {
5008					height: original.height * factor,
5009					width: original.width * factor
5010				}
5011		});
5012
5013		elem.effect('scale', o.options, o.duration, o.callback);
5014		elem.dequeue();
5015	});
5016};
5017
5018$.effects.scale = function(o) {
5019
5020	return this.queue(function() {
5021
5022		// Create element
5023		var el = $(this);
5024
5025		// Set options
5026		var options = $.extend(true, {}, o.options);
5027		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
5028		var percent = parseInt(o.options.percent,10) || (parseInt(o.options.percent,10) == 0 ? 0 : (mode == 'hide' ? 0 : 100)); // Set default scaling percent
5029		var direction = o.options.direction || 'both'; // Set default axis
5030		var origin = o.options.origin; // The origin of the scaling
5031		if (mode != 'effect') { // Set default origin and restore for show/hide
5032			options.origin = origin || ['middle','center'];
5033			options.restore = true;
5034		}
5035		var original = {height: el.height(), width: el.width()}; // Save original
5036		el.from = o.options.from || (mode == 'show' ? {height: 0, width: 0} : original); // Default from state
5037
5038		// Adjust
5039		var factor = { // Set scaling factor
5040			y: direction != 'horizontal' ? (percent / 100) : 1,
5041			x: direction != 'vertical' ? (percent / 100) : 1
5042		};
5043		el.to = {height: original.height * factor.y, width: original.width * factor.x}; // Set to state
5044
5045		if (o.options.fade) { // Fade option to support puff
5046			if (mode == 'show') {el.from.opacity = 0; el.to.opacity = 1;};
5047			if (mode == 'hide') {el.from.opacity = 1; el.to.opacity = 0;};
5048		};
5049
5050		// Animation
5051		options.from = el.from; options.to = el.to; options.mode = mode;
5052
5053		// Animate
5054		el.effect('size', options, o.duration, o.callback);
5055		el.dequeue();
5056	});
5057
5058};
5059
5060$.effects.size = function(o) {
5061
5062	return this.queue(function() {
5063
5064		// Create element
5065		var el = $(this), props = ['position','top','bottom','left','right','width','height','overflow','opacity'];
5066		var props1 = ['position','top','bottom','left','right','overflow','opacity']; // Always restore
5067		var props2 = ['width','height','overflow']; // Copy for children
5068		var cProps = ['fontSize'];
5069		var vProps = ['borderTopWidth', 'borderBottomWidth', 'paddingTop', 'paddingBottom'];
5070		var hProps = ['borderLeftWidth', 'borderRightWidth', 'paddingLeft', 'paddingRight'];
5071
5072		// Set options
5073		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
5074		var restore = o.options.restore || false; // Default restore
5075		var scale = o.options.scale || 'both'; // Default scale mode
5076		var origin = o.options.origin; // The origin of the sizing
5077		var original = {height: el.height(), width: el.width()}; // Save original
5078		el.from = o.options.from || original; // Default from state
5079		el.to = o.options.to || original; // Default to state
5080		// Adjust
5081		if (origin) { // Calculate baseline shifts
5082			var baseline = $.effects.getBaseline(origin, original);
5083			el.from.top = (original.height - el.from.height) * baseline.y;
5084			el.from.left = (original.width - el.from.width) * baseline.x;
5085			el.to.top = (original.height - el.to.height) * baseline.y;
5086			el.to.left = (original.width - el.to.width) * baseline.x;
5087		};
5088		var factor = { // Set scaling factor
5089			from: {y: el.from.height / original.height, x: el.from.width / original.width},
5090			to: {y: el.to.height / original.height, x: el.to.width / original.width}
5091		};
5092		if (scale == 'box' || scale == 'both') { // Scale the css box
5093			if (factor.from.y != factor.to.y) { // Vertical props scaling
5094				props = props.concat(vProps);
5095				el.from = $.effects.setTransition(el, vProps, factor.from.y, el.from);
5096				el.to = $.effects.setTransition(el, vProps, factor.to.y, el.to);
5097			};
5098			if (factor.from.x != factor.to.x) { // Horizontal props scaling
5099				props = props.concat(hProps);
5100				el.from = $.effects.setTransition(el, hProps, factor.from.x, el.from);
5101				el.to = $.effects.setTransition(el, hProps, factor.to.x, el.to);
5102			};
5103		};
5104		if (scale == 'content' || scale == 'both') { // Scale the content
5105			if (factor.from.y != factor.to.y) { // Vertical props scaling
5106				props = props.concat(cProps);
5107				el.from = $.effects.setTransition(el, cProps, factor.from.y, el.from);
5108				el.to = $.effects.setTransition(el, cProps, factor.to.y, el.to);
5109			};
5110		};
5111		$.effects.save(el, restore ? props : props1); el.show(); // Save & Show
5112		$.effects.createWrapper(el); // Create Wrapper
5113		el.css('overflow','hidden').css(el.from); // Shift
5114
5115		// Animate
5116		if (scale == 'content' || scale == 'both') { // Scale the children
5117			vProps = vProps.concat(['marginTop','marginBottom']).concat(cProps); // Add margins/font-size
5118			hProps = hProps.concat(['marginLeft','marginRight']); // Add margins
5119			props2 = props.concat(vProps).concat(hProps); // Concat
5120			el.find("*[width]").each(function(){
5121				var child = $(this);
5122				if (restore) $.effects.save(child, props2);
5123				var c_original = {height: child.height(), width: child.width()}; // Save original
5124				child.from = {height: c_original.height * factor.from.y, width: c_original.width * factor.from.x};
5125				child.to = {height: c_original.height * factor.to.y, width: c_original.width * factor.to.x};
5126				if (factor.from.y != factor.to.y) { // Vertical props scaling
5127					child.from = $.effects.setTransition(child, vProps, factor.from.y, child.from);
5128					child.to = $.effects.setTransition(child, vProps, factor.to.y, child.to);
5129				};
5130				if (factor.from.x != factor.to.x) { // Horizontal props scaling
5131					child.from = $.effects.setTransition(child, hProps, factor.from.x, child.from);
5132					child.to = $.effects.setTransition(child, hProps, factor.to.x, child.to);
5133				};
5134				child.css(child.from); // Shift children
5135				child.animate(child.to, o.duration, o.options.easing, function(){
5136					if (restore) $.effects.restore(child, props2); // Restore children
5137				}); // Animate children
5138			});
5139		};
5140
5141		// Animate
5142		el.animate(el.to, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
5143			if (el.to.opacity === 0) {
5144				el.css('opacity', el.from.opacity);
5145			}
5146			if(mode == 'hide') el.hide(); // Hide
5147			$.effects.restore(el, restore ? props : props1); $.effects.removeWrapper(el); // Restore
5148			if(o.callback) o.callback.apply(this, arguments); // Callback
5149			el.dequeue();
5150		}});
5151
5152	});
5153
5154};
5155
5156})(jQuery);
5157
5158(function( $, undefined ) {
5159
5160$.effects.shake = function(o) {
5161
5162	return this.queue(function() {
5163
5164		// Create element
5165		var el = $(this), props = ['position','top','bottom','left','right'];
5166
5167		// Set options
5168		var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
5169		var direction = o.options.direction || 'left'; // Default direction
5170		var distance = o.options.distance || 20; // Default distance
5171		var times = o.options.times || 3; // Default # of times
5172		var speed = o.duration || o.options.duration || 140; // Default speed per shake
5173
5174		// Adjust
5175		$.effects.save(el, props); el.show(); // Save & Show
5176		$.effects.createWrapper(el); // Create Wrapper
5177		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
5178		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
5179
5180		// Animation
5181		var animation = {}, animation1 = {}, animation2 = {};
5182		animation[ref] = (motion == 'pos' ? '-=' : '+=')  + distance;
5183		animation1[ref] = (motion == 'pos' ? '+=' : '-=')  + distance * 2;
5184		animation2[ref] = (motion == 'pos' ? '-=' : '+=')  + distance * 2;
5185
5186		// Animate
5187		el.animate(animation, speed, o.options.easing);
5188		for (var i = 1; i < times; i++) { // Shakes
5189			el.animate(animation1, speed, o.options.easing).animate(animation2, speed, o.options.easing);
5190		};
5191		el.animate(animation1, speed, o.options.easing).
5192		animate(animation, speed / 2, o.options.easing, function(){ // Last shake
5193			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
5194			if(o.callback) o.callback.apply(this, arguments); // Callback
5195		});
5196		el.queue('fx', function() { el.dequeue(); });
5197		el.dequeue();
5198	});
5199
5200};
5201
5202})(jQuery);
5203
5204(function( $, undefined ) {
5205
5206$.effects.slide = function(o) {
5207
5208	return this.queue(function() {
5209
5210		// Create element
5211		var el = $(this), props = ['position','top','bottom','left','right'];
5212
5213		// Set options
5214		var mode = $.effects.setMode(el, o.options.mode || 'show'); // Set Mode
5215		var direction = o.options.direction || 'left'; // Default Direction
5216
5217		// Adjust
5218		$.effects.save(el, props); el.show(); // Save & Show
5219		$.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
5220		var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
5221		var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
5222		var distance = o.options.distance || (ref == 'top' ? el.outerHeight( true ) : el.outerWidth( true ));
5223		if (mode == 'show') el.css(ref, motion == 'pos' ? (isNaN(distance) ? "-" + distance : -distance) : distance); // Shift
5224
5225		// Animation
5226		var animation = {};
5227		animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
5228
5229		// Animate
5230		el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
5231			if(mode == 'hide') el.hide(); // Hide
5232			$.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
5233			if(o.callback) o.callback.apply(this, arguments); // Callback
5234			el.dequeue();
5235		}});
5236
5237	});
5238
5239};
5240
5241})(jQuery);
5242
5243(function( $, undefined ) {
5244
5245$.effects.transfer = function(o) {
5246	return this.queue(function() {
5247		var elem = $(this),
5248			target = $(o.options.to),
5249			endPosition = target.offset(),
5250			animation = {
5251				top: endPosition.top,
5252				left: endPosition.left,
5253				height: target.innerHeight(),
5254				width: target.innerWidth()
5255			},
5256			startPosition = elem.offset(),
5257			transfer = $('<div class="ui-effects-transfer"></div>')
5258				.appendTo(document.body)
5259				.addClass(o.options.className)
5260				.css({
5261					top: startPosition.top,
5262					left: startPosition.left,
5263					height: elem.innerHeight(),
5264					width: elem.innerWidth(),
5265					position: 'absolute'
5266				})
5267				.animate(animation, o.duration, o.options.easing, function() {
5268					transfer.remove();
5269					(o.callback && o.callback.apply(elem[0], arguments));
5270					elem.dequeue();
5271				});
5272	});
5273};
5274
5275})(jQuery);
5276
5277(function( $, undefined ) {
5278
5279$.widget( "ui.accordion", {
5280	options: {
5281		active: 0,
5282		animated: "slide",
5283		autoHeight: true,
5284		clearStyle: false,
5285		collapsible: false,
5286		event: "click",
5287		fillSpace: false,
5288		header: "> li > :first-child,> :not(li):even",
5289		icons: {
5290			header: "ui-icon-triangle-1-e",
5291			headerSelected: "ui-icon-triangle-1-s"
5292		},
5293		navigation: false,
5294		navigationFilter: function() {
5295			return this.href.toLowerCase() === location.href.toLowerCase();
5296		}
5297	},
5298
5299	_create: function() {
5300		var self = this,
5301			options = self.options;
5302
5303		self.running = 0;
5304
5305		self.element
5306			.addClass( "ui-accordion ui-widget ui-helper-reset" )
5307			// in lack of child-selectors in CSS
5308			// we need to mark top-LIs in a UL-accordion for some IE-fix
5309			.children( "li" )
5310				.addClass( "ui-accordion-li-fix" );
5311
5312		self.headers = self.element.find( options.header )
5313			.addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" )
5314			.bind( "mouseenter.accordion", function() {
5315				if ( options.disabled ) {
5316					return;
5317				}
5318				$( this ).addClass( "ui-state-hover" );
5319			})
5320			.bind( "mouseleave.accordion", function() {
5321				if ( options.disabled ) {
5322					return;
5323				}
5324				$( this ).removeClass( "ui-state-hover" );
5325			})
5326			.bind( "focus.accordion", function() {
5327				if ( options.disabled ) {
5328					return;
5329				}
5330				$( this ).addClass( "ui-state-focus" );
5331			})
5332			.bind( "blur.accordion", function() {
5333				if ( options.disabled ) {
5334					return;
5335				}
5336				$( this ).removeClass( "ui-state-focus" );
5337			});
5338
5339		self.headers.next()
5340			.addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" );
5341
5342		if ( options.navigation ) {
5343			var current = self.element.find( "a" ).filter( options.navigationFilter ).eq( 0 );
5344			if ( current.length ) {
5345				var header = current.closest( ".ui-accordion-header" );
5346				if ( header.length ) {
5347					// anchor within header
5348					self.active = header;
5349				} else {
5350					// anchor within content
5351					self.active = current.closest( ".ui-accordion-content" ).prev();
5352				}
5353			}
5354		}
5355
5356		self.active = self._findActive( self.active || options.active )
5357			.addClass( "ui-state-default ui-state-active" )
5358			.toggleClass( "ui-corner-all" )
5359			.toggleClass( "ui-corner-top" );
5360		self.active.next().addClass( "ui-accordion-content-active" );
5361
5362		self._createIcons();
5363		self.resize();
5364		
5365		// ARIA
5366		self.element.attr( "role", "tablist" );
5367
5368		self.headers
5369			.attr( "role", "tab" )
5370			.bind( "keydown.accordion", function( event ) {
5371				return self._keydown( event );
5372			})
5373			.next()
5374				.attr( "role", "tabpanel" );
5375
5376		self.headers
5377			.not( self.active || "" )
5378			.attr({
5379				"aria-expanded": "false",
5380				"aria-selected": "false",
5381				tabIndex: -1
5382			})
5383			.next()
5384				.hide();
5385
5386		// make sure at least one header is in the tab order
5387		if ( !self.active.length ) {
5388			self.headers.eq( 0 ).attr( "tabIndex", 0 );
5389		} else {
5390			self.active
5391				.attr({
5392					"aria-expanded": "true",
5393					"aria-selected": "true",
5394					tabIndex: 0
5395				});
5396		}
5397
5398		// only need links in tab order for Safari
5399		if ( !$.browser.safari ) {
5400			self.headers.find( "a" ).attr( "tabIndex", -1 );
5401		}
5402
5403		if ( options.event ) {
5404			self.headers.bind( options.event.split(" ").join(".accordion ") + ".accordion", function(event) {
5405				self._clickHandler.call( self, event, this );
5406				event.preventDefault();
5407			});
5408		}
5409	},
5410
5411	_createIcons: function() {
5412		var options = this.options;
5413		if ( options.icons ) {
5414			$( "<span></span>" )
5415				.addClass( "ui-icon " + options.icons.header )
5416				.prependTo( this.headers );
5417			this.active.children( ".ui-icon" )
5418				.toggleClass(options.icons.header)
5419				.toggleClass(options.icons.headerSelected);
5420			this.element.addClass( "ui-accordion-icons" );
5421		}
5422	},
5423
5424	_destroyIcons: function() {
5425		this.headers.children( ".ui-icon" ).remove();
5426		this.element.removeClass( "ui-accordion-icons" );
5427	},
5428
5429	destroy: function() {
5430		var options = this.options;
5431
5432		this.element
5433			.removeClass( "ui-accordion ui-widget ui-helper-reset" )
5434			.removeAttr( "role" );
5435
5436		this.headers
5437			.unbind( ".accordion" )
5438			.removeClass( "ui-accordion-header ui-accordion-disabled ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top" )
5439			.removeAttr( "role" )
5440			.removeAttr( "aria-expanded" )
5441			.removeAttr( "aria-selected" )
5442			.removeAttr( "tabIndex" );
5443
5444		this.headers.find( "a" ).removeAttr( "tabIndex" );
5445		this._destroyIcons();
5446		var contents = this.headers.next()
5447			.css( "display", "" )
5448			.removeAttr( "role" )
5449			.removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled" );
5450		if ( options.autoHeight || options.fillHeight ) {
5451			contents.css( "height", "" );
5452		}
5453
5454		return $.Widget.prototype.destroy.call( this );
5455	},
5456
5457	_setOption: function( key, value ) {
5458		$.Widget.prototype._setOption.apply( this, arguments );
5459			
5460		if ( key == "active" ) {
5461			this.activate( value );
5462		}
5463		if ( key == "icons" ) {
5464			this._destroyIcons();
5465			if ( value ) {
5466				this._createIcons();
5467			}
5468		}
5469		// #5332 - opacity doesn't cascade to positioned elements in IE
5470		// so we need to add the disabled class to the headers and panels
5471		if ( key == "disabled" ) {
5472			this.headers.add(this.headers.next())
5473				[ value ? "addClass" : "removeClass" ](
5474					"ui-accordion-disabled ui-state-disabled" );
5475		}
5476	},
5477
5478	_keydown: function( event ) {
5479		if ( this.options.disabled || event.altKey || event.ctrlKey ) {
5480			return;
5481		}
5482
5483		var keyCode = $.ui.keyCode,
5484			length = this.headers.length,
5485			currentIndex = this.headers.index( event.target ),
5486			toFocus = false;
5487
5488		switch ( event.keyCode ) {
5489			case keyCode.RIGHT:
5490			case keyCode.DOWN:
5491				toFocus = this.headers[ ( currentIndex + 1 ) % length ];
5492				break;
5493			case keyCode.LEFT:
5494			case keyCode.UP:
5495				toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
5496				break;
5497			case keyCode.SPACE:
5498			case keyCode.ENTER:
5499				this._clickHandler( { target: event.target }, event.target );
5500				event.preventDefault();
5501		}
5502
5503		if ( toFocus ) {
5504			$( event.target ).attr( "tabIndex", -1 );
5505			$( toFocus ).attr( "tabIndex", 0 );
5506			toFocus.focus();
5507			return false;
5508		}
5509
5510		return true;
5511	},
5512
5513	resize: function() {
5514		var options = this.options,
5515			maxHeight;
5516
5517		if ( options.fillSpace ) {
5518			if ( $.browser.msie ) {
5519				var defOverflow = this.element.parent().css( "overflow" );
5520				this.element.parent().css( "overflow", "hidden");
5521			}
5522			maxHeight = this.element.parent().height();
5523			if ($.browser.msie) {
5524				this.element.parent().css( "overflow", defOverflow );
5525			}
5526
5527			this.headers.each(function() {
5528				maxHeight -= $( this ).outerHeight( true );
5529			});
5530
5531			this.headers.next()
5532				.each(function() {
5533					$( this ).height( Math.max( 0, maxHeight -
5534						$( this ).innerHeight() + $( this ).height() ) );
5535				})
5536				.css( "overflow", "auto" );
5537		} else if ( options.autoHeight ) {
5538			maxHeight = 0;
5539			this.headers.next()
5540				.each(function() {
5541					maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
5542				})
5543				.height( maxHeight );
5544		}
5545
5546		return this;
5547	},
5548
5549	activate: function( index ) {
5550		// TODO this gets called on init, changing the option without an explicit call for that
5551		this.options.active = index;
5552		// call clickHandler with custom event
5553		var active = this._findActive( index )[ 0 ];
5554		this._clickHandler( { target: active }, active );
5555
5556		return this;
5557	},
5558
5559	_findActive: function( selector ) {
5560		return selector
5561			? typeof selector === "number"
5562				? this.headers.filter( ":eq(" + selector + ")" )
5563				: this.headers.not( this.headers.not( selector ) )
5564			: selector === false
5565				? $( [] )
5566				: this.headers.filter( ":eq(0)" );
5567	},
5568
5569	// TODO isn't event.target enough? why the separate target argument?
5570	_clickHandler: function( event, target ) {
5571		var options = this.options;
5572		if ( options.disabled ) {
5573			return;
5574		}
5575
5576		// called only when using activate(false) to close all parts programmatically
5577		if ( !event.target ) {
5578			if ( !options.collapsible ) {
5579				return;
5580			}
5581			this.active
5582				.removeClass( "ui-state-active ui-corner-top" )
5583				.addClass( "ui-state-default ui-corner-all" )
5584				.children( ".ui-icon" )
5585					.removeClass( options.icons.headerSelected )
5586					.addClass( options.icons.header );
5587			this.active.next().addClass( "ui-accordion-content-active" );
5588			var toHide = this.active.next(),
5589				data = {
5590					options: options,
5591					newHeader: $( [] ),
5592					oldHeader: options.active,
5593					newContent: $( [] ),
5594					oldContent: toHide
5595				},
5596				toShow = ( this.active = $( [] ) );
5597			this._toggle( toShow, toHide, data );
5598			return;
5599		}
5600
5601		// get the click target
5602		var clicked = $( event.currentTarget || target ),
5603			clickedIsActive = clicked[0] === this.active[0];
5604
5605		// TODO the option is changed, is that correct?
5606		// TODO if it is correct, shouldn't that happen after determining that the click is valid?
5607		options.active = options.collapsible && clickedIsActive ?
5608			false :
5609			this.headers.index( clicked );
5610
5611		// if animations are still active, or the active header is the target, ignore click
5612		if ( this.running || ( !options.collapsible && clickedIsActive ) ) {
5613			return;
5614		}
5615
5616		// find elements to show and hide
5617		var active = this.active,
5618			toShow = clicked.next(),
5619			toHide = this.active.next(),
5620			data = {
5621				options: options,
5622				newHeader: clickedIsActive && options.collapsible ? $([]) : clicked,
5623				oldHeader: this.active,
5624				newContent: clickedIsActive && options.collapsible ? $([]) : toShow,
5625				oldContent: toHide
5626			},
5627			down = this.headers.index( this.active[0] ) > this.headers.index( clicked[0] );
5628
5629		// when the call to ._toggle() comes after the class changes
5630		// it causes a very odd bug in IE 8 (see #6720)
5631		this.active = clickedIsActive ? $([]) : clicked;
5632		this._toggle( toShow, toHide, data, clickedIsActive, down );
5633
5634		// switch classes
5635		active
5636			.removeClass( "ui-state-active ui-corner-top" )
5637			.addClass( "ui-state-default ui-corner-all" )
5638			.children( ".ui-icon" )
5639				.removeClass( options.icons.headerSelected )
5640				.addClass( options.icons.header );
5641		if ( !clickedIsActive ) {
5642			clicked
5643				.removeClass( "ui-state-default ui-corner-all" )
5644				.addClass( "ui-state-active ui-corner-top" )
5645				.children( ".ui-icon" )
5646					.removeClass( options.icons.header )
5647					.addClass( options.icons.headerSelected );
5648			clicked
5649				.next()
5650				.addClass( "ui-accordion-content-active" );
5651		}
5652
5653		return;
5654	},
5655
5656	_toggle: function( toShow, toHide, data, clickedIsActive, down ) {
5657		var self = this,
5658			options = self.options;
5659
5660		self.toShow = toShow;
5661		self.toHide = toHide;
5662		self.data = data;
5663
5664		var complete = function() {
5665			if ( !self ) {
5666				return;
5667			}
5668			return self._completed.apply( self, arguments );
5669		};
5670
5671		// trigger changestart event
5672		self._trigger( "changestart", null, self.data );
5673
5674		// count elements to animate
5675		self.running = toHide.size() === 0 ? toShow.size() : toHide.size();
5676
5677		if ( options.animated ) {
5678			var animOptions = {};
5679
5680			if ( options.collapsible && clickedIsActive ) {
5681				animOptions = {
5682					toShow: $( [] ),
5683					toHide: toHide,
5684					complete: complete,
5685					down: down,
5686					autoHeight: options.autoHeight || options.fillSpace
5687				};
5688			} else {
5689				animOptions = {
5690					toShow: toShow,
5691					toHide: toHide,
5692					complete: complete,
5693					down: down,
5694					autoHeight: options.autoHeight || options.fillSpace
5695				};
5696			}
5697
5698			if ( !options.proxied ) {
5699				options.proxied = options.animated;
5700			}
5701
5702			if ( !options.proxiedDuration ) {
5703				options.proxiedDuration = options.duration;
5704			}
5705
5706			options.animated = $.isFunction( options.proxied ) ?
5707				options.proxied( animOptions ) :
5708				options.proxied;
5709
5710			options.duration = $.isFunction( options.proxiedDuration ) ?
5711				options.proxiedDuration( animOptions ) :
5712				options.proxiedDuration;
5713
5714			var animations = $.ui.accordion.animations,
5715				duration = options.duration,
5716				easing = options.animated;
5717
5718			if ( easing && !animations[ easing ] && !$.easing[ easing ] ) {
5719				easing = "slide";
5720			}
5721			if ( !animations[ easing ] ) {
5722				animations[ easing ] = function( options ) {
5723					this.slide( options, {
5724						easing: easing,
5725						duration: duration || 700
5726					});
5727				};
5728			}
5729
5730			animations[ easing ]( animOptions );
5731		} else {
5732			if ( options.collapsible && clickedIsActive ) {
5733				toShow.toggle();
5734			} else {
5735				toHide.hide();
5736				toShow.show();
5737			}
5738
5739			complete( true );
5740		}
5741
5742		// TODO assert that the blur and focus triggers are really necessary, remove otherwise
5743		toHide.prev()
5744			.attr({
5745				"aria-expanded": "false",
5746				"aria-selected": "false",
5747				tabIndex: -1
5748			})
5749			.blur();
5750		toShow.prev()
5751			.attr({
5752				"aria-expanded": "true",
5753				"aria-selected": "true",
5754				tabIndex: 0
5755			})
5756			.focus();
5757	},
5758
5759	_completed: function( cancel ) {
5760		this.running = cancel ? 0 : --this.running;
5761		if ( this.running ) {
5762			return;
5763		}
5764
5765		if ( this.options.clearStyle ) {
5766			this.toShow.add( this.toHide ).css({
5767				height: "",
5768				overflow: ""
5769			});
5770		}
5771
5772		// other classes are removed before the animation; this one needs to stay until completed
5773		this.toHide.removeClass( "ui-accordion-content-active" );
5774		// Work around for rendering bug in IE (#5421)
5775		if ( this.toHide.length ) {
5776			this.toHide.parent()[0].className = this.toHide.parent()[0].className;
5777		}
5778
5779		this._trigger( "change", null, this.data );
5780	}
5781});
5782
5783$.extend( $.ui.accordion, {
5784	version: "1.8.24",
5785	animations: {
5786		slide: function( options, additions ) {
5787			options = $.extend({
5788				easing: "swing",
5789				duration: 300
5790			}, options, additions );
5791			if ( !options.toHide.size() ) {
5792				options.toShow.animate({
5793					height: "show",
5794					paddingTop: "show",
5795					paddingBottom: "show"
5796				}, options );
5797				return;
5798			}
5799			if ( !options.toShow.size() ) {
5800				options.toHide.animate({
5801					height: "hide",
5802					paddingTop: "hide",
5803					paddingBottom: "hide"
5804				}, options );
5805				return;
5806			}
5807			var overflow = options.toShow.css( "overflow" ),
5808				percentDone = 0,
5809				showProps = {},
5810				hideProps = {},
5811				fxAttrs = [ "height", "paddingTop", "paddingBottom" ],
5812				originalWidth;
5813			// fix width before calculating height of hidden element
5814			var s = options.toShow;
5815			originalWidth = s[0].style.width;
5816			s.width( s.parent().width()
5817				- parseFloat( s.css( "paddingLeft" ) )
5818				- parseFloat( s.css( "paddingRight" ) )
5819				- ( parseFloat( s.css( "borderLeftWidth" ) ) || 0 )
5820				- ( parseFloat( s.css( "borderRightWidth" ) ) || 0 ) );
5821
5822			$.each( fxAttrs, function( i, prop ) {
5823				hideProps[ prop ] = "hide";
5824
5825				var parts = ( "" + $.css( options.toShow[0], prop ) ).match( /^([\d+-.]+)(.*)$/ );
5826				showProps[ prop ] = {
5827					value: parts[ 1 ],
5828					unit: parts[ 2 ] || "px"
5829				};
5830			});
5831			options.toShow.css({ height: 0, overflow: "hidden" }).show();
5832			options.toHide
5833				.filter( ":hidden" )
5834					.each( options.complete )
5835				.end()
5836				.filter( ":visible" )
5837				.animate( hideProps, {
5838				step: function( now, settings ) {
5839					// only calculate the percent when animating height
5840					// IE gets very inconsistent results when animating elements
5841					// with small values, which is common for padding
5842					if ( settings.prop == "height" ) {
5843						percentDone = ( settings.end - settings.start === 0 ) ? 0 :
5844							( settings.now - settings.start ) / ( settings.end - settings.start );
5845					}
5846
5847					options.toShow[ 0 ].style[ settings.prop ] =
5848						( percentDone * showProps[ settings.prop ].value )
5849						+ showProps[ settings.prop ].unit;
5850				},
5851				duration: options.duration,
5852				easing: options.easing,
5853				complete: function() {
5854					if ( !options.autoHeight ) {
5855						options.toShow.css( "height", "" );
5856					}
5857					options.toShow.css({
5858						width: originalWidth,
5859						overflow: overflow
5860					});
5861					options.complete();
5862				}
5863			});
5864		},
5865		bounceslide: function( options ) {
5866			this.slide( options, {
5867				easing: options.down ? "easeOutBounce" : "swing",
5868				duration: options.down ? 1000 : 200
5869			});
5870		}
5871	}
5872});
5873
5874})( jQuery );
5875
5876(function( $, undefined ) {
5877
5878// used to prevent race conditions with remote data sources
5879var requestIndex = 0;
5880
5881$.widget( "ui.autocomplete", {
5882	options: {
5883		appendTo: "body",
5884		autoFocus: false,
5885		delay: 300,
5886		minLength: 1,
5887		position: {
5888			my: "left top",
5889			at: "left bottom",
5890			collision: "none"
5891		},
5892		source: null
5893	},
5894
5895	pending: 0,
5896
5897	_create: function() {
5898		var self = this,
5899			doc = this.element[ 0 ].ownerDocument,
5900			suppressKeyPress;
5901		this.isMultiLine = this.element.is( "textarea" );
5902
5903		this.element
5904			.addClass( "ui-autocomplete-input" )
5905			.attr( "autocomplete", "off" )
5906			// TODO verify these actually work as intended
5907			.attr({
5908				role: "textbox",
5909				"aria-autocomplete": "list",
5910				"aria-haspopup": "true"
5911			})
5912			.bind( "keydown.autocomplete", function( event ) {
5913				if ( self.options.disabled || self.element.propAttr( "readOnly" ) ) {
5914					return;
5915				}
5916
5917				suppressKeyPress = false;
5918				var keyCode = $.ui.keyCode;
5919				switch( event.keyCode ) {
5920				case keyCode.PAGE_UP:
5921					self._move( "previousPage", event );
5922					break;
5923				case keyCode.PAGE_DOWN:
5924					self._move( "nextPage", event );
5925					break;
5926				case keyCode.UP:
5927					self._keyEvent( "previous", event );
5928					break;
5929				case keyCode.DOWN:
5930					self._keyEvent( "next", event );
5931					break;
5932				case keyCode.ENTER:
5933				case keyCode.NUMPAD_ENTER:
5934					// when menu is open and has focus
5935					if ( self.menu.active ) {
5936						// #6055 - Opera still allows the keypress to occur
5937						// which causes forms to submit
5938						suppressKeyPress = true;
5939						event.preventDefault();
5940					}
5941					//passthrough - ENTER and TAB both select the current element
5942				case keyCode.TAB:
5943					if ( !self.menu.active ) {
5944						return;
5945					}
5946					self.menu.select( event );
5947					break;
5948				case keyCode.ESCAPE:
5949					self.element.val( self.term );
5950					self.close( event );
5951					break;
5952				default:
5953					// keypress is triggered before the input value is changed
5954					clearTimeout( self.searching );
5955					self.searching = setTimeout(function() {
5956						// only search if the value has changed
5957						if ( self.term != self.element.val() ) {
5958							self.selectedItem = null;
5959							self.search( null, event );
5960						}
5961					}, self.options.delay );
5962					break;
5963				}
5964			})
5965			.bind( "keypress.autocomplete", function( event ) {
5966				if ( suppressKeyPress ) {
5967					suppressKeyPress = false;
5968					event.preventDefault();
5969				}
5970			})
5971			.bind( "focus.autocomplete", function() {
5972				if ( self.options.disabled ) {
5973					return;
5974				}
5975
5976				self.selectedItem = null;
5977				self.previous = self.element.val();
5978			})
5979			.bind( "blur.autocomplete", function( event ) {
5980				if ( self.options.disabled ) {
5981					return;
5982				}
5983
5984				clearTimeout( self.searching );
5985				// clicks on the menu (or a button to trigger a search) will cause a blur event
5986				self.closing = setTimeout(function() {
5987					self.close( event );
5988					self._change( event );
5989				}, 150 );
5990			});
5991		this._initSource();
5992		this.menu = $( "<ul></ul>" )
5993			.addClass( "ui-autocomplete" )
5994			.appendTo( $( this.options.appendTo || "body", doc )[0] )
5995			// prevent the close-on-blur in case of a "slow" click on the menu (long mousedown)
5996			.mousedown(function( event ) {
5997				// clicking on the scrollbar causes focus to shift to the body
5998				// but we can't detect a mouseup or a click immediately afterward
5999				// so we have to track the next mousedown and close the menu if
6000				// the user clicks somewhere outside of the autocomplete
6001				var menuElement = self.menu.element[ 0 ];
6002				if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
6003					setTimeout(function() {
6004						$( document ).one( 'mousedown', function( event ) {
6005							if ( event.target !== self.element[ 0 ] &&
6006								event.target !== menuElement &&
6007								!$.ui.contains( menuElement, event.target ) ) {
6008								self.close();
6009							}
6010						});
6011					}, 1 );
6012				}
6013
6014				// use another timeout to make sure the blur-event-handler on the input was already triggered
6015				setTimeout(function() {
6016					clearTimeout( self.closing );
6017				}, 13);
6018			})
6019			.menu({
6020				focus: function( event, ui ) {
6021					var item = ui.item.data( "item.autocomplete" );
6022					if ( false !== self._trigger( "focus", event, { item: item } ) ) {
6023						// use value to match what will end up in the input, if it was a key event
6024						if ( /^key/.test(event.originalEvent.type) ) {
6025							self.element.val( item.value );
6026						}
6027					}
6028				},
6029				selected: function( event, ui ) {
6030					var item = ui.item.data( "item.autocomplete" ),
6031						previous = self.previous;
6032
6033					// only trigger when focus was lost (click on menu)
6034					if ( self.element[0] !== doc.activeElement ) {
6035						self.element.focus();
6036						self.previous = previous;
6037						// #6109 - IE triggers two focus events and the second
6038						// is asynchronous, so we need to reset the previous
6039						// term synchronously and asynchronously :-(
6040						setTimeout(function() {
6041							self.previous = previous;
6042							self.selectedItem = item;
6043						}, 1);
6044					}
6045
6046					if ( false !== self._trigger( "select", event, { item: item } ) ) {
6047						self.element.val( item.value );
6048					}
6049					// reset the term after the select event
6050					// this allows custom select handling to work properly
6051					self.term = self.element.val();
6052
6053					self.close( event );
6054					self.selectedItem = item;
6055				},
6056				blur: function( event, ui ) {
6057					// don't set the value of the text field if it's already correct
6058					// this prevents moving the cursor unnecessarily
6059					if ( self.menu.element.is(":visible") &&
6060						( self.element.val() !== self.term ) ) {
6061						self.element.val( self.term );
6062					}
6063				}
6064			})
6065			.zIndex( this.element.zIndex() + 1 )
6066			// workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
6067			.css({ top: 0, left: 0 })
6068			.hide()
6069			.data( "menu" );
6070		if ( $.fn.bgiframe ) {
6071			 this.menu.element.bgiframe();
6072		}
6073		// turning off autocomplete prevents the browser from remembering the
6074		// value when navigating through history, so we re-enable autocomplete
6075		// if the page is unloaded before the widget is destroyed. #7790
6076		self.beforeunloadHandler = function() {
6077			self.element.removeAttr( "autocomplete" );
6078		};
6079		$( window ).bind( "beforeunload", self.beforeunloadHandler );
6080	},
6081
6082	destroy: function() {
6083		this.element
6084			.removeClass( "ui-autocomplete-input" )
6085			.removeAttr( "autocomplete" )
6086			.removeAttr( "role" )
6087			.removeAttr( "aria-autocomplete" )
6088			.removeAttr( "aria-haspopup" );
6089		this.menu.element.remove();
6090		$( window ).unbind( "beforeunload", this.beforeunloadHandler );
6091		$.Widget.prototype.destroy.call( this );
6092	},
6093
6094	_setOption: function( key, value ) {
6095		$.Widget.prototype._setOption.apply( this, arguments );
6096		if ( key === "source" ) {
6097			this._initSource();
6098		}
6099		if ( key === "appendTo" ) {
6100			this.menu.element.appendTo( $( value || "body", this.element[0].ownerDocument )[0] )
6101		}
6102		if ( key === "disabled" && value && this.xhr ) {
6103			this.xhr.abort();
6104		}
6105	},
6106
6107	_initSource: function() {
6108		var self = this,
6109			array,
6110			url;
6111		if ( $.isArray(this.options.source) ) {
6112			array = this.options.source;
6113			this.source = function( request, response ) {
6114				response( $.ui.autocomplete.filter(array, request.term) );
6115			};
6116		} else if ( typeof this.options.source === "string" ) {
6117			url = this.options.source;
6118			this.source = function( request, response ) {
6119				if ( self.xhr ) {
6120					self.xhr.abort();
6121				}
6122				self.xhr = $.ajax({
6123					url: url,
6124					data: request,
6125					dataType: "json",
6126					success: function( data, status ) {
6127						response( data );
6128					},
6129					error: function() {
6130						response( [] );
6131					}
6132				});
6133			};
6134		} else {
6135			this.source = this.options.source;
6136		}
6137	},
6138
6139	search: function( value, event ) {
6140		value = value != null ? value : this.element.val();
6141
6142		// always save the actual value, not the one passed as an argument
6143		this.term = this.element.val();
6144
6145		if ( value.length < this.options.minLength ) {
6146			return this.close( event );
6147		}
6148
6149		clearTimeout( this.closing );
6150		if ( this._trigger( "search", event ) === false ) {
6151			return;
6152		}
6153
6154		return this._search( value );
6155	},
6156
6157	_search: function( value ) {
6158		this.pending++;
6159		this.element.addClass( "ui-autocomplete-loading" );
6160
6161		this.source( { term: value }, this._response() );
6162	},
6163
6164	_response: function() {
6165		var that = this,
6166			index = ++requestIndex;
6167
6168		return function( content ) {
6169			if ( index === requestIndex ) {
6170				that.__response( content );
6171			}
6172
6173			that.pending--;
6174			if ( !that.pending ) {
6175				that.element.removeClass( "ui-autocomplete-loading" );
6176			}
6177		};
6178	},
6179
6180	__response: function( content ) {
6181		if ( !this.options.disabled && content && content.length ) {
6182			content = this._normalize( content );
6183			this._suggest( content );
6184			this._trigger( "open" );
6185		} else {
6186			this.close();
6187		}
6188	},
6189
6190	close: function( event ) {
6191		clearTimeout( this.closing );
6192		if ( this.menu.element.is(":visible") ) {
6193			this.menu.element.hide();
6194			this.menu.deactivate();
6195			this._trigger( "close", event );
6196		}
6197	},
6198	
6199	_change: function( event ) {
6200		if ( this.previous !== this.element.val() ) {
6201			this._trigger( "change", event, { item: this.selectedItem } );
6202		}
6203	},
6204
6205	_normalize: function( items ) {
6206		// assume all items have the right format when the first item is complete
6207		if ( items.length && items[0].label && items[0].value ) {
6208			return items;
6209		}
6210		return $.map( items, function(item) {
6211			if ( typeof item === "string" ) {
6212				return {
6213					label: item,
6214					value: item
6215				};
6216			}
6217			return $.extend({
6218				label: item.label || item.value,
6219				value: item.value || item.label
6220			}, item );
6221		});
6222	},
6223
6224	_suggest: function( items ) {
6225		var ul = this.menu.element
6226			.empty()
6227			.zIndex( this.element.zIndex() + 1 );
6228		this._renderMenu( ul, items );
6229		// TODO refresh should check if the active item is still in the dom, removing the need for a manual deactivate
6230		this.menu.deactivate();
6231		this.menu.refresh();
6232
6233		// size and position menu
6234		ul.show();
6235		this._resizeMenu();
6236		ul.position( $.extend({
6237			of: this.element
6238		}, this.options.position ));
6239
6240		if ( this.options.autoFocus ) {
6241			this.menu.next( new $.Event("mouseover") );
6242		}
6243	},
6244
6245	_resizeMenu: function() {
6246		var ul = this.menu.element;
6247		ul.outerWidth( Math.max(
6248			// Firefox wraps long text (possibly a rounding bug)
6249			// so we add 1px to avoid the wrapping (#7513)
6250			ul.width( "" ).outerWidth() + 1,
6251			this.element.outerWidth()
6252		) );
6253	},
6254
6255	_renderMenu: function( ul, items ) {
6256		var self = this;
6257		$.each( items, function( index, item ) {
6258			self._renderItem( ul, item );
6259		});
6260	},
6261
6262	_renderItem: function( ul, item) {
6263		return $( "<li></li>" )
6264			.data( "item.autocomplete", item )
6265			.append( $( "<a></a>" ).text( item.label ) )
6266			.appendTo( ul );
6267	},
6268
6269	_move: function( direction, event ) {
6270		if ( !this.menu.element.is(":visible") ) {
6271			this.search( null, event );
6272			return;
6273		}
6274		if ( this.menu.first() && /^previous/.test(direction) ||
6275				this.menu.last() && /^next/.test(direction) ) {
6276			this.element.val( this.term );
6277			this.menu.deactivate();
6278			return;
6279		}
6280		this.menu[ direction ]( event );
6281	},
6282
6283	widget: function() {
6284		return this.menu.element;
6285	},
6286	_keyEvent: function( keyEvent, event ) {
6287		if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
6288			this._move( keyEvent, event );
6289
6290			// prevents moving cursor to beginning/end of the text field in some browsers
6291			event.preventDefault();
6292		}
6293	}
6294});
6295
6296$.extend( $.ui.autocomplete, {
6297	escapeRegex: function( value ) {
6298		return value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
6299	},
6300	filter: function(array, term) {
6301		var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" );
6302		return $.grep( array, function(value) {
6303			return matcher.test( value.label || value.value || value );
6304		});
6305	}
6306});
6307
6308}( jQuery ));
6309
6310/*
6311 * jQuery UI Menu (not officially released)
6312 * 
6313 * This widget isn't yet finished and the API is subject to change. We plan to finish
6314 * it for the next release. You're welcome to give it a try anyway and give us feedback,
6315 * as long as you're okay with migrating your code later on. We can help with that, too.
6316 *
6317 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
6318 * Dual licensed under the MIT or GPL Version 2 licenses.
6319 * http://jquery.org/license
6320 *
6321 * http://docs.jquery.com/UI/Menu
6322 *
6323 * Depends:
6324 *	jquery.ui.core.js
6325 *  jquery.ui.widget.js
6326 */
6327(function($) {
6328
6329$.widget("ui.menu", {
6330	_create: function() {
6331		var self = this;
6332		this.element
6333			.addClass("ui-menu ui-widget ui-widget-content ui-corner-all")
6334			.attr({
6335				role: "listbox",
6336				"aria-activedescendant": "ui-active-menuitem"
6337			})
6338			.click(function( event ) {
6339				if ( !$( event.target ).closest( ".ui-menu-item a" ).length ) {
6340					return;
6341				}
6342				// temporary
6343				event.preventDefault();
6344				self.select( event );
6345			});
6346		this.refresh();
6347	},
6348	
6349	refresh: function() {
6350		var self = this;
6351
6352		// don't refresh list items that are already adapted
6353		var items = this.element.children("li:not(.ui-menu-item):has(a)")
6354			.addClass("ui-menu-item")
6355			.attr("role", "menuitem");
6356		
6357		items.children("a")
6358			.addClass("ui-corner-all")
6359			.attr("tabindex", -1)
6360			// mouseenter doesn't work with event delegation
6361			.mouseenter(function( event ) {
6362				self.activate( event, $(this).parent() );
6363			})
6364			.mouseleave(function() {
6365				self.deactivate();
6366			});
6367	},
6368
6369	activate: function( event, item ) {
6370		this.deactivate();
6371		if (this.hasScroll()) {
6372			var offset = item.offset().top - this.element.offset().top,
6373				scroll = this.element.scrollTop(),
6374				elementHeight = this.element.height();
6375			if (offset < 0) {
6376				this.element.scrollTop( scroll + offset);
6377			} else if (offset >= elementHeight) {
6378				this.element.scrollTop( scroll + offset - elementHeight + item.height());
6379			}
6380		}
6381		this.active = item.eq(0)
6382			.children("a")
6383				.addClass("ui-state-hover")
6384				.attr("id", "ui-active-menuitem")
6385			.end();
6386		this._trigger("focus", event, { item: item });
6387	},
6388
6389	deactivate: function() {
6390		if (!this.active) { return; }
6391
6392		this.active.children("a")
6393			.removeClass("ui-state-hover")
6394			.removeAttr("id");
6395		this._trigger("blur");
6396		this.active = null;
6397	},
6398
6399	next: function(event) {
6400		this.move("next", ".ui-menu-item:first", event);
6401	},
6402
6403	previous: function(event) {
6404		this.move("prev", ".ui-menu-item:last", event);
6405	},
6406
6407	first: function() {
6408		return this.active && !this.active.prevAll(".ui-menu-item").length;
6409	},
6410
6411	last: function() {
6412		return this.active && !this.active.nextAll(".ui-menu-item").length;
6413	},
6414
6415	move: function(direction, edge, event) {
6416		if (!this.active) {
6417			this.activate(event, this.element.children(edge));
6418			return;
6419		}
6420		var next = this.active[direction + "All"](".ui-menu-item").eq(0);
6421		if (next.length) {
6422			this.activate(event, next);
6423		} else {
6424			this.activate(event, this.element.children(edge));
6425		}
6426	},
6427
6428	// TODO merge with previousPage
6429	nextPage: function(event) {
6430		if (this.hasScroll()) {
6431			// TODO merge with no-scroll-else
6432			if (!this.active || this.last()) {
6433				this.activate(event, this.element.children(".ui-menu-item:first"));
6434				return;
6435			}
6436			var base = this.active.offset().top,
6437				height = this.element.height(),
6438				result = this.element.children(".ui-menu-item").filter(function() {
6439					var close = $(this).offset().top - base - height + $(this).height();
6440					// TODO improve approximation
6441					return close < 10 && close > -10;
6442				});
6443
6444			// TODO try to catch this earlier when scrollTop indicates the last page anyway
6445			if (!result.length) {
6446				result = this.element.children(".ui-menu-item:last");
6447			}
6448			this.activate(event, result);
6449		} else {
6450			this.activate(event, this.element.children(".ui-menu-item")
6451				.filter(!this.active || this.last() ? ":first" : ":last"));
6452		}
6453	},
6454
6455	// TODO merge with nextPage
6456	previousPage: function(event) {
6457		if (this.hasScroll()) {
6458			// TODO merge with no-scroll-else
6459			if (!this.active || this.first()) {
6460				this.activate(event, this.element.children(".ui-menu-item:last"));
6461				return;
6462			}
6463
6464			var base = this.active.offset().top,
6465				height = this.element.height(),
6466				result = this.element.children(".ui-menu-item").filter(function() {
6467					var close = $(this).offset().top - base + height - $(this).height();
6468					// TODO improve approximation
6469					return close < 10 && close > -10;
6470				});
6471
6472			// TODO try to catch this earlier when scrollTop indicates the last page anyway
6473			if (!result.length) {
6474				result = this.element.children(".ui-menu-item:first");
6475			}
6476			this.activate(event, result);
6477		} else {
6478			this.activate(event, this.element.children(".ui-menu-item")
6479				.filter(!this.active || this.first() ? ":last" : ":first"));
6480		}
6481	},
6482
6483	hasScroll: function() {
6484		return this.element.height() < this.element[ $.fn.prop ? "prop" : "attr" ]("scrollHeight");
6485	},
6486
6487	select: function( event ) {
6488		this._trigger("selected", event, { item: this.active });
6489	}
6490});
6491
6492}(jQuery));
6493
6494(function( $, undefined ) {
6495
6496var lastActive, startXPos, startYPos, clickDragged,
6497	baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
6498	stateClasses = "ui-state-hover ui-state-active ",
6499	typeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",
6500	formResetHandler = function() {
6501		var buttons = $( this ).find( ":ui-button" );
6502		setTimeout(function() {
6503			buttons.button( "refresh" );
6504		}, 1 );
6505	},
6506	radioGroup = function( radio ) {
6507		var name = radio.name,
6508			form = radio.form,
6509			radios = $( [] );
6510		if ( name ) {
6511			if ( form ) {
6512				radios = $( form ).find( "[name='" + name + "']" );
6513			} else {
6514				radios = $( "[name='" + name + "']", radio.ownerDocument )
6515					.filter(function() {
6516						return !this.form;
6517					});
6518			}
6519		}
6520		return radios;
6521	};
6522
6523$.widget( "ui.button", {
6524	options: {
6525		disabled: null,
6526		text: true,
6527		label: null,
6528		icons: {
6529			primary: null,
6530			secondary: null
6531		}
6532	},
6533	_create: function() {
6534		this.element.closest( "form" )
6535			.unbind( "reset.button" )
6536			.bind( "reset.button", formResetHandler );
6537
6538		if ( typeof this.options.disabled !== "boolean" ) {
6539			this.options.disabled = !!this.element.propAttr( "disabled" );
6540		} else {
6541			this.element.propAttr( "disabled", this.options.disabled );
6542		}
6543
6544		this._determineButtonType();
6545		this.hasTitle = !!this.buttonElement.attr( "title" );
6546
6547		var self = this,
6548			options = this.options,
6549			toggleButton = this.type === "checkbox" || this.type === "radio",
6550			hoverClass = "ui-state-hover" + ( !toggleButton ? " ui-state-active" : "" ),
6551			focusClass = "ui-state-focus";
6552
6553		if ( options.label === null ) {
6554			options.label = this.buttonElement.html();
6555		}
6556
6557		this.buttonElement
6558			.addClass( baseClasses )
6559			.attr( "role", "button" )
6560			.bind( "mouseenter.button", function() {
6561				if ( options.disabled ) {
6562					return;
6563				}
6564				$( this ).addClass( "ui-state-hover" );
6565				if ( this === lastActive ) {
6566					$( this ).addClass( "ui-state-active" );
6567				}
6568			})
6569			.bind( "mouseleave.button", function() {
6570				if ( options.disabled ) {
6571					return;
6572				}
6573				$( this ).removeClass( hoverClass );
6574			})
6575			.bind( "click.button", function( event ) {
6576				if ( options.disabled ) {
6577					event.preventDefault();
6578					event.stopImmediatePropagation();
6579				}
6580			});
6581
6582		this.element
6583			.bind( "focus.button", function() {
6584				// no need to check disabled, focus won't be triggered anyway
6585				self.buttonElement.addClass( focusClass );
6586			})
6587			.bind( "blur.button", function() {
6588				self.buttonElement.removeClass( focusClass );
6589			});
6590
6591		if ( toggleButton ) {
6592			this.element.bind( "change.button", function() {
6593				if ( clickDragged ) {
6594					return;
6595				}
6596				self.refresh();
6597			});
6598			// if mouse moves between mousedown and mouseup (drag) set clickDragged flag
6599			// prevents issue where button state changes but checkbox/radio checked state
6600			// does not in Firefox (see ticket #6970)
6601			this.buttonElement
6602				.bind( "mousedown.button", function( event ) {
6603					if ( options.disabled ) {
6604						return;
6605					}
6606					clickDragged = false;
vendor: 16,047 bytes, lines 6607-7033
6607					startXPos = event.pageX;
6608					startYPos = event.pageY;
6609				})
6610				.bind( "mouseup.button", function( event ) {
6611					if ( options.disabled ) {
6612						return;
6613					}
6614					if ( startXPos !== event.pageX || startYPos !== event.pageY ) {
6615						clickDragged = true;
6616					}
6617			});
6618		}
6619
6620		if ( this.type === "checkbox" ) {
6621			this.buttonElement.bind( "click.button", function() {
6622				if ( options.disabled || clickDragged ) {
6623					return false;
6624				}
6625				$( this ).toggleClass( "ui-state-active" );
6626				self.buttonElement.attr( "aria-pressed", self.element[0].checked );
6627			});
6628		} else if ( this.type === "radio" ) {
6629			this.buttonElement.bind( "click.button", function() {
6630				if ( options.disabled || clickDragged ) {
6631					return false;
6632				}
6633				$( this ).addClass( "ui-state-active" );
6634				self.buttonElement.attr( "aria-pressed", "true" );
6635
6636				var radio = self.element[ 0 ];
6637				radioGroup( radio )
6638					.not( radio )
6639					.map(function() {
6640						return $( this ).button( "widget" )[ 0 ];
6641					})
6642					.removeClass( "ui-state-active" )
6643					.attr( "aria-pressed", "false" );
6644			});
6645		} else {
6646			this.buttonElement
6647				.bind( "mousedown.button", function() {
6648					if ( options.disabled ) {
6649						return false;
6650					}
6651					$( this ).addClass( "ui-state-active" );
6652					lastActive = this;
6653					$( document ).one( "mouseup", function() {
6654						lastActive = null;
6655					});
6656				})
6657				.bind( "mouseup.button", function() {
6658					if ( options.disabled ) {
6659						return false;
6660					}
6661					$( this ).removeClass( "ui-state-active" );
6662				})
6663				.bind( "keydown.button", function(event) {
6664					if ( options.disabled ) {
6665						return false;
6666					}
6667					if ( event.keyCode == $.ui.keyCode.SPACE || event.keyCode == $.ui.keyCode.ENTER ) {
6668						$( this ).addClass( "ui-state-active" );
6669					}
6670				})
6671				.bind( "keyup.button", function() {
6672					$( this ).removeClass( "ui-state-active" );
6673				});
6674
6675			if ( this.buttonElement.is("a") ) {
6676				this.buttonElement.keyup(function(event) {
6677					if ( event.keyCode === $.ui.keyCode.SPACE ) {
6678						// TODO pass through original event correctly (just as 2nd argument doesn't work)
6679						$( this ).click();
6680					}
6681				});
6682			}
6683		}
6684
6685		// TODO: pull out $.Widget's handling for the disabled option into
6686		// $.Widget.prototype._setOptionDisabled so it's easy to proxy and can
6687		// be overridden by individual plugins
6688		this._setOption( "disabled", options.disabled );
6689		this._resetButton();
6690	},
6691
6692	_determineButtonType: function() {
6693
6694		if ( this.element.is(":checkbox") ) {
6695			this.type = "checkbox";
6696		} else if ( this.element.is(":radio") ) {
6697			this.type = "radio";
6698		} else if ( this.element.is("input") ) {
6699			this.type = "input";
6700		} else {
6701			this.type = "button";
6702		}
6703
6704		if ( this.type === "checkbox" || this.type === "radio" ) {
6705			// we don't search against the document in case the element
6706			// is disconnected from the DOM
6707			var ancestor = this.element.parents().filter(":last"),
6708				labelSelector = "label[for='" + this.element.attr("id") + "']";
6709			this.buttonElement = ancestor.find( labelSelector );
6710			if ( !this.buttonElement.length ) {
6711				ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings();
6712				this.buttonElement = ancestor.filter( labelSelector );
6713				if ( !this.buttonElement.length ) {
6714					this.buttonElement = ancestor.find( labelSelector );
6715				}
6716			}
6717			this.element.addClass( "ui-helper-hidden-accessible" );
6718
6719			var checked = this.element.is( ":checked" );
6720			if ( checked ) {
6721				this.buttonElement.addClass( "ui-state-active" );
6722			}
6723			this.buttonElement.attr( "aria-pressed", checked );
6724		} else {
6725			this.buttonElement = this.element;
6726		}
6727	},
6728
6729	widget: function() {
6730		return this.buttonElement;
6731	},
6732
6733	destroy: function() {
6734		this.element
6735			.removeClass( "ui-helper-hidden-accessible" );
6736		this.buttonElement
6737			.removeClass( baseClasses + " " + stateClasses + " " + typeClasses )
6738			.removeAttr( "role" )
6739			.removeAttr( "aria-pressed" )
6740			.html( this.buttonElement.find(".ui-button-text").html() );
6741
6742		if ( !this.hasTitle ) {
6743			this.buttonElement.removeAttr( "title" );
6744		}
6745
6746		$.Widget.prototype.destroy.call( this );
6747	},
6748
6749	_setOption: function( key, value ) {
6750		$.Widget.prototype._setOption.apply( this, arguments );
6751		if ( key === "disabled" ) {
6752			if ( value ) {
6753				this.element.propAttr( "disabled", true );
6754			} else {
6755				this.element.propAttr( "disabled", false );
6756			}
6757			return;
6758		}
6759		this._resetButton();
6760	},
6761
6762	refresh: function() {
6763		var isDisabled = this.element.is( ":disabled" );
6764		if ( isDisabled !== this.options.disabled ) {
6765			this._setOption( "disabled", isDisabled );
6766		}
6767		if ( this.type === "radio" ) {
6768			radioGroup( this.element[0] ).each(function() {
6769				if ( $( this ).is( ":checked" ) ) {
6770					$( this ).button( "widget" )
6771						.addClass( "ui-state-active" )
6772						.attr( "aria-pressed", "true" );
6773				} else {
6774					$( this ).button( "widget" )
6775						.removeClass( "ui-state-active" )
6776						.attr( "aria-pressed", "false" );
6777				}
6778			});
6779		} else if ( this.type === "checkbox" ) {
6780			if ( this.element.is( ":checked" ) ) {
6781				this.buttonElement
6782					.addClass( "ui-state-active" )
6783					.attr( "aria-pressed", "true" );
6784			} else {
6785				this.buttonElement
6786					.removeClass( "ui-state-active" )
6787					.attr( "aria-pressed", "false" );
6788			}
6789		}
6790	},
6791
6792	_resetButton: function() {
6793		if ( this.type === "input" ) {
6794			if ( this.options.label ) {
6795				this.element.val( this.options.label );
6796			}
6797			return;
6798		}
6799		var buttonElement = this.buttonElement.removeClass( typeClasses ),
6800			buttonText = $( "<span></span>", this.element[0].ownerDocument )
6801				.addClass( "ui-button-text" )
6802				.html( this.options.label )
6803				.appendTo( buttonElement.empty() )
6804				.text(),
6805			icons = this.options.icons,
6806			multipleIcons = icons.primary && icons.secondary,
6807			buttonClasses = [];  
6808
6809		if ( icons.primary || icons.secondary ) {
6810			if ( this.options.text ) {
6811				buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
6812			}
6813
6814			if ( icons.primary ) {
6815				buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
6816			}
6817
6818			if ( icons.secondary ) {
6819				buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
6820			}
6821
6822			if ( !this.options.text ) {
6823				buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" );
6824
6825				if ( !this.hasTitle ) {
6826					buttonElement.attr( "title", buttonText );
6827				}
6828			}
6829		} else {
6830			buttonClasses.push( "ui-button-text-only" );
6831		}
6832		buttonElement.addClass( buttonClasses.join( " " ) );
6833	}
6834});
6835
6836$.widget( "ui.buttonset", {
6837	options: {
6838		items: ":button, :submit, :reset, :checkbox, :radio, a, :data(button)"
6839	},
6840
6841	_create: function() {
6842		this.element.addClass( "ui-buttonset" );
6843	},
6844	
6845	_init: function() {
6846		this.refresh();
6847	},
6848
6849	_setOption: function( key, value ) {
6850		if ( key === "disabled" ) {
6851			this.buttons.button( "option", key, value );
6852		}
6853
6854		$.Widget.prototype._setOption.apply( this, arguments );
6855	},
6856	
6857	refresh: function() {
6858		var rtl = this.element.css( "direction" ) === "rtl";
6859		
6860		this.buttons = this.element.find( this.options.items )
6861			.filter( ":ui-button" )
6862				.button( "refresh" )
6863			.end()
6864			.not( ":ui-button" )
6865				.button()
6866			.end()
6867			.map(function() {
6868				return $( this ).button( "widget" )[ 0 ];
6869			})
6870				.removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
6871				.filter( ":first" )
6872					.addClass( rtl ? "ui-corner-right" : "ui-corner-left" )
6873				.end()
6874				.filter( ":last" )
6875					.addClass( rtl ? "ui-corner-left" : "ui-corner-right" )
6876				.end()
6877			.end();
6878	},
6879
6880	destroy: function() {
6881		this.element.removeClass( "ui-buttonset" );
6882		this.buttons
6883			.map(function() {
6884				return $( this ).button( "widget" )[ 0 ];
6885			})
6886				.removeClass( "ui-corner-left ui-corner-right" )
6887			.end()
6888			.button( "destroy" );
6889
6890		$.Widget.prototype.destroy.call( this );
6891	}
6892});
6893
6894}( jQuery ) );
6895
6896(function( $, undefined ) {
6897
6898$.extend($.ui, { datepicker: { version: "1.8.24" } });
6899
6900var PROP_NAME = 'datepicker';
6901var dpuuid = new Date().getTime();
6902var instActive;
6903
6904/* Date picker manager.
6905   Use the singleton instance of this class, $.datepicker, to interact with the date picker.
6906   Settings for (groups of) date pickers are maintained in an instance object,
6907   allowing multiple different settings on the same page. */
6908
6909function Datepicker() {
6910	this.debug = false; // Change this to true to start debugging
6911	this._curInst = null; // The current instance in use
6912	this._keyEvent = false; // If the last event was a key event
6913	this._disabledInputs = []; // List of date picker inputs that have been disabled
6914	this._datepickerShowing = false; // True if the popup picker is showing , false if not
6915	this._inDialog = false; // True if showing within a "dialog", false if not
6916	this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division
6917	this._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class
6918	this._appendClass = 'ui-datepicker-append'; // The name of the append marker class
6919	this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class
6920	this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class
6921	this._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class
6922	this._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class
6923	this._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class
6924	this._dayOverClass = 'ui-datepicker-days-cell-over'; // The name of the day hover marker class
6925	this.regional = []; // Available regional settings, indexed by language code
6926	this.regional[''] = { // Default regional settings
6927		closeText: 'Done', // Display text for close link
6928		prevText: 'Prev', // Display text for previous month link
6929		nextText: 'Next', // Display text for next month link
6930		currentText: 'Today', // Display text for current month link
6931		monthNames: ['January','February','March','April','May','June',
6932			'July','August','September','October','November','December'], // Names of months for drop-down and formatting
6933		monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting
6934		dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting
6935		dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting
6936		dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday
6937		weekHeader: 'Wk', // Column header for week of the year
6938		dateFormat: 'mm/dd/yy', // See format options on parseDate
6939		firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
6940		isRTL: false, // True if right-to-left language, false if left-to-right
6941		showMonthAfterYear: false, // True if the year select precedes month, false for month then year
6942		yearSuffix: '' // Additional text to append to the year in the month headers
6943	};
6944	this._defaults = { // Global defaults for all the date picker instances
6945		showOn: 'focus', // 'focus' for popup on focus,
6946			// 'button' for trigger button, or 'both' for either
6947		showAnim: 'fadeIn', // Name of jQuery animation for popup
6948		showOptions: {}, // Options for enhanced animations
6949		defaultDate: null, // Used when field is blank: actual date,
6950			// +/-number for offset from today, null for today
6951		appendText: '', // Display text following the input box, e.g. showing the format
6952		buttonText: '...', // Text for trigger button
6953		buttonImage: '', // URL for trigger button image
6954		buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
6955		hideIfNoPrevNext: false, // True to hide next/previous month links
6956			// if not applicable, false to just disable them
6957		navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
6958		gotoCurrent: false, // True if today link goes back to current selection instead
6959		changeMonth: false, // True if month can be selected directly, false if only prev/next
6960		changeYear: false, // True if year can be selected directly, false if only prev/next
6961		yearRange: 'c-10:c+10', // Range of years to display in drop-down,
6962			// either relative to today's year (-nn:+nn), relative to currently displayed year
6963			// (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
6964		showOtherMonths: false, // True to show dates in other months, false to leave blank
6965		selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
6966		showWeek: false, // True to show week of the year, false to not show it
6967		calculateWeek: this.iso8601Week, // How to calculate the week of the year,
6968			// takes a Date and returns the number of the week for it
6969		shortYearCutoff: '+10', // Short year values < this are in the current century,
6970			// > this are in the previous century,
6971			// string value starting with '+' for current year + value
6972		minDate: null, // The earliest selectable date, or null for no limit
6973		maxDate: null, // The latest selectable date, or null for no limit
6974		duration: 'fast', // Duration of display/closure
6975		beforeShowDay: null, // Function that takes a date and returns an array with
6976			// [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '',
6977			// [2] = cell title (optional), e.g. $.datepicker.noWeekends
6978		beforeShow: null, // Function that takes an input field and
6979			// returns a set of custom settings for the date picker
6980		onSelect: null, // Define a callback function when a date is selected
6981		onChangeMonthYear: null, // Define a callback function when the month or year is changed
6982		onClose: null, // Define a callback function when the datepicker is closed
6983		numberOfMonths: 1, // Number of months to show at a time
6984		showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
6985		stepMonths: 1, // Number of months to step back/forward
6986		stepBigMonths: 12, // Number of months to step back/forward for the big links
6987		altField: '', // Selector for an alternate field to store selected dates into
6988		altFormat: '', // The date format to use for the alternate field
6989		constrainInput: true, // The input is constrained by the current date format
6990		showButtonPanel: false, // True to show button panel, false to not show it
6991		autoSize: false, // True to size the input for the date format, false to leave as is
6992		disabled: false // The initial disabled state
6993	};
6994	$.extend(this._defaults, this.regional['']);
6995	this.dpDiv = bindHover($('<div id="' + this._mainDivId + '" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'));
6996}
6997
6998$.extend(Datepicker.prototype, {
6999	/* Class name added to elements to indicate already configured with a date picker. */
7000	markerClassName: 'hasDatepicker',
7001	
7002	//Keep track of the maximum number of rows displayed (see #7043)
7003	maxRows: 4,
7004
7005	/* Debug logging (if enabled). */
7006	log: function () {
7007		if (this.debug)
7008			console.log.apply('', arguments);
7009	},
7010	
7011	// TODO rename to "widget" when switching to widget factory
7012	_widgetDatepicker: function() {
7013		return this.dpDiv;
7014	},
7015
7016	/* Override the default settings for all instances of the date picker.
7017	   @param  settings  object - the new settings to use as defaults (anonymous object)
7018	   @return the manager object */
7019	setDefaults: function(settings) {
7020		extendRemove(this._defaults, settings || {});
7021		return this;
7022	},
7023
7024	/* Attach the date picker to a jQuery selection.
7025	   @param  target    element - the target input field or division or span
7026	   @param  settings  object - the new settings to use for this date picker instance (anonymous) */
7027	_attachDatepicker: function(target, settings) {
7028		// check for settings on the control itself - in namespace 'date:'
7029		var inlineSettings = null;
7030		for (var attrName in this._defaults) {
7031			var attrValue = target.getAttribute('date:' + attrName);
7032			if (attrValue) {
7033				inlineSettings = inlineSettings || {};
7034				try {
7035					inlineSettings[attrName] = eval(attrValue);
7036				} catch (err) {
7037					inlineSettings[attrName] = attrValue;
7038				}
7039			}
7040		}
7041		var nodeName = target.nodeName.toLowerCase();
7042		var inline = (nodeName == 'div' || nodeName == 'span');
7043		if (!target.id) {
7044			this.uuid += 1;
7045			target.id = 'dp' + this.uuid;
7046		}
7047		var inst = this._newInst($(target), inline);
7048		inst.settings = $.extend({}, settings || {}, inlineSettings || {});
7049		if (nodeName == 'input') {
7050			this._connectDatepicker(target, inst);
7051		} else if (inline) {
7052			this._inlineDatepicker(target, inst);
7053		}
7054	},
7055
7056	/* Create a new instance object. */
7057	_newInst: function(target, inline) {
7058		var id = target[0].id.replace(/([^A-Za-z0-9_-])/g, '\\\\$1'); // escape jQuery meta chars
7059		return {id: id, input: target, // associated target
7060			selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
7061			drawMonth: 0, drawYear: 0, // month being drawn
7062			inline: inline, // is datepicker inline or not
7063			dpDiv: (!inline ? this.dpDiv : // presentation div
7064			bindHover($('<div class="' + this._inlineClass + ' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>')))};
7065	},
7066
7067	/* Attach the date picker to an input field. */
7068	_connectDatepicker: function(target, inst) {
7069		var input = $(target);
7070		inst.append = $([]);
7071		inst.trigger = $([]);
7072		if (input.hasClass(this.markerClassName))
7073			return;
7074		this._attachments(input, inst);
7075		input.addClass(this.markerClassName).keydown(this._doKeyDown).
7076			keypress(this._doKeyPress).keyup(this._doKeyUp).
7077			bind("setData.datepicker", function(event, key, value) {
7078				inst.settings[key] = value;
7079			}).bind("getData.datepicker", function(event, key) {
7080				return this._get(inst, key);
7081			});
7082		this._autoSize(inst);
7083		$.data(target, PROP_NAME, inst);
7084		//If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
7085		if( inst.settings.disabled ) {
7086			this._disableDatepicker( target );
7087		}
7088	},
7089
7090	/* Make attachments based on settings. */
7091	_attachments: function(input, inst) {
7092		var appendText = this._get(inst, 'appendText');
7093		var isRTL = this._get(inst, 'isRTL');
7094		if (inst.append)
7095			inst.append.remove();
7096		if (appendText) {
7097			inst.append = $('<span class="' + this._appendClass + '">' + appendText + '</span>');
7098			input[isRTL ? 'before' : 'after'](inst.append);
7099		}
7100		input.unbind('focus', this._showDatepicker);
7101		if (inst.trigger)
7102			inst.trigger.remove();
7103		var showOn = this._get(inst, 'showOn');
7104		if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field
7105			input.focus(this._showDatepicker);
7106		if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked
7107			var buttonText = this._get(inst, 'buttonText');
7108			var buttonImage = this._get(inst, 'buttonImage');
7109			inst.trigger = $(this._get(inst, 'buttonImageOnly') ?
7110				$('<img/>').addClass(this._triggerClass).
7111					attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
7112				$('<button type="button"></button>').addClass(this._triggerClass).
7113					html(buttonImage == '' ? buttonText : $('<img/>').attr(
7114					{ src:buttonImage, alt:buttonText, title:buttonText })));
7115			input[isRTL ? 'before' : 'after'](inst.trigger);
7116			inst.trigger.click(function() {
7117				if ($.datepicker._datepickerShowing && $.datepicker._lastInput == input[0])
7118					$.datepicker._hideDatepicker();
7119				else if ($.datepicker._datepickerShowing && $.datepicker._lastInput != input[0]) {
7120					$.datepicker._hideDatepicker(); 
7121					$.datepicker._showDatepicker(input[0]);
7122				} else
7123					$.datepicker._showDatepicker(input[0]);
7124				return false;
7125			});
7126		}
7127	},
7128
7129	/* Apply the maximum length for the date format. */
7130	_autoSize: function(inst) {
7131		if (this._get(inst, 'autoSize') && !inst.inline) {
7132			var date = new Date(2009, 12 - 1, 20); // Ensure double digits
7133			var dateFormat = this._get(inst, 'dateFormat');
7134			if (dateFormat.match(/[DM]/)) {
7135				var findMax = function(names) {
7136					var max = 0;
7137					var maxI = 0;
7138					for (var i = 0; i < names.length; i++) {
7139						if (names[i].length > max) {
7140							max = names[i].length;
7141							maxI = i;
7142						}
7143					}
7144					return maxI;
7145				};
7146				date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
7147					'monthNames' : 'monthNamesShort'))));
7148				date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
7149					'dayNames' : 'dayNamesShort'))) + 20 - date.getDay());
7150			}
7151			inst.input.attr('size', this._formatDate(inst, date).length);
7152		}
7153	},
7154
7155	/* Attach an inline date picker to a div. */
7156	_inlineDatepicker: function(target, inst) {
7157		var divSpan = $(target);
7158		if (divSpan.hasClass(this.markerClassName))
7159			return;
7160		divSpan.addClass(this.markerClassName).append(inst.dpDiv).
7161			bind("setData.datepicker", function(event, key, value){
7162				inst.settings[key] = value;
7163			}).bind("getData.datepicker", function(event, key){
7164				return this._get(inst, key);
7165			});
7166		$.data(target, PROP_NAME, inst);
7167		this._setDate(inst, this._getDefaultDate(inst), true);
7168		this._updateDatepicker(inst);
7169		this._updateAlternate(inst);
7170		//If disabled option is true, disable the datepicker before showing it (see ticket #5665)
7171		if( inst.settings.disabled ) {
7172			this._disableDatepicker( target );
7173		}
7174		// Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
7175		// http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
7176		inst.dpDiv.css( "display", "block" );
7177	},
7178
7179	/* Pop-up the date picker in a "dialog" box.
7180	   @param  input     element - ignored
7181	   @param  date      string or Date - the initial date to display
7182	   @param  onSelect  function - the function to call when a date is selected
7183	   @param  settings  object - update the dialog date picker instance's settings (anonymous object)
7184	   @param  pos       int[2] - coordinates for the dialog's position within the screen or
7185	                     event - with x/y coordinates or
7186	                     leave empty for default (screen centre)
7187	   @return the manager object */
7188	_dialogDatepicker: function(input, date, onSelect, settings, pos) {
7189		var inst = this._dialogInst; // internal instance
7190		if (!inst) {
7191			this.uuid += 1;
7192			var id = 'dp' + this.uuid;
7193			this._dialogInput = $('<input type="text" id="' + id +
7194				'" style="position: absolute; top: -100px; width: 0px;"/>');
7195			this._dialogInput.keydown(this._doKeyDown);
7196			$('body').append(this._dialogInput);
7197			inst = this._dialogInst = this._newInst(this._dialogInput, false);
7198			inst.settings = {};
7199			$.data(this._dialogInput[0], PROP_NAME, inst);
7200		}
7201		extendRemove(inst.settings, settings || {});
7202		date = (date && date.constructor == Date ? this._formatDate(inst, date) : date);
7203		this._dialogInput.val(date);
7204
7205		this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
7206		if (!this._pos) {
7207			var browserWidth = document.documentElement.clientWidth;
7208			var browserHeight = document.documentElement.clientHeight;
7209			var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
7210			var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
7211			this._pos = // should use actual width/height below
7212				[(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
7213		}
7214
7215		// move input on screen for focus, but hidden behind dialog
7216		this._dialogInput.css('left', (this._pos[0] + 20) + 'px').css('top', this._pos[1] + 'px');
7217		inst.settings.onSelect = onSelect;
7218		this._inDialog = true;
7219		this.dpDiv.addClass(this._dialogClass);
7220		this._showDatepicker(this._dialogInput[0]);
7221		if ($.blockUI)
7222			$.blockUI(this.dpDiv);
7223		$.data(this._dialogInput[0], PROP_NAME, inst);
7224		return this;
7225	},
7226
7227	/* Detach a datepicker from its control.
7228	   @param  target    element - the target input field or division or span */
7229	_destroyDatepicker: function(target) {
7230		var $target = $(target);
7231		var inst = $.data(target, PROP_NAME);
7232		if (!$target.hasClass(this.markerClassName)) {
7233			return;
7234		}
7235		var nodeName = target.nodeName.toLowerCase();
7236		$.removeData(target, PROP_NAME);
7237		if (nodeName == 'input') {
7238			inst.append.remove();
7239			inst.trigger.remove();
7240			$target.removeClass(this.markerClassName).
7241				unbind('focus', this._showDatepicker).
7242				unbind('keydown', this._doKeyDown).
7243				unbind('keypress', this._doKeyPress).
7244				unbind('keyup', this._doKeyUp);
7245		} else if (nodeName == 'div' || nodeName == 'span')
7246			$target.removeClass(this.markerClassName).empty();
7247	},
7248
7249	/* Enable the date picker to a jQuery selection.
7250	   @param  target    element - the target input field or division or span */
7251	_enableDatepicker: function(target) {
7252		var $target = $(target);
7253		var inst = $.data(target, PROP_NAME);
7254		if (!$target.hasClass(this.markerClassName)) {
7255			return;
7256		}
7257		var nodeName = target.nodeName.toLowerCase();
7258		if (nodeName == 'input') {
7259			target.disabled = false;
7260			inst.trigger.filter('button').
7261				each(function() { this.disabled = false; }).end().
7262				filter('img').css({opacity: '1.0', cursor: ''});
7263		}
7264		else if (nodeName == 'div' || nodeName == 'span') {
7265			var inline = $target.children('.' + this._inlineClass);
7266			inline.children().removeClass('ui-state-disabled');
7267			inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
7268				removeAttr("disabled");
7269		}
7270		this._disabledInputs = $.map(this._disabledInputs,
7271			function(value) { return (value == target ? null : value); }); // delete entry
7272	},
7273
7274	/* Disable the date picker to a jQuery selection.
7275	   @param  target    element - the target input field or division or span */
7276	_disableDatepicker: function(target) {
7277		var $target = $(target);
7278		var inst = $.data(target, PROP_NAME);
7279		if (!$target.hasClass(this.markerClassName)) {
7280			return;
7281		}
7282		var nodeName = target.nodeName.toLowerCase();
7283		if (nodeName == 'input') {
7284			target.disabled = true;
7285			inst.trigger.filter('button').
7286				each(function() { this.disabled = true; }).end().
7287				filter('img').css({opacity: '0.5', cursor: 'default'});
7288		}
7289		else if (nodeName == 'div' || nodeName == 'span') {
7290			var inline = $target.children('.' + this._inlineClass);
7291			inline.children().addClass('ui-state-disabled');
7292			inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
7293				attr("disabled", "disabled");
7294		}
7295		this._disabledInputs = $.map(this._disabledInputs,
7296			function(value) { return (value == target ? null : value); }); // delete entry
7297		this._disabledInputs[this._disabledInputs.length] = target;
7298	},
7299
7300	/* Is the first field in a jQuery collection disabled as a datepicker?
7301	   @param  target    element - the target input field or division or span
7302	   @return boolean - true if disabled, false if enabled */
7303	_isDisabledDatepicker: function(target) {
7304		if (!target) {
7305			return false;
7306		}
7307		for (var i = 0; i < this._disabledInputs.length; i++) {
7308			if (this._disabledInputs[i] == target)
7309				return true;
7310		}
7311		return false;
7312	},
7313
7314	/* Retrieve the instance data for the target control.
7315	   @param  target  element - the target input field or division or span
7316	   @return  object - the associated instance data
7317	   @throws  error if a jQuery problem getting data */
7318	_getInst: function(target) {
7319		try {
7320			return $.data(target, PROP_NAME);
7321		}
7322		catch (err) {
7323			throw 'Missing instance data for this datepicker';
7324		}
7325	},
7326
7327	/* Update or retrieve the settings for a date picker attached to an input field or division.
7328	   @param  target  element - the target input field or division or span
7329	   @param  name    object - the new settings to update or
7330	                   string - the name of the setting to change or retrieve,
7331	                   when retrieving also 'all' for all instance settings or
7332	                   'defaults' for all global defaults
7333	   @param  value   any - the new value for the setting
7334	                   (omit if above is an object or to retrieve a value) */
7335	_optionDatepicker: function(target, name, value) {
7336		var inst = this._getInst(target);
7337		if (arguments.length == 2 && typeof name == 'string') {
7338			return (name == 'defaults' ? $.extend({}, $.datepicker._defaults) :
7339				(inst ? (name == 'all' ? $.extend({}, inst.settings) :
7340				this._get(inst, name)) : null));
7341		}
7342		var settings = name || {};
7343		if (typeof name == 'string') {
7344			settings = {};
7345			settings[name] = value;
7346		}
7347		if (inst) {
7348			if (this._curInst == inst) {
7349				this._hideDatepicker();
7350			}
7351			var date = this._getDateDatepicker(target, true);
7352			var minDate = this._getMinMaxDate(inst, 'min');
7353			var maxDate = this._getMinMaxDate(inst, 'max');
7354			extendRemove(inst.settings, settings);
7355			// reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
7356			if (minDate !== null && settings['dateFormat'] !== undefined && settings['minDate'] === undefined)
7357				inst.settings.minDate = this._formatDate(inst, minDate);
7358			if (maxDate !== null && settings['dateFormat'] !== undefined && settings['maxDate'] === undefined)
7359				inst.settings.maxDate = this._formatDate(inst, maxDate);
7360			this._attachments($(target), inst);
7361			this._autoSize(inst);
7362			this._setDate(inst, date);
7363			this._updateAlternate(inst);
7364			this._updateDatepicker(inst);
7365		}
7366	},
7367
7368	// change method deprecated
7369	_changeDatepicker: function(target, name, value) {
7370		this._optionDatepicker(target, name, value);
7371	},
7372
7373	/* Redraw the date picker attached to an input field or division.
7374	   @param  target  element - the target input field or division or span */
7375	_refreshDatepicker: function(target) {
7376		var inst = this._getInst(target);
7377		if (inst) {
7378			this._updateDatepicker(inst);
7379		}
7380	},
7381
7382	/* Set the dates for a jQuery selection.
7383	   @param  target   element - the target input field or division or span
7384	   @param  date     Date - the new date */
7385	_setDateDatepicker: function(target, date) {
7386		var inst = this._getInst(target);
7387		if (inst) {
7388			this._setDate(inst, date);
7389			this._updateDatepicker(inst);
7390			this._updateAlternate(inst);
7391		}
7392	},
7393
7394	/* Get the date(s) for the first entry in a jQuery selection.
7395	   @param  target     element - the target input field or division or span
7396	   @param  noDefault  boolean - true if no default date is to be used
7397	   @return Date - the current date */
7398	_getDateDatepicker: function(target, noDefault) {
7399		var inst = this._getInst(target);
7400		if (inst && !inst.inline)
7401			this._setDateFromField(inst, noDefault);
7402		return (inst ? this._getDate(inst) : null);
7403	},
7404
7405	/* Handle keystrokes. */
7406	_doKeyDown: function(event) {
7407		var inst = $.datepicker._getInst(event.target);
7408		var handled = true;
7409		var isRTL = inst.dpDiv.is('.ui-datepicker-rtl');
7410		inst._keyEvent = true;
7411		if ($.datepicker._datepickerShowing)
7412			switch (event.keyCode) {
7413				case 9: $.datepicker._hideDatepicker();
7414						handled = false;
7415						break; // hide on tab out
7416				case 13: var sel = $('td.' + $.datepicker._dayOverClass + ':not(.' + 
7417									$.datepicker._currentClass + ')', inst.dpDiv);
7418						if (sel[0])
7419							$.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
7420							var onSelect = $.datepicker._get(inst, 'onSelect');
7421							if (onSelect) {
7422								var dateStr = $.datepicker._formatDate(inst);
7423
7424								// trigger custom callback
7425								onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);
7426							}
7427						else
7428							$.datepicker._hideDatepicker();
7429						return false; // don't submit the form
7430						break; // select the value on enter
7431				case 27: $.datepicker._hideDatepicker();
7432						break; // hide on escape
7433				case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
7434							-$.datepicker._get(inst, 'stepBigMonths') :
7435							-$.datepicker._get(inst, 'stepMonths')), 'M');
7436						break; // previous month/year on page up/+ ctrl
7437				case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
7438							+$.datepicker._get(inst, 'stepBigMonths') :
7439							+$.datepicker._get(inst, 'stepMonths')), 'M');
7440						break; // next month/year on page down/+ ctrl
7441				case 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target);
7442						handled = event.ctrlKey || event.metaKey;
7443						break; // clear on ctrl or command +end
7444				case 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target);
7445						handled = event.ctrlKey || event.metaKey;
7446						break; // current on ctrl or command +home
7447				case 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D');
7448						handled = event.ctrlKey || event.metaKey;
7449						// -1 day on ctrl or command +left
7450						if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
7451									-$.datepicker._get(inst, 'stepBigMonths') :
7452									-$.datepicker._get(inst, 'stepMonths')), 'M');
7453						// next month/year on alt +left on Mac
7454						break;
7455				case 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D');
7456						handled = event.ctrlKey || event.metaKey;
7457						break; // -1 week on ctrl or command +up
7458				case 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D');
7459						handled = event.ctrlKey || event.metaKey;
7460						// +1 day on ctrl or command +right
7461						if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
7462									+$.datepicker._get(inst, 'stepBigMonths') :
7463									+$.datepicker._get(inst, 'stepMonths')), 'M');
7464						// next month/year on alt +right
7465						break;
7466				case 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D');
7467						handled = event.ctrlKey || event.metaKey;
7468						break; // +1 week on ctrl or command +down
7469				default: handled = false;
7470			}
7471		else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home
7472			$.datepicker._showDatepicker(this);
7473		else {
7474			handled = false;
7475		}
7476		if (handled) {
7477			event.preventDefault();
7478			event.stopPropagation();
7479		}
7480	},
7481
7482	/* Filter entered characters - based on date format. */
7483	_doKeyPress: function(event) {
7484		var inst = $.datepicker._getInst(event.target);
7485		if ($.datepicker._get(inst, 'constrainInput')) {
7486			var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat'));
7487			var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode);
7488			return event.ctrlKey || event.metaKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1);
7489		}
7490	},
7491
7492	/* Synchronise manual entry and field/alternate field. */
7493	_doKeyUp: function(event) {
7494		var inst = $.datepicker._getInst(event.target);
7495		if (inst.input.val() != inst.lastVal) {
7496			try {
7497				var date = $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
7498					(inst.input ? inst.input.val() : null),
7499					$.datepicker._getFormatConfig(inst));
7500				if (date) { // only if valid
7501					$.datepicker._setDateFromField(inst);
7502					$.datepicker._updateAlternate(inst);
7503					$.datepicker._updateDatepicker(inst);
7504				}
7505			}
7506			catch (err) {
7507				$.datepicker.log(err);
7508			}
7509		}
7510		return true;
7511	},
7512
7513	/* Pop-up the date picker for a given input field.
7514       If false returned from beforeShow event handler do not show. 
7515	   @param  input  element - the input field attached to the date picker or
7516	                  event - if triggered by focus */
7517	_showDatepicker: function(input) {
7518		input = input.target || input;
7519		if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger
7520			input = $('input', input.parentNode)[0];
7521		if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here
7522			return;
7523		var inst = $.datepicker._getInst(input);
7524		if ($.datepicker._curInst && $.datepicker._curInst != inst) {
7525			$.datepicker._curInst.dpDiv.stop(true, true);
7526			if ( inst && $.datepicker._datepickerShowing ) {
7527				$.datepicker._hideDatepicker( $.datepicker._curInst.input[0] );
7528			}
7529		}
7530		var beforeShow = $.datepicker._get(inst, 'beforeShow');
7531		var beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {};
7532		if(beforeShowSettings === false){
7533            //false
7534			return;
7535		}
7536		extendRemove(inst.settings, beforeShowSettings);
7537		inst.lastVal = null;
7538		$.datepicker._lastInput = input;
7539		$.datepicker._setDateFromField(inst);
7540		if ($.datepicker._inDialog) // hide cursor
7541			input.value = '';
7542		if (!$.datepicker._pos) { // position below input
7543			$.datepicker._pos = $.datepicker._findPos(input);
7544			$.datepicker._pos[1] += input.offsetHeight; // add the height
7545		}
7546		var isFixed = false;
7547		$(input).parents().each(function() {
7548			isFixed |= $(this).css('position') == 'fixed';
7549			return !isFixed;
7550		});
7551		if (isFixed && $.browser.opera) { // correction for Opera when fixed and scrolled
7552			$.datepicker._pos[0] -= document.documentElement.scrollLeft;
7553			$.datepicker._pos[1] -= document.documentElement.scrollTop;
7554		}
7555		var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
7556		$.datepicker._pos = null;
7557		//to avoid flashes on Firefox
7558		inst.dpDiv.empty();
7559		// determine sizing offscreen
7560		inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'});
7561		$.datepicker._updateDatepicker(inst);
7562		// fix width for dynamic number of date pickers
7563		// and adjust position before showing
7564		offset = $.datepicker._checkOffset(inst, offset, isFixed);
7565		inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
7566			'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none',
7567			left: offset.left + 'px', top: offset.top + 'px'});
7568		if (!inst.inline) {
7569			var showAnim = $.datepicker._get(inst, 'showAnim');
7570			var duration = $.datepicker._get(inst, 'duration');
7571			var postProcess = function() {
7572				var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only
7573				if( !! cover.length ){
7574					var borders = $.datepicker._getBorders(inst.dpDiv);
7575					cover.css({left: -borders[0], top: -borders[1],
7576						width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()});
7577				}
7578			};
7579			inst.dpDiv.zIndex($(input).zIndex()+1);
7580			$.datepicker._datepickerShowing = true;
7581			if ($.effects && $.effects[showAnim])
7582				inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
7583			else
7584				inst.dpDiv[showAnim || 'show']((showAnim ? duration : null), postProcess);
7585			if (!showAnim || !duration)
7586				postProcess();
7587			if (inst.input.is(':visible') && !inst.input.is(':disabled'))
7588				inst.input.focus();
7589			$.datepicker._curInst = inst;
7590		}
7591	},
7592
7593	/* Generate the date picker content. */
7594	_updateDatepicker: function(inst) {
7595		var self = this;
7596		self.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
7597		var borders = $.datepicker._getBorders(inst.dpDiv);
7598		instActive = inst; // for delegate hover events
7599		inst.dpDiv.empty().append(this._generateHTML(inst));
7600		this._attachHandlers(inst);
7601		var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only
7602		if( !!cover.length ){ //avoid call to outerXXXX() when not in IE6
7603			cover.css({left: -borders[0], top: -borders[1], width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()})
7604		}
7605		inst.dpDiv.find('.' + this._dayOverClass + ' a').mouseover();
7606		var numMonths = this._getNumberOfMonths(inst);
7607		var cols = numMonths[1];
7608		var width = 17;
7609		inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');
7610		if (cols > 1)
7611			inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em');
7612		inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') +
7613			'Class']('ui-datepicker-multi');
7614		inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') +
7615			'Class']('ui-datepicker-rtl');
7616		if (inst == $.datepicker._curInst && $.datepicker._datepickerShowing && inst.input &&
7617				// #6694 - don't focus the input if it's already focused
7618				// this breaks the change event in IE
7619				inst.input.is(':visible') && !inst.input.is(':disabled') && inst.input[0] != document.activeElement)
7620			inst.input.focus();
7621		// deffered render of the years select (to avoid flashes on Firefox) 
7622		if( inst.yearshtml ){
7623			var origyearshtml = inst.yearshtml;
7624			setTimeout(function(){
7625				//assure that inst.yearshtml didn't change.
7626				if( origyearshtml === inst.yearshtml && inst.yearshtml ){
7627					inst.dpDiv.find('select.ui-datepicker-year:first').replaceWith(inst.yearshtml);
7628				}
7629				origyearshtml = inst.yearshtml = null;
7630			}, 0);
7631		}
7632	},
7633
7634	/* Retrieve the size of left and top borders for an element.
7635	   @param  elem  (jQuery object) the element of interest
7636	   @return  (number[2]) the left and top borders */
7637	_getBorders: function(elem) {
7638		var convert = function(value) {
7639			return {thin: 1, medium: 2, thick: 3}[value] || value;
7640		};
7641		return [parseFloat(convert(elem.css('border-left-width'))),
7642			parseFloat(convert(elem.css('border-top-width')))];
7643	},
7644
7645	/* Check positioning to remain on screen. */
7646	_checkOffset: function(inst, offset, isFixed) {
7647		var dpWidth = inst.dpDiv.outerWidth();
7648		var dpHeight = inst.dpDiv.outerHeight();
7649		var inputWidth = inst.input ? inst.input.outerWidth() : 0;
7650		var inputHeight = inst.input ? inst.input.outerHeight() : 0;
7651		var viewWidth = document.documentElement.clientWidth + (isFixed ? 0 : $(document).scrollLeft());
7652		var viewHeight = document.documentElement.clientHeight + (isFixed ? 0 : $(document).scrollTop());
7653
7654		offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0);
7655		offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0;
7656		offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
7657
7658		// now check if datepicker is showing outside window viewport - move to a better place if so.
7659		offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
7660			Math.abs(offset.left + dpWidth - viewWidth) : 0);
7661		offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
7662			Math.abs(dpHeight + inputHeight) : 0);
7663
7664		return offset;
7665	},
7666
7667	/* Find an object's position on the screen. */
7668	_findPos: function(obj) {
7669		var inst = this._getInst(obj);
7670		var isRTL = this._get(inst, 'isRTL');
7671        while (obj && (obj.type == 'hidden' || obj.nodeType != 1 || $.expr.filters.hidden(obj))) {
7672            obj = obj[isRTL ? 'previousSibling' : 'nextSibling'];
7673        }
7674        var position = $(obj).offset();
7675	    return [position.left, position.top];
7676	},
7677
7678	/* Hide the date picker from view.
7679	   @param  input  element - the input field attached to the date picker */
7680	_hideDatepicker: function(input) {
7681		var inst = this._curInst;
7682		if (!inst || (input && inst != $.data(input, PROP_NAME)))
7683			return;
7684		if (this._datepickerShowing) {
7685			var showAnim = this._get(inst, 'showAnim');
7686			var duration = this._get(inst, 'duration');
7687			var postProcess = function() {
7688				$.datepicker._tidyDialog(inst);
7689			};
7690			if ($.effects && $.effects[showAnim])
7691				inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
7692			else
7693				inst.dpDiv[(showAnim == 'slideDown' ? 'slideUp' :
7694					(showAnim == 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim ? duration : null), postProcess);
7695			if (!showAnim)
7696				postProcess();
7697			this._datepickerShowing = false;
7698			var onClose = this._get(inst, 'onClose');
7699			if (onClose)
7700				onClose.apply((inst.input ? inst.input[0] : null),
7701					[(inst.input ? inst.input.val() : ''), inst]);
7702			this._lastInput = null;
7703			if (this._inDialog) {
7704				this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' });
7705				if ($.blockUI) {
7706					$.unblockUI();
7707					$('body').append(this.dpDiv);
7708				}
7709			}
7710			this._inDialog = false;
7711		}
7712	},
7713
7714	/* Tidy up after a dialog display. */
7715	_tidyDialog: function(inst) {
7716		inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar');
7717	},
7718
7719	/* Close date picker if clicked elsewhere. */
7720	_checkExternalClick: function(event) {
7721		if (!$.datepicker._curInst)
7722			return;
7723
7724		var $target = $(event.target),
7725			inst = $.datepicker._getInst($target[0]);
7726
7727		if ( ( ( $target[0].id != $.datepicker._mainDivId &&
7728				$target.parents('#' + $.datepicker._mainDivId).length == 0 &&
7729				!$target.hasClass($.datepicker.markerClassName) &&
7730				!$target.closest("." + $.datepicker._triggerClass).length &&
7731				$.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI) ) ) ||
7732			( $target.hasClass($.datepicker.markerClassName) && $.datepicker._curInst != inst ) )
7733			$.datepicker._hideDatepicker();
7734	},
7735
7736	/* Adjust one of the date sub-fields. */
7737	_adjustDate: function(id, offset, period) {
7738		var target = $(id);
7739		var inst = this._getInst(target[0]);
7740		if (this._isDisabledDatepicker(target[0])) {
7741			return;
7742		}
7743		this._adjustInstDate(inst, offset +
7744			(period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning
7745			period);
7746		this._updateDatepicker(inst);
7747	},
7748
7749	/* Action for current link. */
7750	_gotoToday: function(id) {
7751		var target = $(id);
7752		var inst = this._getInst(target[0]);
7753		if (this._get(inst, 'gotoCurrent') && inst.currentDay) {
7754			inst.selectedDay = inst.currentDay;
7755			inst.drawMonth = inst.selectedMonth = inst.currentMonth;
7756			inst.drawYear = inst.selectedYear = inst.currentYear;
7757		}
7758		else {
7759			var date = new Date();
7760			inst.selectedDay = date.getDate();
7761			inst.drawMonth = inst.selectedMonth = date.getMonth();
7762			inst.drawYear = inst.selectedYear = date.getFullYear();
7763		}
7764		this._notifyChange(inst);
7765		this._adjustDate(target);
7766	},
7767
7768	/* Action for selecting a new month/year. */
7769	_selectMonthYear: function(id, select, period) {
7770		var target = $(id);
7771		var inst = this._getInst(target[0]);
7772		inst['selected' + (period == 'M' ? 'Month' : 'Year')] =
7773		inst['draw' + (period == 'M' ? 'Month' : 'Year')] =
7774			parseInt(select.options[select.selectedIndex].value,10);
7775		this._notifyChange(inst);
7776		this._adjustDate(target);
7777	},
7778
7779	/* Action for selecting a day. */
7780	_selectDay: function(id, month, year, td) {
7781		var target = $(id);
7782		if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
7783			return;
7784		}
7785		var inst = this._getInst(target[0]);
7786		inst.selectedDay = inst.currentDay = $('a', td).html();
7787		inst.selectedMonth = inst.currentMonth = month;
7788		inst.selectedYear = inst.currentYear = year;
7789		this._selectDate(id, this._formatDate(inst,
7790			inst.currentDay, inst.currentMonth, inst.currentYear));
7791	},
7792
7793	/* Erase the input field and hide the date picker. */
7794	_clearDate: function(id) {
7795		var target = $(id);
7796		var inst = this._getInst(target[0]);
7797		this._selectDate(target, '');
7798	},
7799
7800	/* Update the input field with the selected date. */
7801	_selectDate: function(id, dateStr) {
7802		var target = $(id);
7803		var inst = this._getInst(target[0]);
7804		dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
7805		if (inst.input)
7806			inst.input.val(dateStr);
7807		this._updateAlternate(inst);
7808		var onSelect = this._get(inst, 'onSelect');
7809		if (onSelect)
7810			onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);  // trigger custom callback
7811		else if (inst.input)
7812			inst.input.trigger('change'); // fire the change event
7813		if (inst.inline)
7814			this._updateDatepicker(inst);
7815		else {
7816			this._hideDatepicker();
7817			this._lastInput = inst.input[0];
7818			if (typeof(inst.input[0]) != 'object')
7819				inst.input.focus(); // restore focus
7820			this._lastInput = null;
7821		}
7822	},
7823
7824	/* Update any alternate field to synchronise with the main field. */
7825	_updateAlternate: function(inst) {
7826		var altField = this._get(inst, 'altField');
7827		if (altField) { // update alternate field too
7828			var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat');
7829			var date = this._getDate(inst);
7830			var dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
7831			$(altField).each(function() { $(this).val(dateStr); });
7832		}
7833	},
7834
7835	/* Set as beforeShowDay function to prevent selection of weekends.
7836	   @param  date  Date - the date to customise
7837	   @return [boolean, string] - is this date selectable?, what is its CSS class? */
7838	noWeekends: function(date) {
7839		var day = date.getDay();
7840		return [(day > 0 && day < 6), ''];
7841	},
7842
7843	/* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
7844	   @param  date  Date - the date to get the week for
7845	   @return  number - the number of the week within the year that contains this date */
7846	iso8601Week: function(date) {
7847		var checkDate = new Date(date.getTime());
7848		// Find Thursday of this week starting on Monday
7849		checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
7850		var time = checkDate.getTime();
7851		checkDate.setMonth(0); // Compare with Jan 1
7852		checkDate.setDate(1);
7853		return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
7854	},
7855
7856	/* Parse a string value into a date object.
7857	   See formatDate below for the possible formats.
7858
7859	   @param  format    string - the expected format of the date
7860	   @param  value     string - the date in the above format
7861	   @param  settings  Object - attributes include:
7862	                     shortYearCutoff  number - the cutoff year for determining the century (optional)
7863	                     dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)
7864	                     dayNames         string[7] - names of the days from Sunday (optional)
7865	                     monthNamesShort  string[12] - abbreviated names of the months (optional)
7866	                     monthNames       string[12] - names of the months (optional)
7867	   @return  Date - the extracted date value or null if value is blank */
7868	parseDate: function (format, value, settings) {
7869		if (format == null || value == null)
7870			throw 'Invalid arguments';
7871		value = (typeof value == 'object' ? value.toString() : value + '');
7872		if (value == '')
7873			return null;
7874		var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff;
7875		shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
7876				new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
7877		var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
7878		var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
7879		var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
7880		var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
7881		var year = -1;
7882		var month = -1;
7883		var day = -1;
7884		var doy = -1;
7885		var literal = false;
7886		// Check whether a format character is doubled
7887		var lookAhead = function(match) {
7888			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
7889			if (matches)
7890				iFormat++;
7891			return matches;
7892		};
7893		// Extract a number from the string value
7894		var getNumber = function(match) {
7895			var isDoubled = lookAhead(match);
7896			var size = (match == '@' ? 14 : (match == '!' ? 20 :
7897				(match == 'y' && isDoubled ? 4 : (match == 'o' ? 3 : 2))));
7898			var digits = new RegExp('^\\d{1,' + size + '}');
7899			var num = value.substring(iValue).match(digits);
7900			if (!num)
7901				throw 'Missing number at position ' + iValue;
7902			iValue += num[0].length;
7903			return parseInt(num[0], 10);
7904		};
7905		// Extract a name from the string value and convert to an index
7906		var getName = function(match, shortNames, longNames) {
7907			var names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) {
7908				return [ [k, v] ];
7909			}).sort(function (a, b) {
7910				return -(a[1].length - b[1].length);
7911			});
7912			var index = -1;
7913			$.each(names, function (i, pair) {
7914				var name = pair[1];
7915				if (value.substr(iValue, name.length).toLowerCase() == name.toLowerCase()) {
7916					index = pair[0];
7917					iValue += name.length;
7918					return false;
7919				}
7920			});
7921			if (index != -1)
7922				return index + 1;
7923			else
7924				throw 'Unknown name at position ' + iValue;
7925		};
7926		// Confirm that a literal character matches the string value
7927		var checkLiteral = function() {
7928			if (value.charAt(iValue) != format.charAt(iFormat))
7929				throw 'Unexpected literal at position ' + iValue;
7930			iValue++;
7931		};
7932		var iValue = 0;
7933		for (var iFormat = 0; iFormat < format.length; iFormat++) {
7934			if (literal)
7935				if (format.charAt(iFormat) == "'" && !lookAhead("'"))
7936					literal = false;
7937				else
7938					checkLiteral();
7939			else
7940				switch (format.charAt(iFormat)) {
7941					case 'd':
7942						day = getNumber('d');
7943						break;
7944					case 'D':
7945						getName('D', dayNamesShort, dayNames);
7946						break;
7947					case 'o':
7948						doy = getNumber('o');
7949						break;
7950					case 'm':
7951						month = getNumber('m');
7952						break;
7953					case 'M':
7954						month = getName('M', monthNamesShort, monthNames);
7955						break;
7956					case 'y':
7957						year = getNumber('y');
7958						break;
7959					case '@':
7960						var date = new Date(getNumber('@'));
7961						year = date.getFullYear();
7962						month = date.getMonth() + 1;
7963						day = date.getDate();
7964						break;
7965					case '!':
7966						var date = new Date((getNumber('!') - this._ticksTo1970) / 10000);
7967						year = date.getFullYear();
7968						month = date.getMonth() + 1;
7969						day = date.getDate();
7970						break;
7971					case "'":
7972						if (lookAhead("'"))
7973							checkLiteral();
7974						else
7975							literal = true;
7976						break;
7977					default:
7978						checkLiteral();
7979				}
7980		}
7981		if (iValue < value.length){
7982			throw "Extra/unparsed characters found in date: " + value.substring(iValue);
7983		}
7984		if (year == -1)
7985			year = new Date().getFullYear();
7986		else if (year < 100)
7987			year += new Date().getFullYear() - new Date().getFullYear() % 100 +
7988				(year <= shortYearCutoff ? 0 : -100);
7989		if (doy > -1) {
7990			month = 1;
7991			day = doy;
7992			do {
7993				var dim = this._getDaysInMonth(year, month - 1);
7994				if (day <= dim)
7995					break;
7996				month++;
7997				day -= dim;
7998			} while (true);
7999		}
8000		var date = this._daylightSavingAdjust(new Date(year, month - 1, day));
8001		if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day)
8002			throw 'Invalid date'; // E.g. 31/02/00
8003		return date;
8004	},
8005
8006	/* Standard date formats. */
8007	ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601)
8008	COOKIE: 'D, dd M yy',
8009	ISO_8601: 'yy-mm-dd',
8010	RFC_822: 'D, d M y',
8011	RFC_850: 'DD, dd-M-y',
8012	RFC_1036: 'D, d M y',
8013	RFC_1123: 'D, d M yy',
8014	RFC_2822: 'D, d M yy',
8015	RSS: 'D, d M y', // RFC 822
8016	TICKS: '!',
8017	TIMESTAMP: '@',
8018	W3C: 'yy-mm-dd', // ISO 8601
8019
8020	_ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
8021		Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
8022
8023	/* Format a date object into a string value.
8024	   The format can be combinations of the following:
8025	   d  - day of month (no leading zero)
8026	   dd - day of month (two digit)
8027	   o  - day of year (no leading zeros)
8028	   oo - day of year (three digit)
8029	   D  - day name short
8030	   DD - day name long
8031	   m  - month of year (no leading zero)
8032	   mm - month of year (two digit)
8033	   M  - month name short
8034	   MM - month name long
8035	   y  - year (two digit)
8036	   yy - year (four digit)
8037	   @ - Unix timestamp (ms since 01/01/1970)
8038	   ! - Windows ticks (100ns since 01/01/0001)
8039	   '...' - literal text
8040	   '' - single quote
8041
8042	   @param  format    string - the desired format of the date
8043	   @param  date      Date - the date value to format
8044	   @param  settings  Object - attributes include:
8045	                     dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)
8046	                     dayNames         string[7] - names of the days from Sunday (optional)
8047	                     monthNamesShort  string[12] - abbreviated names of the months (optional)
8048	                     monthNames       string[12] - names of the months (optional)
8049	   @return  string - the date in the above format */
8050	formatDate: function (format, date, settings) {
8051		if (!date)
8052			return '';
8053		var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
8054		var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
8055		var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
8056		var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
8057		// Check whether a format character is doubled
8058		var lookAhead = function(match) {
8059			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
8060			if (matches)
8061				iFormat++;
8062			return matches;
8063		};
8064		// Format a number, with leading zero if necessary
8065		var formatNumber = function(match, value, len) {
8066			var num = '' + value;
8067			if (lookAhead(match))
8068				while (num.length < len)
8069					num = '0' + num;
8070			return num;
8071		};
8072		// Format a name, short or long as requested
8073		var formatName = function(match, value, shortNames, longNames) {
8074			return (lookAhead(match) ? longNames[value] : shortNames[value]);
8075		};
8076		var output = '';
8077		var literal = false;
8078		if (date)
8079			for (var iFormat = 0; iFormat < format.length; iFormat++) {
8080				if (literal)
8081					if (format.charAt(iFormat) == "'" && !lookAhead("'"))
8082						literal = false;
8083					else
8084						output += format.charAt(iFormat);
8085				else
8086					switch (format.charAt(iFormat)) {
8087						case 'd':
8088							output += formatNumber('d', date.getDate(), 2);
8089							break;
8090						case 'D':
8091							output += formatName('D', date.getDay(), dayNamesShort, dayNames);
8092							break;
8093						case 'o':
8094							output += formatNumber('o',
8095								Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3);
8096							break;
8097						case 'm':
8098							output += formatNumber('m', date.getMonth() + 1, 2);
8099							break;
8100						case 'M':
8101							output += formatName('M', date.getMonth(), monthNamesShort, monthNames);
8102							break;
8103						case 'y':
8104							output += (lookAhead('y') ? date.getFullYear() :
8105								(date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);
8106							break;
8107						case '@':
8108							output += date.getTime();
8109							break;
8110						case '!':
8111							output += date.getTime() * 10000 + this._ticksTo1970;
8112							break;
8113						case "'":
8114							if (lookAhead("'"))
8115								output += "'";
8116							else
8117								literal = true;
8118							break;
8119						default:
8120							output += format.charAt(iFormat);
8121					}
8122			}
8123		return output;
8124	},
8125
8126	/* Extract all possible characters from the date format. */
8127	_possibleChars: function (format) {
8128		var chars = '';
8129		var literal = false;
8130		// Check whether a format character is doubled
8131		var lookAhead = function(match) {
8132			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
8133			if (matches)
8134				iFormat++;
8135			return matches;
8136		};
8137		for (var iFormat = 0; iFormat < format.length; iFormat++)
8138			if (literal)
8139				if (format.charAt(iFormat) == "'" && !lookAhead("'"))
8140					literal = false;
8141				else
8142					chars += format.charAt(iFormat);
8143			else
8144				switch (format.charAt(iFormat)) {
8145					case 'd': case 'm': case 'y': case '@':
8146						chars += '0123456789';
8147						break;
8148					case 'D': case 'M':
8149						return null; // Accept anything
8150					case "'":
8151						if (lookAhead("'"))
8152							chars += "'";
8153						else
8154							literal = true;
8155						break;
8156					default:
8157						chars += format.charAt(iFormat);
8158				}
8159		return chars;
8160	},
8161
8162	/* Get a setting value, defaulting if necessary. */
8163	_get: function(inst, name) {
8164		return inst.settings[name] !== undefined ?
8165			inst.settings[name] : this._defaults[name];
8166	},
8167
8168	/* Parse existing date and initialise date picker. */
8169	_setDateFromField: function(inst, noDefault) {
8170		if (inst.input.val() == inst.lastVal) {
8171			return;
8172		}
8173		var dateFormat = this._get(inst, 'dateFormat');
8174		var dates = inst.lastVal = inst.input ? inst.input.val() : null;
8175		var date, defaultDate;
8176		date = defaultDate = this._getDefaultDate(inst);
8177		var settings = this._getFormatConfig(inst);
8178		try {
8179			date = this.parseDate(dateFormat, dates, settings) || defaultDate;
8180		} catch (event) {
8181			this.log(event);
8182			dates = (noDefault ? '' : dates);
8183		}
8184		inst.selectedDay = date.getDate();
8185		inst.drawMonth = inst.selectedMonth = date.getMonth();
8186		inst.drawYear = inst.selectedYear = date.getFullYear();
8187		inst.currentDay = (dates ? date.getDate() : 0);
8188		inst.currentMonth = (dates ? date.getMonth() : 0);
8189		inst.currentYear = (dates ? date.getFullYear() : 0);
8190		this._adjustInstDate(inst);
8191	},
8192
8193	/* Retrieve the default date shown on opening. */
8194	_getDefaultDate: function(inst) {
8195		return this._restrictMinMax(inst,
8196			this._determineDate(inst, this._get(inst, 'defaultDate'), new Date()));
8197	},
8198
8199	/* A date may be specified as an exact value or a relative one. */
8200	_determineDate: function(inst, date, defaultDate) {
8201		var offsetNumeric = function(offset) {
8202			var date = new Date();
8203			date.setDate(date.getDate() + offset);
8204			return date;
8205		};
8206		var offsetString = function(offset) {
8207			try {
8208				return $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
8209					offset, $.datepicker._getFormatConfig(inst));
8210			}
8211			catch (e) {
8212				// Ignore
8213			}
8214			var date = (offset.toLowerCase().match(/^c/) ?
8215				$.datepicker._getDate(inst) : null) || new Date();
8216			var year = date.getFullYear();
8217			var month = date.getMonth();
8218			var day = date.getDate();
8219			var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;
8220			var matches = pattern.exec(offset);
8221			while (matches) {
8222				switch (matches[2] || 'd') {
8223					case 'd' : case 'D' :
8224						day += parseInt(matches[1],10); break;
8225					case 'w' : case 'W' :
8226						day += parseInt(matches[1],10) * 7; break;
8227					case 'm' : case 'M' :
8228						month += parseInt(matches[1],10);
8229						day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
8230						break;
8231					case 'y': case 'Y' :
8232						year += parseInt(matches[1],10);
8233						day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
8234						break;
8235				}
8236				matches = pattern.exec(offset);
8237			}
8238			return new Date(year, month, day);
8239		};
8240		var newDate = (date == null || date === '' ? defaultDate : (typeof date == 'string' ? offsetString(date) :
8241			(typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime()))));
8242		newDate = (newDate && newDate.toString() == 'Invalid Date' ? defaultDate : newDate);
8243		if (newDate) {
8244			newDate.setHours(0);
8245			newDate.setMinutes(0);
8246			newDate.setSeconds(0);
8247			newDate.setMilliseconds(0);
8248		}
8249		return this._daylightSavingAdjust(newDate);
8250	},
8251
8252	/* Handle switch to/from daylight saving.
8253	   Hours may be non-zero on daylight saving cut-over:
8254	   > 12 when midnight changeover, but then cannot generate
8255	   midnight datetime, so jump to 1AM, otherwise reset.
8256	   @param  date  (Date) the date to check
8257	   @return  (Date) the corrected date */
8258	_daylightSavingAdjust: function(date) {
8259		if (!date) return null;
8260		date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
8261		return date;
8262	},
8263
8264	/* Set the date(s) directly. */
8265	_setDate: function(inst, date, noChange) {
8266		var clear = !date;
8267		var origMonth = inst.selectedMonth;
8268		var origYear = inst.selectedYear;
8269		var newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
8270		inst.selectedDay = inst.currentDay = newDate.getDate();
8271		inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
8272		inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
8273		if ((origMonth != inst.selectedMonth || origYear != inst.selectedYear) && !noChange)
8274			this._notifyChange(inst);
8275		this._adjustInstDate(inst);
8276		if (inst.input) {
8277			inst.input.val(clear ? '' : this._formatDate(inst));
8278		}
8279	},
8280
8281	/* Retrieve the date(s) directly. */
8282	_getDate: function(inst) {
8283		var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null :
8284			this._daylightSavingAdjust(new Date(
8285			inst.currentYear, inst.currentMonth, inst.currentDay)));
8286			return startDate;
8287	},
8288
8289	/* Attach the onxxx handlers.  These are declared statically so
8290	 * they work with static code transformers like Caja.
8291	 */
8292	_attachHandlers: function(inst) {
8293		var stepMonths = this._get(inst, 'stepMonths');
8294		var id = '#' + inst.id.replace( /\\\\/g, "\\" );
8295		inst.dpDiv.find('[data-handler]').map(function () {
8296			var handler = {
8297				prev: function () {
8298					window['DP_jQuery_' + dpuuid].datepicker._adjustDate(id, -stepMonths, 'M');
8299				},
8300				next: function () {
8301					window['DP_jQuery_' + dpuuid].datepicker._adjustDate(id, +stepMonths, 'M');
8302				},
8303				hide: function () {
8304					window['DP_jQuery_' + dpuuid].datepicker._hideDatepicker();
8305				},
8306				today: function () {
8307					window['DP_jQuery_' + dpuuid].datepicker._gotoToday(id);
8308				},
8309				selectDay: function () {
8310					window['DP_jQuery_' + dpuuid].datepicker._selectDay(id, +this.getAttribute('data-month'), +this.getAttribute('data-year'), this);
8311					return false;
8312				},
8313				selectMonth: function () {
8314					window['DP_jQuery_' + dpuuid].datepicker._selectMonthYear(id, this, 'M');
8315					return false;
8316				},
8317				selectYear: function () {
8318					window['DP_jQuery_' + dpuuid].datepicker._selectMonthYear(id, this, 'Y');
8319					return false;
8320				}
8321			};
8322			$(this).bind(this.getAttribute('data-event'), handler[this.getAttribute('data-handler')]);
8323		});
8324	},
8325	
8326	/* Generate the HTML for the current state of the date picker. */
8327	_generateHTML: function(inst) {
8328		var today = new Date();
8329		today = this._daylightSavingAdjust(
8330			new Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time
8331		var isRTL = this._get(inst, 'isRTL');
8332		var showButtonPanel = this._get(inst, 'showButtonPanel');
8333		var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext');
8334		var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat');
8335		var numMonths = this._getNumberOfMonths(inst);
8336		var showCurrentAtPos = this._get(inst, 'showCurrentAtPos');
8337		var stepMonths = this._get(inst, 'stepMonths');
8338		var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1);
8339		var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
8340			new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
8341		var minDate = this._getMinMaxDate(inst, 'min');
8342		var maxDate = this._getMinMaxDate(inst, 'max');
8343		var drawMonth = inst.drawMonth - showCurrentAtPos;
8344		var drawYear = inst.drawYear;
8345		if (drawMonth < 0) {
8346			drawMonth += 12;
8347			drawYear--;
8348		}
8349		if (maxDate) {
8350			var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
8351				maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
8352			maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
8353			while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
8354				drawMonth--;
8355				if (drawMonth < 0) {
8356					drawMonth = 11;
8357					drawYear--;
8358				}
8359			}
8360		}
8361		inst.drawMonth = drawMonth;
8362		inst.drawYear = drawYear;
8363		var prevText = this._get(inst, 'prevText');
8364		prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
8365			this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
8366			this._getFormatConfig(inst)));
8367		var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
8368			'<a class="ui-datepicker-prev ui-corner-all" data-handler="prev" data-event="click"' +
8369			' title="' + prevText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>' :
8370			(hideIfNoPrevNext ? '' : '<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+ prevText +'"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>'));
8371		var nextText = this._get(inst, 'nextText');
8372		nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
8373			this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
8374			this._getFormatConfig(inst)));
8375		var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
8376			'<a class="ui-datepicker-next ui-corner-all" data-handler="next" data-event="click"' +
8377			' title="' + nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>' :
8378			(hideIfNoPrevNext ? '' : '<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+ nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>'));
8379		var currentText = this._get(inst, 'currentText');
8380		var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today);
8381		currentText = (!navigationAsDateFormat ? currentText :
8382			this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
8383		var controls = (!inst.inline ? '<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" data-handler="hide" data-event="click">' +
8384			this._get(inst, 'closeText') + '</button>' : '');
8385		var buttonPanel = (showButtonPanel) ? '<div class="ui-datepicker-buttonpane ui-widget-content">' + (isRTL ? controls : '') +
8386			(this._isInRange(inst, gotoDate) ? '<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" data-handler="today" data-event="click"' +
8387			'>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : '';
8388		var firstDay = parseInt(this._get(inst, 'firstDay'),10);
8389		firstDay = (isNaN(firstDay) ? 0 : firstDay);
8390		var showWeek = this._get(inst, 'showWeek');
8391		var dayNames = this._get(inst, 'dayNames');
8392		var dayNamesShort = this._get(inst, 'dayNamesShort');
8393		var dayNamesMin = this._get(inst, 'dayNamesMin');
8394		var monthNames = this._get(inst, 'monthNames');
8395		var monthNamesShort = this._get(inst, 'monthNamesShort');
8396		var beforeShowDay = this._get(inst, 'beforeShowDay');
8397		var showOtherMonths = this._get(inst, 'showOtherMonths');
8398		var selectOtherMonths = this._get(inst, 'selectOtherMonths');
8399		var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week;
8400		var defaultDate = this._getDefaultDate(inst);
8401		var html = '';
8402		for (var row = 0; row < numMonths[0]; row++) {
8403			var group = '';
8404			this.maxRows = 4;
8405			for (var col = 0; col < numMonths[1]; col++) {
8406				var selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
8407				var cornerClass = ' ui-corner-all';
8408				var calender = '';
8409				if (isMultiMonth) {
8410					calender += '<div class="ui-datepicker-group';
8411					if (numMonths[1] > 1)
8412						switch (col) {
8413							case 0: calender += ' ui-datepicker-group-first';
8414								cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left'); break;
8415							case numMonths[1]-1: calender += ' ui-datepicker-group-last';
8416								cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right'); break;
8417							default: calender += ' ui-datepicker-group-middle'; cornerClass = ''; break;
8418						}
8419					calender += '">';
8420				}
8421				calender += '<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix' + cornerClass + '">' +
8422					(/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') +
8423					(/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') +
8424					this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
8425					row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
8426					'</div><table class="ui-datepicker-calendar"><thead>' +
8427					'<tr>';
8428				var thead = (showWeek ? '<th class="ui-datepicker-week-col">' + this._get(inst, 'weekHeader') + '</th>' : '');
8429				for (var dow = 0; dow < 7; dow++) { // days of the week
8430					var day = (dow + firstDay) % 7;
8431					thead += '<th' + ((dow + firstDay + 6) % 7 >= 5 ? ' class="ui-datepicker-week-end"' : '') + '>
8431' +
8432						'<span title="' + dayNames[day] + '">' + dayNamesMin[day] + '</span></th>';
8433				}
8434				calender += thead + '</tr></thead><tbody>';
8435				var daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
8436				if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth)
8437					inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
8438				var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
8439				var curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate
8440				var numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043)
8441				this.maxRows = numRows;
8442				var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
8443				for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows
8444					calender += '<tr>';
8445					var tbody = (!showWeek ? '' : '<td class="ui-datepicker-week-col">' +
8446						this._get(inst, 'calculateWeek')(printDate) + '</td>');
8447					for (var dow = 0; dow < 7; dow++) { // create date picker days
8448						var daySettings = (beforeShowDay ?
8449							beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']);
8450						var otherMonth = (printDate.getMonth() != drawMonth);
8451						var unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
8452							(minDate && printDate < minDate) || (maxDate && printDate > maxDate);
8453						tbody += '<td class="' +
8454							((dow + firstDay + 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends
8455							(otherMonth ? ' ui-datepicker-other-month' : '') + // highlight days from other months
8456							((printDate.getTime() == selectedDate.getTime() && drawMonth == inst.selectedMonth && inst._keyEvent) || // user pressed key
8457							(defaultDate.getTime() == printDate.getTime() && defaultDate.getTime() == selectedDate.getTime()) ?
8458							// or defaultDate is current printedDate and defaultDate is selectedDate
8459							' ' + this._dayOverClass : '') + // highlight selected day
8460							(unselectable ? ' ' + this._unselectableClass + ' ui-state-disabled': '') +  // highlight unselectable days
8461							(otherMonth && !showOtherMonths ? '' : ' ' + daySettings[1] + // highlight custom dates
8462							(printDate.getTime() == currentDate.getTime() ? ' ' + this._currentClass : '') + // highlight selected day
8463							(printDate.getTime() == today.getTime() ? ' ui-datepicker-today' : '')) + '"' + // highlight today (if different)
8464							((!otherMonth || showOtherMonths) && daySettings[2] ? ' title="' + daySettings[2] + '"' : '') + // cell title
8465							(unselectable ? '' : ' data-handler="selectDay" data-event="click" data-month="' + printDate.getMonth() + '" data-year="' + printDate.getFullYear() + '"') + '>' + // actions
8466							(otherMonth && !showOtherMonths ? '&#xa0;' : // display for other months
8467							(unselectable ? '<span class="ui-state-default">' + printDate.getDate() + '</span>' : '<a class="ui-state-default' +
8468							(printDate.getTime() == today.getTime() ? ' ui-state-highlight' : '') +
8469							(printDate.getTime() == currentDate.getTime() ? ' ui-state-active' : '') + // highlight selected day
8470							(otherMonth ? ' ui-priority-secondary' : '') + // distinguish dates from other months
8471							'" href="#">' + printDate.getDate() + '</a>')) + '</td>'; // display selectable date
8472						printDate.setDate(printDate.getDate() + 1);
8473						printDate = this._daylightSavingAdjust(printDate);
8474					}
8475					calender += tbody + '</tr>';
8476				}
8477				drawMonth++;
8478				if (drawMonth > 11) {
8479					drawMonth = 0;
8480					drawYear++;
8481				}
8482				calender += '</tbody></table>' + (isMultiMonth ? '</div>' + 
8483							((numMonths[0] > 0 && col == numMonths[1]-1) ? '<div class="ui-datepicker-row-break"></div>' : '') : '');
8484				group += calender;
8485			}
8486			html += group;
8487		}
8488		html += buttonPanel + ($.browser.msie && parseInt($.browser.version,10) < 7 && !inst.inline ?
8489			'<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>' : '');
8490		inst._keyEvent = false;
8491		return html;
8492	},
8493
8494	/* Generate the month and year header. */
8495	_generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
8496			secondary, monthNames, monthNamesShort) {
8497		var changeMonth = this._get(inst, 'changeMonth');
8498		var changeYear = this._get(inst, 'changeYear');
8499		var showMonthAfterYear = this._get(inst, 'showMonthAfterYear');
8500		var html = '<div class="ui-datepicker-title">';
8501		var monthHtml = '';
8502		// month selection
8503		if (secondary || !changeMonth)
8504			monthHtml += '<span class="ui-datepicker-month">' + monthNames[drawMonth] + '</span>';
8505		else {
8506			var inMinYear = (minDate && minDate.getFullYear() == drawYear);
8507			var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear);
8508			monthHtml += '<select class="ui-datepicker-month" data-handler="selectMonth" data-event="change">';
8509			for (var month = 0; month < 12; month++) {
8510				if ((!inMinYear || month >= minDate.getMonth()) &&
8511						(!inMaxYear || month <= maxDate.getMonth()))
8512					monthHtml += '<option value="' + month + '"' +
8513						(month == drawMonth ? ' selected="selected"' : '') +
8514						'>' + monthNamesShort[month] + '</option>';
8515			}
8516			monthHtml += '</select>';
8517		}
8518		if (!showMonthAfterYear)
8519			html += monthHtml + (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '');
8520		// year selection
8521		if ( !inst.yearshtml ) {
8522			inst.yearshtml = '';
8523			if (secondary || !changeYear)
8524				html += '<span class="ui-datepicker-year">' + drawYear + '</span>';
8525			else {
8526				// determine range of years to display
8527				var years = this._get(inst, 'yearRange').split(':');
8528				var thisYear = new Date().getFullYear();
8529				var determineYear = function(value) {
8530					var year = (value.match(/c[+-].*/) ? drawYear + parseInt(value.substring(1), 10) :
8531						(value.match(/[+-].*/) ? thisYear + parseInt(value, 10) :
8532						parseInt(value, 10)));
8533					return (isNaN(year) ? thisYear : year);
8534				};
8535				var year = determineYear(years[0]);
8536				var endYear = Math.max(year, determineYear(years[1] || ''));
8537				year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
8538				endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
8539				inst.yearshtml += '<select class="ui-datepicker-year" data-handler="selectYear" data-event="change">';
8540				for (; year <= endYear; year++) {
8541					inst.yearshtml += '<option value="' + year + '"' +
8542						(year == drawYear ? ' selected="selected"' : '') +
8543						'>' + year + '</option>';
8544				}
8545				inst.yearshtml += '</select>';
8546				
8547				html += inst.yearshtml;
8548				inst.yearshtml = null;
8549			}
8550		}
8551		html += this._get(inst, 'yearSuffix');
8552		if (showMonthAfterYear)
8553			html += (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '') + monthHtml;
8554		html += '</div>'; // Close datepicker_header
8555		return html;
8556	},
8557
8558	/* Adjust one of the date sub-fields. */
8559	_adjustInstDate: function(inst, offset, period) {
8560		var year = inst.drawYear + (period == 'Y' ? offset : 0);
8561		var month = inst.drawMonth + (period == 'M' ? offset : 0);
8562		var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) +
8563			(period == 'D' ? offset : 0);
8564		var date = this._restrictMinMax(inst,
8565			this._daylightSavingAdjust(new Date(year, month, day)));
8566		inst.selectedDay = date.getDate();
8567		inst.drawMonth = inst.selectedMonth = date.getMonth();
8568		inst.drawYear = inst.selectedYear = date.getFullYear();
8569		if (period == 'M' || period == 'Y')
8570			this._notifyChange(inst);
8571	},
8572
8573	/* Ensure a date is within any min/max bounds. */
8574	_restrictMinMax: function(inst, date) {
8575		var minDate = this._getMinMaxDate(inst, 'min');
8576		var maxDate = this._getMinMaxDate(inst, 'max');
8577		var newDate = (minDate && date < minDate ? minDate : date);
8578		newDate = (maxDate && newDate > maxDate ? maxDate : newDate);
8579		return newDate;
8580	},
8581
8582	/* Notify change of month/year. */
8583	_notifyChange: function(inst) {
8584		var onChange = this._get(inst, 'onChangeMonthYear');
8585		if (onChange)
8586			onChange.apply((inst.input ? inst.input[0] : null),
8587				[inst.selectedYear, inst.selectedMonth + 1, inst]);
8588	},
8589
8590	/* Determine the number of months to show. */
8591	_getNumberOfMonths: function(inst) {
8592		var numMonths = this._get(inst, 'numberOfMonths');
8593		return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths));
8594	},
8595
8596	/* Determine the current maximum date - ensure no time components are set. */
8597	_getMinMaxDate: function(inst, minMax) {
8598		return this._determineDate(inst, this._get(inst, minMax + 'Date'), null);
8599	},
8600
8601	/* Find the number of days in a given month. */
8602	_getDaysInMonth: function(year, month) {
8603		return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate();
8604	},
8605
8606	/* Find the day of the week of the first of a month. */
8607	_getFirstDayOfMonth: function(year, month) {
8608		return new Date(year, month, 1).getDay();
8609	},
8610
8611	/* Determines if we should allow a "next/prev" month display change. */
8612	_canAdjustMonth: function(inst, offset, curYear, curMonth) {
8613		var numMonths = this._getNumberOfMonths(inst);
8614		var date = this._daylightSavingAdjust(new Date(curYear,
8615			curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
8616		if (offset < 0)
8617			date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
8618		return this._isInRange(inst, date);
8619	},
8620
8621	/* Is the given date in the accepted range? */
8622	_isInRange: function(inst, date) {
8623		var minDate = this._getMinMaxDate(inst, 'min');
8624		var maxDate = this._getMinMaxDate(inst, 'max');
8625		return ((!minDate || date.getTime() >= minDate.getTime()) &&
8626			(!maxDate || date.getTime() <= maxDate.getTime()));
8627	},
8628
8629	/* Provide the configuration settings for formatting/parsing. */
8630	_getFormatConfig: function(inst) {
8631		var shortYearCutoff = this._get(inst, 'shortYearCutoff');
8632		shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
8633			new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
8634		return {shortYearCutoff: shortYearCutoff,
8635			dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'),
8636			monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')};
8637	},
8638
8639	/* Format the given date for display. */
8640	_formatDate: function(inst, day, month, year) {
8641		if (!day) {
8642			inst.currentDay = inst.selectedDay;
8643			inst.currentMonth = inst.selectedMonth;
8644			inst.currentYear = inst.selectedYear;
8645		}
8646		var date = (day ? (typeof day == 'object' ? day :
8647			this._daylightSavingAdjust(new Date(year, month, day))) :
8648			this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
8649		return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst));
8650	}
8651});
8652
8653/*
8654 * Bind hover events for datepicker elements.
8655 * Done via delegate so the binding only occurs once in the lifetime of the parent div.
8656 * Global instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
8657 */ 
8658function bindHover(dpDiv) {
8659	var selector = 'button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a';
8660	return dpDiv.bind('mouseout', function(event) {
8661			var elem = $( event.target ).closest( selector );
8662			if ( !elem.length ) {
8663				return;
8664			}
8665			elem.removeClass( "ui-state-hover ui-datepicker-prev-hover ui-datepicker-next-hover" );
8666		})
8667		.bind('mouseover', function(event) {
8668			var elem = $( event.target ).closest( selector );
8669			if ($.datepicker._isDisabledDatepicker( instActive.inline ? dpDiv.parent()[0] : instActive.input[0]) ||
8670					!elem.length ) {
8671				return;
8672			}
8673			elem.parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover');
8674			elem.addClass('ui-state-hover');
8675			if (elem.hasClass('ui-datepicker-prev')) elem.addClass('ui-datepicker-prev-hover');
8676			if (elem.hasClass('ui-datepicker-next')) elem.addClass('ui-datepicker-next-hover');
8677		});
8678}
8679
8680/* jQuery extend now ignores nulls! */
8681function extendRemove(target, props) {
8682	$.extend(target, props);
8683	for (var name in props)
8684		if (props[name] == null || props[name] == undefined)
8685			target[name] = props[name];
8686	return target;
8687};
8688
8689/* Determine whether an object is an array. */
8690function isArray(a) {
8691	return (a && (($.browser.safari && typeof a == 'object' && a.length) ||
8692		(a.constructor && a.constructor.toString().match(/\Array\(\)/))));
8693};
8694
8695/* Invoke the datepicker functionality.
8696   @param  options  string - a command, optionally followed by additional parameters or
8697                    Object - settings for attaching new datepicker functionality
8698   @return  jQuery object */
8699$.fn.datepicker = function(options){
8700	
8701	/* Verify an empty collection wasn't passed - Fixes #6976 */
8702	if ( !this.length ) {
8703		return this;
8704	}
8705	
8706	/* Initialise the date picker. */
8707	if (!$.datepicker.initialized) {
8708		$(document).mousedown($.datepicker._checkExternalClick).
8709			find('body').append($.datepicker.dpDiv);
8710		$.datepicker.initialized = true;
8711	}
8712
8713	var otherArgs = Array.prototype.slice.call(arguments, 1);
8714	if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate' || options == 'widget'))
8715		return $.datepicker['_' + options + 'Datepicker'].
8716			apply($.datepicker, [this[0]].concat(otherArgs));
8717	if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string')
8718		return $.datepicker['_' + options + 'Datepicker'].
8719			apply($.datepicker, [this[0]].concat(otherArgs));
8720	return this.each(function() {
8721		typeof options == 'string' ?
8722			$.datepicker['_' + options + 'Datepicker'].
8723				apply($.datepicker, [this].concat(otherArgs)) :
8724			$.datepicker._attachDatepicker(this, options);
8725	});
8726};
8727
8728$.datepicker = new Datepicker(); // singleton instance
8729$.datepicker.initialized = false;
8730$.datepicker.uuid = new Date().getTime();
8731$.datepicker.version = "1.8.24";
8732
8733// Workaround for #4055
8734// Add another global to avoid noConflict issues with inline event handlers
8735window['DP_jQuery_' + dpuuid] = $;
8736
8737})(jQuery);
8738
8739(function( $, undefined ) {
8740
8741var uiDialogClasses =
8742		'ui-dialog ' +
8743		'ui-widget ' +
8744		'ui-widget-content ' +
8745		'ui-corner-all ',
8746	sizeRelatedOptions = {
8747		buttons: true,
8748		height: true,
8749		maxHeight: true,
8750		maxWidth: true,
8751		minHeight: true,
8752		minWidth: true,
8753		width: true
8754	},
8755	resizableRelatedOptions = {
8756		maxHeight: true,
8757		maxWidth: true,
8758		minHeight: true,
8759		minWidth: true
8760	};
8761
8762$.widget("ui.dialog", {
8763	options: {
8764		autoOpen: true,
8765		buttons: {},
8766		closeOnEscape: true,
8767		closeText: 'close',
8768		dialogClass: '',
8769		draggable: true,
8770		hide: null,
8771		height: 'auto',
8772		maxHeight: false,
8773		maxWidth: false,
8774		minHeight: 150,
8775		minWidth: 150,
8776		modal: false,
8777		position: {
8778			my: 'center',
8779			at: 'center',
8780			collision: 'fit',
8781			// ensure that the titlebar is never outside the document
8782			using: function(pos) {
8783				var topOffset = $(this).css(pos).offset().top;
8784				if (topOffset < 0) {
8785					$(this).css('top', pos.top - topOffset);
8786				}
8787			}
8788		},
8789		resizable: true,
8790		show: null,
8791		stack: true,
8792		title: '',
8793		width: 300,
8794		zIndex: 1000
8795	},
8796
8797	_create: function() {
8798		this.originalTitle = this.element.attr('title');
8799		// #5742 - .attr() might return a DOMElement
8800		if ( typeof this.originalTitle !== "string" ) {
8801			this.originalTitle = "";
8802		}
8803
8804		this.options.title = this.options.title || this.originalTitle;
8805		var self = this,
8806			options = self.options,
8807
8808			title = options.title || '&#160;',
8809			titleId = $.ui.dialog.getTitleId(self.element),
8810
8811			uiDialog = (self.uiDialog = $('<div></div>'))
8812				.appendTo(document.body)
8813				.hide()
8814				.addClass(uiDialogClasses + options.dialogClass)
8815				.css({
8816					zIndex: options.zIndex
8817				})
8818				// setting tabIndex makes the div focusable
8819				// setting outline to 0 prevents a border on focus in Mozilla
8820				.attr('tabIndex', -1).css('outline', 0).keydown(function(event) {
8821					if (options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
8822						event.keyCode === $.ui.keyCode.ESCAPE) {
8823						
8824						self.close(event);
8825						event.preventDefault();
8826					}
8827				})
8828				.attr({
8829					role: 'dialog',
8830					'aria-labelledby': titleId
8831				})
8832				.mousedown(function(event) {
8833					self.moveToTop(false, event);
8834				}),
8835
8836			uiDialogContent = self.element
8837				.show()
8838				.removeAttr('title')
8839				.addClass(
8840					'ui-dialog-content ' +
8841					'ui-widget-content')
8842				.appendTo(uiDialog),
8843
8844			uiDialogTitlebar = (self.uiDialogTitlebar = $('<div></div>'))
8845				.addClass(
8846					'ui-dialog-titlebar ' +
8847					'ui-widget-header ' +
8848					'ui-corner-all ' +
8849					'ui-helper-clearfix'
8850				)
8851				.prependTo(uiDialog),
8852
8853			uiDialogTitlebarClose = $('<a href="#"></a>')
8854				.addClass(
8855					'ui-dialog-titlebar-close ' +
8856					'ui-corner-all'
8857				)
8858				.attr('role', 'button')
8859				.hover(
8860					function() {
8861						uiDialogTitlebarClose.addClass('ui-state-hover');
8862					},
8863					function() {
8864						uiDialogTitlebarClose.removeClass('ui-state-hover');
8865					}
8866				)
8867				.focus(function() {
8868					uiDialogTitlebarClose.addClass('ui-state-focus');
8869				})
8870				.blur(function() {
8871					uiDialogTitlebarClose.removeClass('ui-state-focus');
8872				})
8873				.click(function(event) {
8874					self.close(event);
8875					return false;
8876				})
8877				.appendTo(uiDialogTitlebar),
8878
8879			uiDialogTitlebarCloseText = (self.uiDialogTitlebarCloseText = $('<span></span>'))
8880				.addClass(
8881					'ui-icon ' +
8882					'ui-icon-closethick'
8883				)
8884				.text(options.closeText)
8885				.appendTo(uiDialogTitlebarClose),
8886
8887			uiDialogTitle = $('<span></span>')
8888				.addClass('ui-dialog-title')
8889				.attr('id', titleId)
8890				.html(title)
8891				.prependTo(uiDialogTitlebar);
8892
8893		//handling of deprecated beforeclose (vs beforeClose) option
8894		//Ticket #4669 http://dev.jqueryui.com/ticket/4669
8895		//TODO: remove in 1.9pre
8896		if ($.isFunction(options.beforeclose) && !$.isFunction(options.beforeClose)) {
8897			options.beforeClose = options.beforeclose;
8898		}
8899
8900		uiDialogTitlebar.find("*").add(uiDialogTitlebar).disableSelection();
8901
8902		if (options.draggable && $.fn.draggable) {
8903			self._makeDraggable();
8904		}
8905		if (options.resizable && $.fn.resizable) {
8906			self._makeResizable();
8907		}
8908
8909		self._createButtons(options.buttons);
8910		self._isOpen = false;
8911
8912		if ($.fn.bgiframe) {
8913			uiDialog.bgiframe();
8914		}
8915	},
8916
8917	_init: function() {
8918		if ( this.options.autoOpen ) {
8919			this.open();
8920		}
8921	},
8922
8923	destroy: function() {
8924		var self = this;
8925		
8926		if (self.overlay) {
8927			self.overlay.destroy();
8928		}
8929		self.uiDialog.hide();
8930		self.element
8931			.unbind('.dialog')
8932			.removeData('dialog')
8933			.removeClass('ui-dialog-content ui-widget-content')
8934			.hide().appendTo('body');
8935		self.uiDialog.remove();
8936
8937		if (self.originalTitle) {
8938			self.element.attr('title', self.originalTitle);
8939		}
8940
8941		return self;
8942	},
8943
8944	widget: function() {
8945		return this.uiDialog;
8946	},
8947
8948	close: function(event) {
8949		var self = this,
8950			maxZ, thisZ;
8951		
8952		if (false === self._trigger('beforeClose', event)) {
8953			return;
8954		}
8955
8956		if (self.overlay) {
8957			self.overlay.destroy();
8958		}
8959		self.uiDialog.unbind('keypress.ui-dialog');
8960
8961		self._isOpen = false;
8962
8963		if (self.options.hide) {
8964			self.uiDialog.hide(self.options.hide, function() {
8965				self._trigger('close', event);
8966			});
8967		} else {
8968			self.uiDialog.hide();
8969			self._trigger('close', event);
8970		}
8971
8972		$.ui.dialog.overlay.resize();
8973
8974		// adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
8975		if (self.options.modal) {
8976			maxZ = 0;
8977			$('.ui-dialog').each(function() {
8978				if (this !== self.uiDialog[0]) {
8979					thisZ = $(this).css('z-index');
8980					if(!isNaN(thisZ)) {
8981						maxZ = Math.max(maxZ, thisZ);
8982					}
8983				}
8984			});
8985			$.ui.dialog.maxZ = maxZ;
8986		}
8987
8988		return self;
8989	},
8990
8991	isOpen: function() {
8992		return this._isOpen;
8993	},
8994
8995	// the force parameter allows us to move modal dialogs to their correct
8996	// position on open
8997	moveToTop: function(force, event) {
8998		var self = this,
8999			options = self.options,
9000			saveScroll;
9001
9002		if ((options.modal && !force) ||
9003			(!options.stack && !options.modal)) {
9004			return self._trigger('focus', event);
9005		}
9006
9007		if (options.zIndex > $.ui.dialog.maxZ) {
9008			$.ui.dialog.maxZ = options.zIndex;
9009		}
9010		if (self.overlay) {
9011			$.ui.dialog.maxZ += 1;
9012			self.overlay.$el.css('z-index', $.ui.dialog.overlay.maxZ = $.ui.dialog.maxZ);
9013		}
9014
9015		//Save and then restore scroll since Opera 9.5+ resets when parent z-Index is changed.
9016		//  http://ui.jquery.com/bugs/ticket/3193
9017		saveScroll = { scrollTop: self.element.scrollTop(), scrollLeft: self.element.scrollLeft() };
9018		$.ui.dialog.maxZ += 1;
9019		self.uiDialog.css('z-index', $.ui.dialog.maxZ);
9020		self.element.attr(saveScroll);
9021		self._trigger('focus', event);
9022
9023		return self;
9024	},
9025
9026	open: function() {
9027		if (this._isOpen) { return; }
9028
9029		var self = this,
9030			options = self.options,
9031			uiDialog = self.uiDialog;
9032
9033		self.overlay = options.modal ? new $.ui.dialog.overlay(self) : null;
9034		self._size();
9035		self._position(options.position);
9036		uiDialog.show(options.show);
9037		self.moveToTop(true);
9038
9039		// prevent tabbing out of modal dialogs
9040		if ( options.modal ) {
9041			uiDialog.bind( "keydown.ui-dialog", function( event ) {
9042				if ( event.keyCode !== $.ui.keyCode.TAB ) {
9043					return;
9044				}
9045
9046				var tabbables = $(':tabbable', this),
9047					first = tabbables.filter(':first'),
9048					last  = tabbables.filter(':last');
9049
9050				if (event.target === last[0] && !event.shiftKey) {
9051					first.focus(1);
9052					return false;
9053				} else if (event.target === first[0] && event.shiftKey) {
9054					last.focus(1);
9055					return false;
9056				}
9057			});
9058		}
9059
9060		// set focus to the first tabbable element in the content area or the first button
9061		// if there are no tabbable elements, set focus on the dialog itself
9062		$(self.element.find(':tabbable').get().concat(
9063			uiDialog.find('.ui-dialog-buttonpane :tabbable').get().concat(
9064				uiDialog.get()))).eq(0).focus();
9065
9066		self._isOpen = true;
9067		self._trigger('open');
9068
9069		return self;
9070	},
9071
9072	_createButtons: function(buttons) {
9073		var self = this,
9074			hasButtons = false,
9075			uiDialogButtonPane = $('<div></div>')
9076				.addClass(
9077					'ui-dialog-buttonpane ' +
9078					'ui-widget-content ' +
9079					'ui-helper-clearfix'
9080				),
9081			uiButtonSet = $( "<div></div>" )
9082				.addClass( "ui-dialog-buttonset" )
9083				.appendTo( uiDialogButtonPane );
9084
9085		// if we already have a button pane, remove it
9086		self.uiDialog.find('.ui-dialog-buttonpane').remove();
9087
9088		if (typeof buttons === 'object' && buttons !== null) {
9089			$.each(buttons, function() {
9090				return !(hasButtons = true);
9091			});
9092		}
9093		if (hasButtons) {
9094			$.each(buttons, function(name, props) {
9095				props = $.isFunction( props ) ?
9096					{ click: props, text: name } :
9097					props;
9098				var button = $('<button type="button"></button>')
9099					.click(function() {
9100						props.click.apply(self.element[0], arguments);
9101					})
9102					.appendTo(uiButtonSet);
9103				// can't use .attr( props, true ) with jQuery 1.3.2.
9104				$.each( props, function( key, value ) {
9105					if ( key === "click" ) {
9106						return;
9107					}
9108					if ( key in button ) {
9109						button[ key ]( value );
9110					} else {
9111						button.attr( key, value );
9112					}
9113				});
9114				if ($.fn.button) {
9115					button.button();
9116				}
9117			});
9118			uiDialogButtonPane.appendTo(self.uiDialog);
9119		}
9120	},
9121
9122	_makeDraggable: function() {
9123		var self = this,
9124			options = self.options,
9125			doc = $(document),
9126			heightBeforeDrag;
9127
9128		function filteredUi(ui) {
9129			return {
9130				position: ui.position,
9131				offset: ui.offset
9132			};
9133		}
9134
9135		self.uiDialog.draggable({
9136			cancel: '.ui-dialog-content, .ui-dialog-titlebar-close',
9137			handle: '.ui-dialog-titlebar',
9138			containment: 'document',
9139			start: function(event, ui) {
9140				heightBeforeDrag = options.height === "auto" ? "auto" : $(this).height();
9141				$(this).height($(this).height()).addClass("ui-dialog-dragging");
9142				self._trigger('dragStart', event, filteredUi(ui));
9143			},
9144			drag: function(event, ui) {
9145				self._trigger('drag', event, filteredUi(ui));
9146			},
9147			stop: function(event, ui) {
9148				options.position = [ui.position.left - doc.scrollLeft(),
9149					ui.position.top - doc.scrollTop()];
9150				$(this).removeClass("ui-dialog-dragging").height(heightBeforeDrag);
9151				self._trigger('dragStop', event, filteredUi(ui));
9152				$.ui.dialog.overlay.resize();
9153			}
9154		});
9155	},
9156
9157	_makeResizable: function(handles) {
9158		handles = (handles === undefined ? this.options.resizable : handles);
9159		var self = this,
9160			options = self.options,
9161			// .ui-resizable has position: relative defined in the stylesheet
9162			// but dialogs have to use absolute or fixed positioning
9163			position = self.uiDialog.css('position'),
9164			resizeHandles = (typeof handles === 'string' ?
9165				handles	:
9166				'n,e,s,w,se,sw,ne,nw'
9167			);
9168
9169		function filteredUi(ui) {
9170			return {
9171				originalPosition: ui.originalPosition,
9172				originalSize: ui.originalSize,
9173				position: ui.position,
9174				size: ui.size
9175			};
9176		}
9177
9178		self.uiDialog.resizable({
9179			cancel: '.ui-dialog-content',
9180			containment: 'document',
9181			alsoResize: self.element,
9182			maxWidth: options.maxWidth,
9183			maxHeight: options.maxHeight,
9184			minWidth: options.minWidth,
9185			minHeight: self._minHeight(),
9186			handles: resizeHandles,
9187			start: function(event, ui) {
9188				$(this).addClass("ui-dialog-resizing");
9189				self._trigger('resizeStart', event, filteredUi(ui));
9190			},
9191			resize: function(event, ui) {
9192				self._trigger('resize', event, filteredUi(ui));
9193			},
9194			stop: function(event, ui) {
9195				$(this).removeClass("ui-dialog-resizing");
9196				options.height = $(this).height();
9197				options.width = $(this).width();
9198				self._trigger('resizeStop', event, filteredUi(ui));
9199				$.ui.dialog.overlay.resize();
9200			}
9201		})
9202		.css('position', position)
9203		.find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se');
9204	},
9205
9206	_minHeight: function() {
9207		var options = this.options;
9208
9209		if (options.height === 'auto') {
9210			return options.minHeight;
9211		} else {
9212			return Math.min(options.minHeight, options.height);
9213		}
9214	},
9215
9216	_position: function(position) {
9217		var myAt = [],
9218			offset = [0, 0],
9219			isVisible;
9220
9221		if (position) {
9222			// deep extending converts arrays to objects in jQuery <= 1.3.2 :-(
9223	//		if (typeof position == 'string' || $.isArray(position)) {
9224	//			myAt = $.isArray(position) ? position : position.split(' ');
9225
9226			if (typeof position === 'string' || (typeof position === 'object' && '0' in position)) {
9227				myAt = position.split ? position.split(' ') : [position[0], position[1]];
9228				if (myAt.length === 1) {
9229					myAt[1] = myAt[0];
9230				}
9231
9232				$.each(['left', 'top'], function(i, offsetPosition) {
9233					if (+myAt[i] === myAt[i]) {
9234						offset[i] = myAt[i];
9235						myAt[i] = offsetPosition;
9236					}
9237				});
9238
9239				position = {
9240					my: myAt.join(" "),
9241					at: myAt.join(" "),
9242					offset: offset.join(" ")
9243				};
9244			} 
9245
9246			position = $.extend({}, $.ui.dialog.prototype.options.position, position);
9247		} else {
9248			position = $.ui.dialog.prototype.options.position;
9249		}
9250
9251		// need to show the dialog to get the actual offset in the position plugin
9252		isVisible = this.uiDialog.is(':visible');
9253		if (!isVisible) {
9254			this.uiDialog.show();
9255		}
9256		this.uiDialog
9257			// workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
9258			.css({ top: 0, left: 0 })
9259			.position($.extend({ of: window }, position));
9260		if (!isVisible) {
9261			this.uiDialog.hide();
9262		}
9263	},
9264
9265	_setOptions: function( options ) {
9266		var self = this,
9267			resizableOptions = {},
9268			resize = false;
9269
9270		$.each( options, function( key, value ) {
9271			self._setOption( key, value );
9272			
9273			if ( key in sizeRelatedOptions ) {
9274				resize = true;
9275			}
9276			if ( key in resizableRelatedOptions ) {
9277				resizableOptions[ key ] = value;
9278			}
9279		});
9280
9281		if ( resize ) {
9282			this._size();
9283		}
9284		if ( this.uiDialog.is( ":data(resizable)" ) ) {
9285			this.uiDialog.resizable( "option", resizableOptions );
9286		}
9287	},
9288
9289	_setOption: function(key, value){
9290		var self = this,
9291			uiDialog = self.uiDialog;
9292
9293		switch (key) {
9294			//handling of deprecated beforeclose (vs beforeClose) option
9295			//Ticket #4669 http://dev.jqueryui.com/ticket/4669
9296			//TODO: remove in 1.9pre
9297			case "beforeclose":
9298				key = "beforeClose";
9299				break;
9300			case "buttons":
9301				self._createButtons(value);
9302				break;
9303			case "closeText":
9304				// ensure that we always pass a string
9305				self.uiDialogTitlebarCloseText.text("" + value);
9306				break;
9307			case "dialogClass":
9308				uiDialog
9309					.removeClass(self.options.dialogClass)
9310					.addClass(uiDialogClasses + value);
9311				break;
9312			case "disabled":
9313				if (value) {
9314					uiDialog.addClass('ui-dialog-disabled');
9315				} else {
9316					uiDialog.removeClass('ui-dialog-disabled');
9317				}
9318				break;
9319			case "draggable":
9320				var isDraggable = uiDialog.is( ":data(draggable)" );
9321				if ( isDraggable && !value ) {
9322					uiDialog.draggable( "destroy" );
9323				}
9324				
9325				if ( !isDraggable && value ) {
9326					self._makeDraggable();
9327				}
9328				break;
9329			case "position":
9330				self._position(value);
9331				break;
9332			case "resizable":
9333				// currently resizable, becoming non-resizable
9334				var isResizable = uiDialog.is( ":data(resizable)" );
9335				if (isResizable && !value) {
9336					uiDialog.resizable('destroy');
9337				}
9338
9339				// currently resizable, changing handles
9340				if (isResizable && typeof value === 'string') {
9341					uiDialog.resizable('option', 'handles', value);
9342				}
9343
9344				// currently non-resizable, becoming resizable
9345				if (!isResizable && value !== false) {
9346					self._makeResizable(value);
9347				}
9348				break;
9349			case "title":
9350				// convert whatever was passed in o a string, for html() to not throw up
9351				$(".ui-dialog-title", self.uiDialogTitlebar).html("" + (value || '&#160;'));
9352				break;
9353		}
9354
9355		$.Widget.prototype._setOption.apply(self, arguments);
9356	},
9357
9358	_size: function() {
9359		/* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
9360		 * divs will both have width and height set, so we need to reset them
9361		 */
9362		var options = this.options,
9363			nonContentHeight,
9364			minContentHeight,
9365			isVisible = this.uiDialog.is( ":visible" );
9366
9367		// reset content sizing
9368		this.element.show().css({
9369			width: 'auto',
9370			minHeight: 0,
9371			height: 0
9372		});
9373
9374		if (options.minWidth > options.width) {
9375			options.width = options.minWidth;
9376		}
9377
9378		// reset wrapper sizing
9379		// determine the height of all the non-content elements
9380		nonContentHeight = this.uiDialog.css({
9381				height: 'auto',
9382				width: options.width
9383			})
9384			.height();
9385		minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
9386		
9387		if ( options.height === "auto" ) {
9388			// only needed for IE6 support
9389			if ( $.support.minHeight ) {
9390				this.element.css({
9391					minHeight: minContentHeight,
9392					height: "auto"
9393				});
9394			} else {
9395				this.uiDialog.show();
9396				var autoHeight = this.element.css( "height", "auto" ).height();
9397				if ( !isVisible ) {
9398					this.uiDialog.hide();
9399				}
9400				this.element.height( Math.max( autoHeight, minContentHeight ) );
9401			}
9402		} else {
9403			this.element.height( Math.max( options.height - nonContentHeight, 0 ) );
9404		}
9405
9406		if (this.uiDialog.is(':data(resizable)')) {
9407			this.uiDialog.resizable('option', 'minHeight', this._minHeight());
9408		}
9409	}
9410});
9411
9412$.extend($.ui.dialog, {
9413	version: "1.8.24",
9414
9415	uuid: 0,
9416	maxZ: 0,
9417
9418	getTitleId: function($el) {
9419		var id = $el.attr('id');
9420		if (!id) {
9421			this.uuid += 1;
9422			id = this.uuid;
9423		}
9424		return 'ui-dialog-title-' + id;
9425	},
9426
9427	overlay: function(dialog) {
9428		this.$el = $.ui.dialog.overlay.create(dialog);
9429	}
9430});
9431
9432$.extend($.ui.dialog.overlay, {
9433	instances: [],
9434	// reuse old instances due to IE memory leak with alpha transparency (see #5185)
9435	oldInstances: [],
9436	maxZ: 0,
9437	events: $.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','),
9438		function(event) { return event + '.dialog-overlay'; }).join(' '),
9439	create: function(dialog) {
9440		if (this.instances.length === 0) {
9441			// prevent use of anchors and inputs
9442			// we use a setTimeout in case the overlay is created from an
9443			// event that we're going to be cancelling (see #2804)
9444			setTimeout(function() {
9445				// handle $(el).dialog().dialog('close') (see #4065)
9446				if ($.ui.dialog.overlay.instances.length) {
9447					$(document).bind($.ui.dialog.overlay.events, function(event) {
9448						// stop events if the z-index of the target is < the z-index of the overlay
9449						// we cannot return true when we don't want to cancel the event (#3523)
9450						if ($(event.target).zIndex() < $.ui.dialog.overlay.maxZ) {
9451							return false;
9452						}
9453					});
9454				}
9455			}, 1);
9456
9457			// allow closing by pressing the escape key
9458			$(document).bind('keydown.dialog-overlay', function(event) {
9459				if (dialog.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
9460					event.keyCode === $.ui.keyCode.ESCAPE) {
9461					
9462					dialog.close(event);
9463					event.preventDefault();
9464				}
9465			});
9466
9467			// handle window resize
9468			$(window).bind('resize.dialog-overlay', $.ui.dialog.overlay.resize);
9469		}
9470
9471		var $el = (this.oldInstances.pop() || $('<div></div>').addClass('ui-widget-overlay'))
9472			.appendTo(document.body)
9473			.css({
9474				width: this.width(),
9475				height: this.height()
9476			});
9477
9478		if ($.fn.bgiframe) {
9479			$el.bgiframe();
9480		}
9481
9482		this.instances.push($el);
9483		return $el;
9484	},
9485
9486	destroy: function($el) {
9487		var indexOf = $.inArray($el, this.instances);
9488		if (indexOf != -1){
9489			this.oldInstances.push(this.instances.splice(indexOf, 1)[0]);
9490		}
9491
9492		if (this.instances.length === 0) {
9493			$([document, window]).unbind('.dialog-overlay');
9494		}
9495
9496		$el.remove();
9497		
9498		// adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
9499		var maxZ = 0;
9500		$.each(this.instances, function() {
9501			maxZ = Math.max(maxZ, this.css('z-index'));
9502		});
9503		this.maxZ = maxZ;
9504	},
9505
9506	height: function() {
9507		var scrollHeight,
9508			offsetHeight;
9509		// handle IE 6
9510		if ($.browser.msie && $.browser.version < 7) {
9511			scrollHeight = Math.max(
9512				document.documentElement.scrollHeight,
9513				document.body.scrollHeight
9514			);
9515			offsetHeight = Math.max(
9516				document.documentElement.offsetHeight,
9517				document.body.offsetHeight
9518			);
9519
9520			if (scrollHeight < offsetHeight) {
9521				return $(window).height() + 'px';
9522			} else {
9523				return scrollHeight + 'px';
9524			}
9525		// handle "good" browsers
9526		} else {
9527			return $(document).height() + 'px';
9528		}
9529	},
9530
9531	width: function() {
9532		var scrollWidth,
9533			offsetWidth;
9534		// handle IE
9535		if ( $.browser.msie ) {
9536			scrollWidth = Math.max(
9537				document.documentElement.scrollWidth,
9538				document.body.scrollWidth
9539			);
9540			offsetWidth = Math.max(
9541				document.documentElement.offsetWidth,
9542				document.body.offsetWidth
9543			);
9544
9545			if (scrollWidth < offsetWidth) {
9546				return $(window).width() + 'px';
9547			} else {
9548				return scrollWidth + 'px';
9549			}
9550		// handle "good" browsers
9551		} else {
9552			return $(document).width() + 'px';
9553		}
9554	},
9555
9556	resize: function() {
9557		/* If the dialog is draggable and the user drags it past the
9558		 * right edge of the window, the document becomes wider so we
9559		 * need to stretch the overlay. If the user then drags the
9560		 * dialog back to the left, the document will become narrower,
9561		 * so we need to shrink the overlay to the appropriate size.
9562		 * This is handled by shrinking the overlay before setting it
9563		 * to the full document size.
9564		 */
9565		var $overlays = $([]);
9566		$.each($.ui.dialog.overlay.instances, function() {
9567			$overlays = $overlays.add(this);
9568		});
9569
9570		$overlays.css({
9571			width: 0,
9572			height: 0
9573		}).css({
9574			width: $.ui.dialog.overlay.width(),
9575			height: $.ui.dialog.overlay.height()
9576		});
9577	}
9578});
9579
9580$.extend($.ui.dialog.overlay.prototype, {
9581	destroy: function() {
9582		$.ui.dialog.overlay.destroy(this.$el);
9583	}
9584});
9585
9586}(jQuery));
9587
9588(function( $, undefined ) {
9589
9590$.ui = $.ui || {};
9591
9592var horizontalPositions = /left|center|right/,
9593	verticalPositions = /top|center|bottom/,
9594	center = "center",
9595	support = {},
9596	_position = $.fn.position,
9597	_offset = $.fn.offset;
9598
9599$.fn.position = function( options ) {
9600	if ( !options || !options.of ) {
9601		return _position.apply( this, arguments );
9602	}
9603
9604	// make a copy, we don't want to modify arguments
9605	options = $.extend( {}, options );
9606
9607	var target = $( options.of ),
9608		targetElem = target[0],
9609		collision = ( options.collision || "flip" ).split( " " ),
9610		offset = options.offset ? options.offset.split( " " ) : [ 0, 0 ],
9611		targetWidth,
9612		targetHeight,
9613		basePosition;
9614
9615	if ( targetElem.nodeType === 9 ) {
9616		targetWidth = target.width();
9617		targetHeight = target.height();
9618		basePosition = { top: 0, left: 0 };
9619	// TODO: use $.isWindow() in 1.9
9620	} else if ( targetElem.setTimeout ) {
9621		targetWidth = target.width();
9622		targetHeight = target.height();
9623		basePosition = { top: target.scrollTop(), left: target.scrollLeft() };
9624	} else if ( targetElem.preventDefault ) {
9625		// force left top to allow flipping
9626		options.at = "left top";
9627		targetWidth = targetHeight = 0;
9628		basePosition = { top: options.of.pageY, left: options.of.pageX };
9629	} else {
9630		targetWidth = target.outerWidth();
9631		targetHeight = target.outerHeight();
9632		basePosition = target.offset();
9633	}
9634
9635	// force my and at to have valid horizontal and veritcal positions
9636	// if a value is missing or invalid, it will be converted to center 
9637	$.each( [ "my", "at" ], function() {
9638		var pos = ( options[this] || "" ).split( " " );
9639		if ( pos.length === 1) {
9640			pos = horizontalPositions.test( pos[0] ) ?
9641				pos.concat( [center] ) :
9642				verticalPositions.test( pos[0] ) ?
9643					[ center ].concat( pos ) :
9644					[ center, center ];
9645		}
9646		pos[ 0 ] = horizontalPositions.test( pos[0] ) ? pos[ 0 ] : center;
9647		pos[ 1 ] = verticalPositions.test( pos[1] ) ? pos[ 1 ] : center;
9648		options[ this ] = pos;
9649	});
9650
9651	// normalize collision option
9652	if ( collision.length === 1 ) {
9653		collision[ 1 ] = collision[ 0 ];
9654	}
9655
9656	// normalize offset option
9657	offset[ 0 ] = parseInt( offset[0], 10 ) || 0;
9658	if ( offset.length === 1 ) {
9659		offset[ 1 ] = offset[ 0 ];
9660	}
9661	offset[ 1 ] = parseInt( offset[1], 10 ) || 0;
9662
9663	if ( options.at[0] === "right" ) {
9664		basePosition.left += targetWidth;
9665	} else if ( options.at[0] === center ) {
9666		basePosition.left += targetWidth / 2;
9667	}
9668
9669	if ( options.at[1] === "bottom" ) {
9670		basePosition.top += targetHeight;
9671	} else if ( options.at[1] === center ) {
9672		basePosition.top += targetHeight / 2;
9673	}
9674
9675	basePosition.left += offset[ 0 ];
9676	basePosition.top += offset[ 1 ];
9677
9678	return this.each(function() {
9679		var elem = $( this ),
9680			elemWidth = elem.outerWidth(),
9681			elemHeight = elem.outerHeight(),
9682			marginLeft = parseInt( $.curCSS( this, "marginLeft", true ) ) || 0,
9683			marginTop = parseInt( $.curCSS( this, "marginTop", true ) ) || 0,
9684			collisionWidth = elemWidth + marginLeft +
9685				( parseInt( $.curCSS( this, "marginRight", true ) ) || 0 ),
9686			collisionHeight = elemHeight + marginTop +
9687				( parseInt( $.curCSS( this, "marginBottom", true ) ) || 0 ),
9688			position = $.extend( {}, basePosition ),
9689			collisionPosition;
9690
9691		if ( options.my[0] === "right" ) {
9692			position.left -= elemWidth;
9693		} else if ( options.my[0] === center ) {
9694			position.left -= elemWidth / 2;
9695		}
9696
9697		if ( options.my[1] === "bottom" ) {
9698			position.top -= elemHeight;
9699		} else if ( options.my[1] === center ) {
9700			position.top -= elemHeight / 2;
9701		}
9702
9703		// prevent fractions if jQuery version doesn't support them (see #5280)
9704		if ( !support.fractions ) {
9705			position.left = Math.round( position.left );
9706			position.top = Math.round( position.top );
9707		}
9708
9709		collisionPosition = {
9710			left: position.left - marginLeft,
9711			top: position.top - marginTop
9712		};
9713
9714		$.each( [ "left", "top" ], function( i, dir ) {
9715			if ( $.ui.position[ collision[i] ] ) {
9716				$.ui.position[ collision[i] ][ dir ]( position, {
9717					targetWidth: targetWidth,
9718					targetHeight: targetHeight,
9719					elemWidth: elemWidth,
9720					elemHeight: elemHeight,
9721					collisionPosition: collisionPosition,
9722					collisionWidth: collisionWidth,
9723					collisionHeight: collisionHeight,
9724					offset: offset,
9725					my: options.my,
9726					at: options.at
9727				});
9728			}
9729		});
9730
9731		if ( $.fn.bgiframe ) {
9732			elem.bgiframe();
9733		}
9734		elem.offset( $.extend( position, { using: options.using } ) );
9735	});
9736};
9737
9738$.ui.position = {
9739	fit: {
9740		left: function( position, data ) {
9741			var win = $( window ),
9742				over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft();
9743			position.left = over > 0 ? position.left - over : Math.max( position.left - data.collisionPosition.left, position.left );
9744		},
9745		top: function( position, data ) {
9746			var win = $( window ),
9747				over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop();
9748			position.top = over > 0 ? position.top - over : Math.max( position.top - data.collisionPosition.top, position.top );
9749		}
9750	},
9751
9752	flip: {
9753		left: function( position, data ) {
9754			if ( data.at[0] === center ) {
9755				return;
9756			}
9757			var win = $( window ),
9758				over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(),
9759				myOffset = data.my[ 0 ] === "left" ?
9760					-data.elemWidth :
9761					data.my[ 0 ] === "right" ?
9762						data.elemWidth :
9763						0,
9764				atOffset = data.at[ 0 ] === "left" ?
9765					data.targetWidth :
9766					-data.targetWidth,
9767				offset = -2 * data.offset[ 0 ];
9768			position.left += data.collisionPosition.left < 0 ?
9769				myOffset + atOffset + offset :
9770				over > 0 ?
9771					myOffset + atOffset + offset :
9772					0;
9773		},
9774		top: function( position, data ) {
9775			if ( data.at[1] === center ) {
9776				return;
9777			}
9778			var win = $( window ),
9779				over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(),
9780				myOffset = data.my[ 1 ] === "top" ?
9781					-data.elemHeight :
9782					data.my[ 1 ] === "bottom" ?
9783						data.elemHeight :
9784						0,
9785				atOffset = data.at[ 1 ] === "top" ?
9786					data.targetHeight :
9787					-data.targetHeight,
9788				offset = -2 * data.offset[ 1 ];
9789			position.top += data.collisionPosition.top < 0 ?
9790				myOffset + atOffset + offset :
9791				over > 0 ?
9792					myOffset + atOffset + offset :
9793					0;
9794		}
9795	}
9796};
9797
9798// offset setter from jQuery 1.4
9799if ( !$.offset.setOffset ) {
9800	$.offset.setOffset = function( elem, options ) {
9801		// set position first, in-case top/left are set even on static elem
9802		if ( /static/.test( $.curCSS( elem, "position" ) ) ) {
9803			elem.style.position = "relative";
9804		}
9805		var curElem   = $( elem ),
9806			curOffset = curElem.offset(),
9807			curTop    = parseInt( $.curCSS( elem, "top",  true ), 10 ) || 0,
9808			curLeft   = parseInt( $.curCSS( elem, "left", true ), 10)  || 0,
9809			props     = {
9810				top:  (options.top  - curOffset.top)  + curTop,
9811				left: (options.left - curOffset.left) + curLeft
9812			};
9813		
9814		if ( 'using' in options ) {
9815			options.using.call( elem, props );
9816		} else {
9817			curElem.css( props );
9818		}
9819	};
9820
9821	$.fn.offset = function( options ) {
9822		var elem = this[ 0 ];
9823		if ( !elem || !elem.ownerDocument ) { return null; }
9824		if ( options ) {
9825			if ( $.isFunction( options ) ) {
9826				return this.each(function( i ) {
9827					$( this ).offset( options.call( this, i, $( this ).offset() ) );
9828				});
9829			}
9830			return this.each(function() {
9831				$.offset.setOffset( this, options );
9832			});
9833		}
9834		return _offset.call( this );
9835	};
9836}
9837
9838// jQuery <1.4.3 uses curCSS, in 1.4.3 - 1.7.2 curCSS = css, 1.8+ only has css
9839if ( !$.curCSS ) {
9840	$.curCSS = $.css;
9841}
9842
9843// fraction support test (older versions of jQuery don't support fractions)
9844(function () {
9845	var body = document.getElementsByTagName( "body" )[ 0 ], 
9846		div = document.createElement( "div" ),
9847		testElement, testElementParent, testElementStyle, offset, offsetTotal;
9848
9849	//Create a "fake body" for testing based on method used in jQuery.support
9850	testElement = document.createElement( body ? "div" : "body" );
9851	testElementStyle = {
9852		visibility: "hidden",
9853		width: 0,
9854		height: 0,
9855		border: 0,
9856		margin: 0,
9857		background: "none"
9858	};
9859	if ( body ) {
9860		$.extend( testElementStyle, {
9861			position: "absolute",
9862			left: "-1000px",
9863			top: "-1000px"
9864		});
9865	}
9866	for ( var i in testElementStyle ) {
9867		testElement.style[ i ] = testElementStyle[ i ];
9868	}
9869	testElement.appendChild( div );
9870	testElementParent = body || document.documentElement;
9871	testElementParent.insertBefore( testElement, testElementParent.firstChild );
9872
9873	div.style.cssText = "position: absolute; left: 10.7432222px; top: 10.432325px; height: 30px; width: 201px;";
9874
9875	offset = $( div ).offset( function( _, offset ) {
9876		return offset;
9877	}).offset();
9878
9879	testElement.innerHTML = "";
9880	testElementParent.removeChild( testElement );
9881
9882	offsetTotal = offset.top + offset.left + ( body ? 2000 : 0 );
9883	support.fractions = offsetTotal > 21 && offsetTotal < 22;
9884})();
9885
9886}( jQuery ));
9887
9888(function( $, undefined ) {
9889
9890$.widget( "ui.progressbar", {
9891	options: {
9892		value: 0,
9893		max: 100
9894	},
9895
9896	min: 0,
9897
9898	_create: function() {
9899		this.element
9900			.addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
9901			.attr({
9902				role: "progressbar",
9903				"aria-valuemin": this.min,
9904				"aria-valuemax": this.options.max,
9905				"aria-valuenow": this._value()
9906			});
9907
9908		this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" )
9909			.appendTo( this.element );
9910
9911		this.oldValue = this._value();
9912		this._refreshValue();
9913	},
9914
9915	destroy: function() {
9916		this.element
9917			.removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
9918			.removeAttr( "role" )
9919			.removeAttr( "aria-valuemin" )
9920			.removeAttr( "aria-valuemax" )
9921			.removeAttr( "aria-valuenow" );
9922
9923		this.valueDiv.remove();
9924
9925		$.Widget.prototype.destroy.apply( this, arguments );
9926	},
9927
9928	value: function( newValue ) {
9929		if ( newValue === undefined ) {
9930			return this._value();
9931		}
9932
9933		this._setOption( "value", newValue );
9934		return this;
9935	},
9936
9937	_setOption: function( key, value ) {
9938		if ( key === "value" ) {
9939			this.options.value = value;
9940			this._refreshValue();
9941			if ( this._value() === this.options.max ) {
9942				this._trigger( "complete" );
9943			}
9944		}
9945
9946		$.Widget.prototype._setOption.apply( this, arguments );
9947	},
9948
9949	_value: function() {
9950		var val = this.options.value;
9951		// normalize invalid value
9952		if ( typeof val !== "number" ) {
9953			val = 0;
9954		}
9955		return Math.min( this.options.max, Math.max( this.min, val ) );
9956	},
9957
9958	_percentage: function() {
9959		return 100 * this._value() / this.options.max;
9960	},
9961
9962	_refreshValue: function() {
9963		var value = this.value();
9964		var percentage = this._percentage();
9965
9966		if ( this.oldValue !== value ) {
9967			this.oldValue = value;
9968			this._trigger( "change" );
9969		}
9970
9971		this.valueDiv
9972			.toggle( value > this.min )
9973			.toggleClass( "ui-corner-right", value === this.options.max )
9974			.width( percentage.toFixed(0) + "%" );
9975		this.element.attr( "aria-valuenow", value );
9976	}
9977});
9978
9979$.extend( $.ui.progressbar, {
9980	version: "1.8.24"
9981});
9982
9983})( jQuery );
9984
9985(function( $, undefined ) {
9986
9987// number of pages in a slider
9988// (how many times can you page up/down to go through the whole range)
9989var numPages = 5;
9990
9991$.widget( "ui.slider", $.ui.mouse, {
9992
9993	widgetEventPrefix: "slide",
9994
9995	options: {
9996		animate: false,
9997		distance: 0,
9998		max: 100,
9999		min: 0,
10000		orientation: "horizontal",
10001		range: false,
10002		step: 1,
10003		value: 0,
10004		values: null
10005	},
10006
10007	_create: function() {
10008		var self = this,
10009			o = this.options,
10010			existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ),
10011			handle = "<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>",
10012			handleCount = ( o.values && o.values.length ) || 1,
10013			handles = [];
10014
10015		this._keySliding = false;
10016		this._mouseSliding = false;
10017		this._animateOff = true;
10018		this._handleIndex = null;
10019		this._detectOrientation();
10020		this._mouseInit();
10021
10022		this.element
10023			.addClass( "ui-slider" +
10024				" ui-slider-" + this.orientation +
10025				" ui-widget" +
10026				" ui-widget-content" +
10027				" ui-corner-all" +
10028				( o.disabled ? " ui-slider-disabled ui-disabled" : "" ) );
10029
10030		this.range = $([]);
10031
10032		if ( o.range ) {
10033			if ( o.range === true ) {
10034				if ( !o.values ) {
10035					o.values = [ this._valueMin(), this._valueMin() ];
10036				}
10037				if ( o.values.length && o.values.length !== 2 ) {
10038					o.values = [ o.values[0], o.values[0] ];
10039				}
10040			}
10041
10042			this.range = $( "<div></div>" )
10043				.appendTo( this.element )
10044				.addClass( "ui-slider-range" +
10045				// note: this isn't the most fittingly semantic framework class for this element,
10046				// but worked best visually with a variety of themes
10047				" ui-widget-header" + 
10048				( ( o.range === "min" || o.range === "max" ) ? " ui-slider-range-" + o.range : "" ) );
10049		}
10050
10051		for ( var i = existingHandles.length; i < handleCount; i += 1 ) {
10052			handles.push( handle );
10053		}
10054
10055		this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( self.element ) );
10056
10057		this.handle = this.handles.eq( 0 );
10058
10059		this.handles.add( this.range ).filter( "a" )
10060			.click(function( event ) {
10061				event.preventDefault();
10062			})
10063			.hover(function() {
10064				if ( !o.disabled ) {
10065					$( this ).addClass( "ui-state-hover" );
10066				}
10067			}, function() {
10068				$( this ).removeClass( "ui-state-hover" );
10069			})
10070			.focus(function() {
10071				if ( !o.disabled ) {
10072					$( ".ui-slider .ui-state-focus" ).removeClass( "ui-state-focus" );
10073					$( this ).addClass( "ui-state-focus" );
10074				} else {
10075					$( this ).blur();
10076				}
10077			})
10078			.blur(function() {
10079				$( this ).removeClass( "ui-state-focus" );
10080			});
10081
10082		this.handles.each(function( i ) {
10083			$( this ).data( "index.ui-slider-handle", i );
10084		});
10085
10086		this.handles
10087			.keydown(function( event ) {
10088				var index = $( this ).data( "index.ui-slider-handle" ),
10089					allowed,
10090					curVal,
10091					newVal,
10092					step;
10093	
10094				if ( self.options.disabled ) {
10095					return;
10096				}
10097	
10098				switch ( event.keyCode ) {
10099					case $.ui.keyCode.HOME:
10100					case $.ui.keyCode.END:
10101					case $.ui.keyCode.PAGE_UP:
10102					case $.ui.keyCode.PAGE_DOWN:
10103					case $.ui.keyCode.UP:
10104					case $.ui.keyCode.RIGHT:
10105					case $.ui.keyCode.DOWN:
10106					case $.ui.keyCode.LEFT:
10107						event.preventDefault();
10108						if ( !self._keySliding ) {
10109							self._keySliding = true;
10110							$( this ).addClass( "ui-state-active" );
10111							allowed = self._start( event, index );
10112							if ( allowed === false ) {
10113								return;
10114							}
10115						}
10116						break;
10117				}
10118	
10119				step = self.options.step;
10120				if ( self.options.values && self.options.values.length ) {
10121					curVal = newVal = self.values( index );
10122				} else {
10123					curVal = newVal = self.value();
10124				}
10125	
10126				switch ( event.keyCode ) {
10127					case $.ui.keyCode.HOME:
10128						newVal = self._valueMin();
10129						break;
10130					case $.ui.keyCode.END:
10131						newVal = self._valueMax();
10132						break;
10133					case $.ui.keyCode.PAGE_UP:
10134						newVal = self._trimAlignValue( curVal + ( (self._valueMax() - self._valueMin()) / numPages ) );
10135						break;
10136					case $.ui.keyCode.PAGE_DOWN:
10137						newVal = self._trimAlignValue( curVal - ( (self._valueMax() - self._valueMin()) / numPages ) );
10138						break;
10139					case $.ui.keyCode.UP:
10140					case $.ui.keyCode.RIGHT:
10141						if ( curVal === self._valueMax() ) {
10142							return;
10143						}
10144						newVal = self._trimAlignValue( curVal + step );
10145						break;
10146					case $.ui.keyCode.DOWN:
10147					case $.ui.keyCode.LEFT:
10148						if ( curVal === self._valueMin() ) {
10149							return;
10150						}
10151						newVal = self._trimAlignValue( curVal - step );
10152						break;
10153				}
10154	
10155				self._slide( event, index, newVal );
10156			})
10157			.keyup(function( event ) {
10158				var index = $( this ).data( "index.ui-slider-handle" );
10159	
10160				if ( self._keySliding ) {
10161					self._keySliding = false;
vendor: 11,399 bytes, lines 10162-10598
10162					self._stop( event, index );
10163					self._change( event, index );
10164					$( this ).removeClass( "ui-state-active" );
10165				}
10166	
10167			});
10168
10169		this._refreshValue();
10170
10171		this._animateOff = false;
10172	},
10173
10174	destroy: function() {
10175		this.handles.remove();
10176		this.range.remove();
10177
10178		this.element
10179			.removeClass( "ui-slider" +
10180				" ui-slider-horizontal" +
10181				" ui-slider-vertical" +
10182				" ui-slider-disabled" +
10183				" ui-widget" +
10184				" ui-widget-content" +
10185				" ui-corner-all" )
10186			.removeData( "slider" )
10187			.unbind( ".slider" );
10188
10189		this._mouseDestroy();
10190
10191		return this;
10192	},
10193
10194	_mouseCapture: function( event ) {
10195		var o = this.options,
10196			position,
10197			normValue,
10198			distance,
10199			closestHandle,
10200			self,
10201			index,
10202			allowed,
10203			offset,
10204			mouseOverHandle;
10205
10206		if ( o.disabled ) {
10207			return false;
10208		}
10209
10210		this.elementSize = {
10211			width: this.element.outerWidth(),
10212			height: this.element.outerHeight()
10213		};
10214		this.elementOffset = this.element.offset();
10215
10216		position = { x: event.pageX, y: event.pageY };
10217		normValue = this._normValueFromMouse( position );
10218		distance = this._valueMax() - this._valueMin() + 1;
10219		self = this;
10220		this.handles.each(function( i ) {
10221			var thisDistance = Math.abs( normValue - self.values(i) );
10222			if ( distance > thisDistance ) {
10223				distance = thisDistance;
10224				closestHandle = $( this );
10225				index = i;
10226			}
10227		});
10228
10229		// workaround for bug #3736 (if both handles of a range are at 0,
10230		// the first is always used as the one with least distance,
10231		// and moving it is obviously prevented by preventing negative ranges)
10232		if( o.range === true && this.values(1) === o.min ) {
10233			index += 1;
10234			closestHandle = $( this.handles[index] );
10235		}
10236
10237		allowed = this._start( event, index );
10238		if ( allowed === false ) {
10239			return false;
10240		}
10241		this._mouseSliding = true;
10242
10243		self._handleIndex = index;
10244
10245		closestHandle
10246			.addClass( "ui-state-active" )
10247			.focus();
10248		
10249		offset = closestHandle.offset();
10250		mouseOverHandle = !$( event.target ).parents().andSelf().is( ".ui-slider-handle" );
10251		this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
10252			left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
10253			top: event.pageY - offset.top -
10254				( closestHandle.height() / 2 ) -
10255				( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
10256				( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
10257				( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
10258		};
10259
10260		if ( !this.handles.hasClass( "ui-state-hover" ) ) {
10261			this._slide( event, index, normValue );
10262		}
10263		this._animateOff = true;
10264		return true;
10265	},
10266
10267	_mouseStart: function( event ) {
10268		return true;
10269	},
10270
10271	_mouseDrag: function( event ) {
10272		var position = { x: event.pageX, y: event.pageY },
10273			normValue = this._normValueFromMouse( position );
10274		
10275		this._slide( event, this._handleIndex, normValue );
10276
10277		return false;
10278	},
10279
10280	_mouseStop: function( event ) {
10281		this.handles.removeClass( "ui-state-active" );
10282		this._mouseSliding = false;
10283
10284		this._stop( event, this._handleIndex );
10285		this._change( event, this._handleIndex );
10286
10287		this._handleIndex = null;
10288		this._clickOffset = null;
10289		this._animateOff = false;
10290
10291		return false;
10292	},
10293	
10294	_detectOrientation: function() {
10295		this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
10296	},
10297
10298	_normValueFromMouse: function( position ) {
10299		var pixelTotal,
10300			pixelMouse,
10301			percentMouse,
10302			valueTotal,
10303			valueMouse;
10304
10305		if ( this.orientation === "horizontal" ) {
10306			pixelTotal = this.elementSize.width;
10307			pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
10308		} else {
10309			pixelTotal = this.elementSize.height;
10310			pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
10311		}
10312
10313		percentMouse = ( pixelMouse / pixelTotal );
10314		if ( percentMouse > 1 ) {
10315			percentMouse = 1;
10316		}
10317		if ( percentMouse < 0 ) {
10318			percentMouse = 0;
10319		}
10320		if ( this.orientation === "vertical" ) {
10321			percentMouse = 1 - percentMouse;
10322		}
10323
10324		valueTotal = this._valueMax() - this._valueMin();
10325		valueMouse = this._valueMin() + percentMouse * valueTotal;
10326
10327		return this._trimAlignValue( valueMouse );
10328	},
10329
10330	_start: function( event, index ) {
10331		var uiHash = {
10332			handle: this.handles[ index ],
10333			value: this.value()
10334		};
10335		if ( this.options.values && this.options.values.length ) {
10336			uiHash.value = this.values( index );
10337			uiHash.values = this.values();
10338		}
10339		return this._trigger( "start", event, uiHash );
10340	},
10341
10342	_slide: function( event, index, newVal ) {
10343		var otherVal,
10344			newValues,
10345			allowed;
10346
10347		if ( this.options.values && this.options.values.length ) {
10348			otherVal = this.values( index ? 0 : 1 );
10349
10350			if ( ( this.options.values.length === 2 && this.options.range === true ) && 
10351					( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
10352				) {
10353				newVal = otherVal;
10354			}
10355
10356			if ( newVal !== this.values( index ) ) {
10357				newValues = this.values();
10358				newValues[ index ] = newVal;
10359				// A slide can be canceled by returning false from the slide callback
10360				allowed = this._trigger( "slide", event, {
10361					handle: this.handles[ index ],
10362					value: newVal,
10363					values: newValues
10364				} );
10365				otherVal = this.values( index ? 0 : 1 );
10366				if ( allowed !== false ) {
10367					this.values( index, newVal, true );
10368				}
10369			}
10370		} else {
10371			if ( newVal !== this.value() ) {
10372				// A slide can be canceled by returning false from the slide callback
10373				allowed = this._trigger( "slide", event, {
10374					handle: this.handles[ index ],
10375					value: newVal
10376				} );
10377				if ( allowed !== false ) {
10378					this.value( newVal );
10379				}
10380			}
10381		}
10382	},
10383
10384	_stop: function( event, index ) {
10385		var uiHash = {
10386			handle: this.handles[ index ],
10387			value: this.value()
10388		};
10389		if ( this.options.values && this.options.values.length ) {
10390			uiHash.value = this.values( index );
10391			uiHash.values = this.values();
10392		}
10393
10394		this._trigger( "stop", event, uiHash );
10395	},
10396
10397	_change: function( event, index ) {
10398		if ( !this._keySliding && !this._mouseSliding ) {
10399			var uiHash = {
10400				handle: this.handles[ index ],
10401				value: this.value()
10402			};
10403			if ( this.options.values && this.options.values.length ) {
10404				uiHash.value = this.values( index );
10405				uiHash.values = this.values();
10406			}
10407
10408			this._trigger( "change", event, uiHash );
10409		}
10410	},
10411
10412	value: function( newValue ) {
10413		if ( arguments.length ) {
10414			this.options.value = this._trimAlignValue( newValue );
10415			this._refreshValue();
10416			this._change( null, 0 );
10417			return;
10418		}
10419
10420		return this._value();
10421	},
10422
10423	values: function( index, newValue ) {
10424		var vals,
10425			newValues,
10426			i;
10427
10428		if ( arguments.length > 1 ) {
10429			this.options.values[ index ] = this._trimAlignValue( newValue );
10430			this._refreshValue();
10431			this._change( null, index );
10432			return;
10433		}
10434
10435		if ( arguments.length ) {
10436			if ( $.isArray( arguments[ 0 ] ) ) {
10437				vals = this.options.values;
10438				newValues = arguments[ 0 ];
10439				for ( i = 0; i < vals.length; i += 1 ) {
10440					vals[ i ] = this._trimAlignValue( newValues[ i ] );
10441					this._change( null, i );
10442				}
10443				this._refreshValue();
10444			} else {
10445				if ( this.options.values && this.options.values.length ) {
10446					return this._values( index );
10447				} else {
10448					return this.value();
10449				}
10450			}
10451		} else {
10452			return this._values();
10453		}
10454	},
10455
10456	_setOption: function( key, value ) {
10457		var i,
10458			valsLength = 0;
10459
10460		if ( $.isArray( this.options.values ) ) {
10461			valsLength = this.options.values.length;
10462		}
10463
10464		$.Widget.prototype._setOption.apply( this, arguments );
10465
10466		switch ( key ) {
10467			case "disabled":
10468				if ( value ) {
10469					this.handles.filter( ".ui-state-focus" ).blur();
10470					this.handles.removeClass( "ui-state-hover" );
10471					this.handles.propAttr( "disabled", true );
10472					this.element.addClass( "ui-disabled" );
10473				} else {
10474					this.handles.propAttr( "disabled", false );
10475					this.element.removeClass( "ui-disabled" );
10476				}
10477				break;
10478			case "orientation":
10479				this._detectOrientation();
10480				this.element
10481					.removeClass( "ui-slider-horizontal ui-slider-vertical" )
10482					.addClass( "ui-slider-" + this.orientation );
10483				this._refreshValue();
10484				break;
10485			case "value":
10486				this._animateOff = true;
10487				this._refreshValue();
10488				this._change( null, 0 );
10489				this._animateOff = false;
10490				break;
10491			case "values":
10492				this._animateOff = true;
10493				this._refreshValue();
10494				for ( i = 0; i < valsLength; i += 1 ) {
10495					this._change( null, i );
10496				}
10497				this._animateOff = false;
10498				break;
10499		}
10500	},
10501
10502	//internal value getter
10503	// _value() returns value trimmed by min and max, aligned by step
10504	_value: function() {
10505		var val = this.options.value;
10506		val = this._trimAlignValue( val );
10507
10508		return val;
10509	},
10510
10511	//internal values getter
10512	// _values() returns array of values trimmed by min and max, aligned by step
10513	// _values( index ) returns single value trimmed by min and max, aligned by step
10514	_values: function( index ) {
10515		var val,
10516			vals,
10517			i;
10518
10519		if ( arguments.length ) {
10520			val = this.options.values[ index ];
10521			val = this._trimAlignValue( val );
10522
10523			return val;
10524		} else {
10525			// .slice() creates a copy of the array
10526			// this copy gets trimmed by min and max and then returned
10527			vals = this.options.values.slice();
10528			for ( i = 0; i < vals.length; i+= 1) {
10529				vals[ i ] = this._trimAlignValue( vals[ i ] );
10530			}
10531
10532			return vals;
10533		}
10534	},
10535	
10536	// returns the step-aligned value that val is closest to, between (inclusive) min and max
10537	_trimAlignValue: function( val ) {
10538		if ( val <= this._valueMin() ) {
10539			return this._valueMin();
10540		}
10541		if ( val >= this._valueMax() ) {
10542			return this._valueMax();
10543		}
10544		var step = ( this.options.step > 0 ) ? this.options.step : 1,
10545			valModStep = (val - this._valueMin()) % step,
10546			alignValue = val - valModStep;
10547
10548		if ( Math.abs(valModStep) * 2 >= step ) {
10549			alignValue += ( valModStep > 0 ) ? step : ( -step );
10550		}
10551
10552		// Since JavaScript has problems with large floats, round
10553		// the final value to 5 digits after the decimal point (see #4124)
10554		return parseFloat( alignValue.toFixed(5) );
10555	},
10556
10557	_valueMin: function() {
10558		return this.options.min;
10559	},
10560
10561	_valueMax: function() {
10562		return this.options.max;
10563	},
10564	
10565	_refreshValue: function() {
10566		var oRange = this.options.range,
10567			o = this.options,
10568			self = this,
10569			animate = ( !this._animateOff ) ? o.animate : false,
10570			valPercent,
10571			_set = {},
10572			lastValPercent,
10573			value,
10574			valueMin,
10575			valueMax;
10576
10577		if ( this.options.values && this.options.values.length ) {
10578			this.handles.each(function( i, j ) {
10579				valPercent = ( self.values(i) - self._valueMin() ) / ( self._valueMax() - self._valueMin() ) * 100;
10580				_set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
10581				$( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
10582				if ( self.options.range === true ) {
10583					if ( self.orientation === "horizontal" ) {
10584						if ( i === 0 ) {
10585							self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
10586						}
10587						if ( i === 1 ) {
10588							self.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
10589						}
10590					} else {
10591						if ( i === 0 ) {
10592							self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
10593						}
10594						if ( i === 1 ) {
10595							self.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
10596						}
10597					}
10598				}
10599				lastValPercent = valPercent;
10600			});
10601		} else {
10602			value = this.value();
10603			valueMin = this._valueMin();
10604			valueMax = this._valueMax();
10605			valPercent = ( valueMax !== valueMin ) ?
10606					( value - valueMin ) / ( valueMax - valueMin ) * 100 :
10607					0;
10608			_set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
10609			this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
10610
10611			if ( oRange === "min" && this.orientation === "horizontal" ) {
10612				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );
10613			}
10614			if ( oRange === "max" && this.orientation === "horizontal" ) {
10615				this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
10616			}
10617			if ( oRange === "min" && this.orientation === "vertical" ) {
10618				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );
10619			}
10620			if ( oRange === "max" && this.orientation === "vertical" ) {
10621				this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
10622			}
10623		}
10624	}
10625
10626});
10627
10628$.extend( $.ui.slider, {
10629	version: "1.8.24"
10630});
10631
10632}(jQuery));
10633
10634(function( $, undefined ) {
10635
10636var tabId = 0,
10637	listId = 0;
10638
10639function getNextTabId() {
10640	return ++tabId;
10641}
10642
10643function getNextListId() {
10644	return ++listId;
10645}
10646
10647$.widget( "ui.tabs", {
10648	options: {
10649		add: null,
10650		ajaxOptions: null,
10651		cache: false,
10652		cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
10653		collapsible: false,
10654		disable: null,
10655		disabled: [],
10656		enable: null,
10657		event: "click",
10658		fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 }
10659		idPrefix: "ui-tabs-",
10660		load: null,
10661		panelTemplate: "<div></div>",
10662		remove: null,
10663		select: null,
10664		show: null,
10665		spinner: "<em>Loading&#8230;</em>",
10666		tabTemplate: "<li><a href='#{href}'><span>#{label}</span></a></li>"
10667	},
10668
10669	_create: function() {
10670		this._tabify( true );
10671	},
10672
10673	_setOption: function( key, value ) {
10674		if ( key == "selected" ) {
10675			if (this.options.collapsible && value == this.options.selected ) {
10676				return;
10677			}
10678			this.select( value );
10679		} else {
10680			this.options[ key ] = value;
10681			this._tabify();
10682		}
10683	},
10684
10685	_tabId: function( a ) {
10686		return a.title && a.title.replace( /\s/g, "_" ).replace( /[^\w\u00c0-\uFFFF-]/g, "" ) ||
10687			this.options.idPrefix + getNextTabId();
10688	},
10689
10690	_sanitizeSelector: function( hash ) {
10691		// we need this because an id may contain a ":"
10692		return hash.replace( /:/g, "\\:" );
10693	},
10694
10695	_cookie: function() {
10696		var cookie = this.cookie ||
10697			( this.cookie = this.options.cookie.name || "ui-tabs-" + getNextListId() );
10698		return $.cookie.apply( null, [ cookie ].concat( $.makeArray( arguments ) ) );
10699	},
10700
10701	_ui: function( tab, panel ) {
10702		return {
10703			tab: tab,
10704			panel: panel,
10705			index: this.anchors.index( tab )
10706		};
10707	},
10708
10709	_cleanup: function() {
10710		// restore all former loading tabs labels
10711		this.lis.filter( ".ui-state-processing" )
10712			.removeClass( "ui-state-processing" )
10713			.find( "span:data(label.tabs)" )
10714				.each(function() {
10715					var el = $( this );
10716					el.html( el.data( "label.tabs" ) ).removeData( "label.tabs" );
10717				});
10718	},
10719
10720	_tabify: function( init ) {
10721		var self = this,
10722			o = this.options,
10723			fragmentId = /^#.+/; // Safari 2 reports '#' for an empty hash
10724
10725		this.list = this.element.find( "ol,ul" ).eq( 0 );
10726		this.lis = $( " > li:has(a[href])", this.list );
10727		this.anchors = this.lis.map(function() {
10728			return $( "a", this )[ 0 ];
10729		});
10730		this.panels = $( [] );
10731
10732		this.anchors.each(function( i, a ) {
10733			var href = $( a ).attr( "href" );
10734			// For dynamically created HTML that contains a hash as href IE < 8 expands
10735			// such href to the full page url with hash and then misinterprets tab as ajax.
10736			// Same consideration applies for an added tab with a fragment identifier
10737			// since a[href=#fragment-identifier] does unexpectedly not match.
10738			// Thus normalize href attribute...
10739			var hrefBase = href.split( "#" )[ 0 ],
10740				baseEl;
10741			if ( hrefBase && ( hrefBase === location.toString().split( "#" )[ 0 ] ||
10742					( baseEl = $( "base" )[ 0 ]) && hrefBase === baseEl.href ) ) {
10743				href = a.hash;
10744				a.href = href;
10745			}
10746
10747			// inline tab
10748			if ( fragmentId.test( href ) ) {
10749				self.panels = self.panels.add( self.element.find( self._sanitizeSelector( href ) ) );
10750			// remote tab
10751			// prevent loading the page itself if href is just "#"
10752			} else if ( href && href !== "#" ) {
10753				// required for restore on destroy
10754				$.data( a, "href.tabs", href );
10755
10756				// TODO until #3808 is fixed strip fragment identifier from url
10757				// (IE fails to load from such url)
10758				$.data( a, "load.tabs", href.replace( /#.*$/, "" ) );
10759
10760				var id = self._tabId( a );
10761				a.href = "#" + id;
10762				var $panel = self.element.find( "#" + id );
10763				if ( !$panel.length ) {
10764					$panel = $( o.panelTemplate )
10765						.attr( "id", id )
10766						.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
10767						.insertAfter( self.panels[ i - 1 ] || self.list );
10768					$panel.data( "destroy.tabs", true );
10769				}
10770				self.panels = self.panels.add( $panel );
10771			// invalid tab href
10772			} else {
10773				o.disabled.push( i );
10774			}
10775		});
10776
10777		// initialization from scratch
10778		if ( init ) {
10779			// attach necessary classes for styling
10780			this.element.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" );
10781			this.list.addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
10782			this.lis.addClass( "ui-state-default ui-corner-top" );
10783			this.panels.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" );
10784
10785			// Selected tab
10786			// use "selected" option or try to retrieve:
10787			// 1. from fragment identifier in url
10788			// 2. from cookie
10789			// 3. from selected class attribute on <li>
10790			if ( o.selected === undefined ) {
10791				if ( location.hash ) {
10792					this.anchors.each(function( i, a ) {
10793						if ( a.hash == location.hash ) {
10794							o.selected = i;
10795							return false;
10796						}
10797					});
10798				}
10799				if ( typeof o.selected !== "number" && o.cookie ) {
10800					o.selected = parseInt( self._cookie(), 10 );
10801				}
10802				if ( typeof o.selected !== "number" && this.lis.filter( ".ui-tabs-selected" ).length ) {
10803					o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
10804				}
10805				o.selected = o.selected || ( this.lis.length ? 0 : -1 );
10806			} else if ( o.selected === null ) { // usage of null is deprecated, TODO remove in next release
10807				o.selected = -1;
10808			}
10809
10810			// sanity check - default to first tab...
10811			o.selected = ( ( o.selected >= 0 && this.anchors[ o.selected ] ) || o.selected < 0 )
10812				? o.selected
10813				: 0;
10814
10815			// Take disabling tabs via class attribute from HTML
10816			// into account and update option properly.
10817			// A selected tab cannot become disabled.
10818			o.disabled = $.unique( o.disabled.concat(
10819				$.map( this.lis.filter( ".ui-state-disabled" ), function( n, i ) {
10820					return self.lis.index( n );
10821				})
10822			) ).sort();
10823
10824			if ( $.inArray( o.selected, o.disabled ) != -1 ) {
10825				o.disabled.splice( $.inArray( o.selected, o.disabled ), 1 );
10826			}
10827
10828			// highlight selected tab
10829			this.panels.addClass( "ui-tabs-hide" );
10830			this.lis.removeClass( "ui-tabs-selected ui-state-active" );
10831			// check for length avoids error when initializing empty list
10832			if ( o.selected >= 0 && this.anchors.length ) {
10833				self.element.find( self._sanitizeSelector( self.anchors[ o.selected ].hash ) ).removeClass( "ui-tabs-hide" );
10834				this.lis.eq( o.selected ).addClass( "ui-tabs-selected ui-state-active" );
10835
10836				// seems to be expected behavior that the show callback is fired
10837				self.element.queue( "tabs", function() {
10838					self._trigger( "show", null,
10839						self._ui( self.anchors[ o.selected ], self.element.find( self._sanitizeSelector( self.anchors[ o.selected ].hash ) )[ 0 ] ) );
10840				});
10841
10842				this.load( o.selected );
10843			}
10844
10845			// clean up to avoid memory leaks in certain versions of IE 6
10846			// TODO: namespace this event
10847			$( window ).bind( "unload", function() {
10848				self.lis.add( self.anchors ).unbind( ".tabs" );
10849				self.lis = self.anchors = self.panels = null;
10850			});
10851		// update selected after add/remove
10852		} else {
10853			o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
10854		}
10855
10856		// update collapsible
10857		// TODO: use .toggleClass()
10858		this.element[ o.collapsible ? "addClass" : "removeClass" ]( "ui-tabs-collapsible" );
10859
10860		// set or update cookie after init and add/remove respectively
10861		if ( o.cookie ) {
10862			this._cookie( o.selected, o.cookie );
10863		}
10864
10865		// disable tabs
10866		for ( var i = 0, li; ( li = this.lis[ i ] ); i++ ) {
10867			$( li )[ $.inArray( i, o.disabled ) != -1 &&
10868				// TODO: use .toggleClass()
10869				!$( li ).hasClass( "ui-tabs-selected" ) ? "addClass" : "removeClass" ]( "ui-state-disabled" );
10870		}
10871
10872		// reset cache if switching from cached to not cached
10873		if ( o.cache === false ) {
10874			this.anchors.removeData( "cache.tabs" );
10875		}
10876
10877		// remove all handlers before, tabify may run on existing tabs after add or option change
10878		this.lis.add( this.anchors ).unbind( ".tabs" );
10879
10880		if ( o.event !== "mouseover" ) {
10881			var addState = function( state, el ) {
10882				if ( el.is( ":not(.ui-state-disabled)" ) ) {
10883					el.addClass( "ui-state-" + state );
10884				}
10885			};
10886			var removeState = function( state, el ) {
10887				el.removeClass( "ui-state-" + state );
10888			};
10889			this.lis.bind( "mouseover.tabs" , function() {
10890				addState( "hover", $( this ) );
10891			});
10892			this.lis.bind( "mouseout.tabs", function() {
10893				removeState( "hover", $( this ) );
10894			});
10895			this.anchors.bind( "focus.tabs", function() {
10896				addState( "focus", $( this ).closest( "li" ) );
10897			});
10898			this.anchors.bind( "blur.tabs", function() {
10899				removeState( "focus", $( this ).closest( "li" ) );
10900			});
10901		}
10902
10903		// set up animations
10904		var hideFx, showFx;
10905		if ( o.fx ) {
10906			if ( $.isArray( o.fx ) ) {
10907				hideFx = o.fx[ 0 ];
10908				showFx = o.fx[ 1 ];
10909			} else {
10910				hideFx = showFx = o.fx;
10911			}
10912		}
10913
10914		// Reset certain styles left over from animation
10915		// and prevent IE's ClearType bug...
10916		function resetStyle( $el, fx ) {
10917			$el.css( "display", "" );
10918			if ( !$.support.opacity && fx.opacity ) {
10919				$el[ 0 ].style.removeAttribute( "filter" );
10920			}
10921		}
10922
10923		// Show a tab...
10924		var showTab = showFx
10925			? function( clicked, $show ) {
10926				$( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
10927				$show.hide().removeClass( "ui-tabs-hide" ) // avoid flicker that way
10928					.animate( showFx, showFx.duration || "normal", function() {
10929						resetStyle( $show, showFx );
10930						self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) );
10931					});
10932			}
10933			: function( clicked, $show ) {
10934				$( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
10935				$show.removeClass( "ui-tabs-hide" );
10936				self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) );
10937			};
10938
10939		// Hide a tab, $show is optional...
10940		var hideTab = hideFx
10941			? function( clicked, $hide ) {
10942				$hide.animate( hideFx, hideFx.duration || "normal", function() {
10943					self.lis.removeClass( "ui-tabs-selected ui-state-active" );
10944					$hide.addClass( "ui-tabs-hide" );
10945					resetStyle( $hide, hideFx );
10946					self.element.dequeue( "tabs" );
10947				});
10948			}
10949			: function( clicked, $hide, $show ) {
10950				self.lis.removeClass( "ui-tabs-selected ui-state-active" );
10951				$hide.addClass( "ui-tabs-hide" );
10952				self.element.dequeue( "tabs" );
10953			};
10954
10955		// attach tab event handler, unbind to avoid duplicates from former tabifying...
10956		this.anchors.bind( o.event + ".tabs", function() {
10957			var el = this,
10958				$li = $(el).closest( "li" ),
10959				$hide = self.panels.filter( ":not(.ui-tabs-hide)" ),
10960				$show = self.element.find( self._sanitizeSelector( el.hash ) );
10961
10962			// If tab is already selected and not collapsible or tab disabled or
10963			// or is already loading or click callback returns false stop here.
10964			// Check if click handler returns false last so that it is not executed
10965			// for a disabled or loading tab!
10966			if ( ( $li.hasClass( "ui-tabs-selected" ) && !o.collapsible) ||
10967				$li.hasClass( "ui-state-disabled" ) ||
10968				$li.hasClass( "ui-state-processing" ) ||
10969				self.panels.filter( ":animated" ).length ||
10970				self._trigger( "select", null, self._ui( this, $show[ 0 ] ) ) === false ) {
10971				this.blur();
10972				return false;
10973			}
10974
10975			o.selected = self.anchors.index( this );
10976
10977			self.abort();
10978
10979			// if tab may be closed
10980			if ( o.collapsible ) {
10981				if ( $li.hasClass( "ui-tabs-selected" ) ) {
10982					o.selected = -1;
10983
10984					if ( o.cookie ) {
10985						self._cookie( o.selected, o.cookie );
10986					}
10987
10988					self.element.queue( "tabs", function() {
10989						hideTab( el, $hide );
10990					}).dequeue( "tabs" );
10991
10992					this.blur();
10993					return false;
10994				} else if ( !$hide.length ) {
10995					if ( o.cookie ) {
10996						self._cookie( o.selected, o.cookie );
10997					}
10998
10999					self.element.queue( "tabs", function() {
11000						showTab( el, $show );
11001					});
11002
11003					// TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171
11004					self.load( self.anchors.index( this ) );
11005
11006					this.blur();
11007					return false;
11008				}
11009			}
11010
11011			if ( o.cookie ) {
11012				self._cookie( o.selected, o.cookie );
11013			}
11014
11015			// show new tab
11016			if ( $show.length ) {
11017				if ( $hide.length ) {
11018					self.element.queue( "tabs", function() {
11019						hideTab( el, $hide );
11020					});
11021				}
11022				self.element.queue( "tabs", function() {
11023					showTab( el, $show );
11024				});
11025
11026				self.load( self.anchors.index( this ) );
11027			} else {
11028				throw "jQuery UI Tabs: Mismatching fragment identifier.";
11029			}
11030
11031			// Prevent IE from keeping other link focussed when using the back button
11032			// and remove dotted border from clicked link. This is controlled via CSS
11033			// in modern browsers; blur() removes focus from address bar in Firefox
11034			// which can become a usability and annoying problem with tabs('rotate').
11035			if ( $.browser.msie ) {
11036				this.blur();
11037			}
11038		});
11039
11040		// disable click in any case
11041		this.anchors.bind( "click.tabs", function(){
11042			return false;
11043		});
11044	},
11045
11046    _getIndex: function( index ) {
11047		// meta-function to give users option to provide a href string instead of a numerical index.
11048		// also sanitizes numerical indexes to valid values.
11049		if ( typeof index == "string" ) {
11050			index = this.anchors.index( this.anchors.filter( "[href$='" + index + "']" ) );
11051		}
11052
11053		return index;
11054	},
11055
11056	destroy: function() {
11057		var o = this.options;
11058
11059		this.abort();
11060
11061		this.element
11062			.unbind( ".tabs" )
11063			.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" )
11064			.removeData( "tabs" );
11065
11066		this.list.removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
11067
11068		this.anchors.each(function() {
11069			var href = $.data( this, "href.tabs" );
11070			if ( href ) {
11071				this.href = href;
11072			}
11073			var $this = $( this ).unbind( ".tabs" );
11074			$.each( [ "href", "load", "cache" ], function( i, prefix ) {
11075				$this.removeData( prefix + ".tabs" );
11076			});
11077		});
11078
11079		this.lis.unbind( ".tabs" ).add( this.panels ).each(function() {
11080			if ( $.data( this, "destroy.tabs" ) ) {
11081				$( this ).remove();
11082			} else {
11083				$( this ).removeClass([
11084					"ui-state-default",
11085					"ui-corner-top",
11086					"ui-tabs-selected",
11087					"ui-state-active",
11088					"ui-state-hover",
11089					"ui-state-focus",
11090					"ui-state-disabled",
11091					"ui-tabs-panel",
11092					"ui-widget-content",
11093					"ui-corner-bottom",
11094					"ui-tabs-hide"
11095				].join( " " ) );
11096			}
11097		});
11098
11099		if ( o.cookie ) {
11100			this._cookie( null, o.cookie );
11101		}
11102
11103		return this;
11104	},
11105
11106	add: function( url, label, index ) {
11107		if ( index === undefined ) {
11108			index = this.anchors.length;
11109		}
11110
11111		var self = this,
11112			o = this.options,
11113			$li = $( o.tabTemplate.replace( /#\{href\}/g, url ).replace( /#\{label\}/g, label ) ),
11114			id = !url.indexOf( "#" ) ? url.replace( "#", "" ) : this._tabId( $( "a", $li )[ 0 ] );
11115
11116		$li.addClass( "ui-state-default ui-corner-top" ).data( "destroy.tabs", true );
11117
11118		// try to find an existing element before creating a new one
11119		var $panel = self.element.find( "#" + id );
11120		if ( !$panel.length ) {
11121			$panel = $( o.panelTemplate )
11122				.attr( "id", id )
11123				.data( "destroy.tabs", true );
11124		}
11125		$panel.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide" );
11126
11127		if ( index >= this.lis.length ) {
11128			$li.appendTo( this.list );
11129			$panel.appendTo( this.list[ 0 ].parentNode );
11130		} else {
11131			$li.insertBefore( this.lis[ index ] );
11132			$panel.insertBefore( this.panels[ index ] );
11133		}
11134
11135		o.disabled = $.map( o.disabled, function( n, i ) {
11136			return n >= index ? ++n : n;
11137		});
11138
11139		this._tabify();
11140
11141		if ( this.anchors.length == 1 ) {
11142			o.selected = 0;
11143			$li.addClass( "ui-tabs-selected ui-state-active" );
11144			$panel.removeClass( "ui-tabs-hide" );
11145			this.element.queue( "tabs", function() {
11146				self._trigger( "show", null, self._ui( self.anchors[ 0 ], self.panels[ 0 ] ) );
11147			});
11148
11149			this.load( 0 );
11150		}
11151
11152		this._trigger( "add", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
11153		return this;
11154	},
11155
11156	remove: function( index ) {
11157		index = this._getIndex( index );
11158		var o = this.options,
11159			$li = this.lis.eq( index ).remove(),
11160			$panel = this.panels.eq( index ).remove();
11161
11162		// If selected tab was removed focus tab to the right or
11163		// in case the last tab was removed the tab to the left.
11164		if ( $li.hasClass( "ui-tabs-selected" ) && this.anchors.length > 1) {
11165			this.select( index + ( index + 1 < this.anchors.length ? 1 : -1 ) );
11166		}
11167
11168		o.disabled = $.map(
11169			$.grep( o.disabled, function(n, i) {
11170				return n != index;
11171			}),
11172			function( n, i ) {
11173				return n >= index ? --n : n;
11174			});
11175
11176		this._tabify();
11177
11178		this._trigger( "remove", null, this._ui( $li.find( "a" )[ 0 ], $panel[ 0 ] ) );
11179		return this;
11180	},
11181
11182	enable: function( index ) {
11183		index = this._getIndex( index );
11184		var o = this.options;
11185		if ( $.inArray( index, o.disabled ) == -1 ) {
11186			return;
11187		}
11188
11189		this.lis.eq( index ).removeClass( "ui-state-disabled" );
11190		o.disabled = $.grep( o.disabled, function( n, i ) {
11191			return n != index;
11192		});
11193
11194		this._trigger( "enable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
11195		return this;
11196	},
11197
11198	disable: function( index ) {
11199		index = this._getIndex( index );
11200		var self = this, o = this.options;
11201		// cannot disable already selected tab
11202		if ( index != o.selected ) {
11203			this.lis.eq( index ).addClass( "ui-state-disabled" );
11204
11205			o.disabled.push( index );
11206			o.disabled.sort();
11207
11208			this._trigger( "disable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
11209		}
11210
11211		return this;
11212	},
11213
11214	select: function( index ) {
11215		index = this._getIndex( index );
11216		if ( index == -1 ) {
11217			if ( this.options.collapsible && this.options.selected != -1 ) {
11218				index = this.options.selected;
11219			} else {
11220				return this;
11221			}
11222		}
11223		this.anchors.eq( index ).trigger( this.options.event + ".tabs" );
11224		return this;
11225	},
11226
11227	load: function( index ) {
11228		index = this._getIndex( index );
11229		var self = this,
11230			o = this.options,
11231			a = this.anchors.eq( index )[ 0 ],
11232			url = $.data( a, "load.tabs" );
11233
11234		this.abort();
11235
11236		// not remote or from cache
11237		if ( !url || this.element.queue( "tabs" ).length !== 0 && $.data( a, "cache.tabs" ) ) {
11238			this.element.dequeue( "tabs" );
11239			return;
11240		}
11241
11242		// load remote from here on
11243		this.lis.eq( index ).addClass( "ui-state-processing" );
11244
11245		if ( o.spinner ) {
11246			var span = $( "span", a );
11247			span.data( "label.tabs", span.html() ).html( o.spinner );
11248		}
11249
11250		this.xhr = $.ajax( $.extend( {}, o.ajaxOptions, {
11251			url: url,
11252			success: function( r, s ) {
11253				self.element.find( self._sanitizeSelector( a.hash ) ).html( r );
11254
11255				// take care of tab labels
11256				self._cleanup();
11257
11258				if ( o.cache ) {
11259					$.data( a, "cache.tabs", true );
11260				}
11261
11262				self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
11263				try {
11264					o.ajaxOptions.success( r, s );
11265				}
11266				catch ( e ) {}
11267			},
11268			error: function( xhr, s, e ) {
11269				// take care of tab labels
11270				self._cleanup();
11271
11272				self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
11273				try {
11274					// Passing index avoid a race condition when this method is
11275					// called after the user has selected another tab.
11276					// Pass the anchor that initiated this request allows
11277					// loadError to manipulate the tab content panel via $(a.hash)
11278					o.ajaxOptions.error( xhr, s, index, a );
11279				}
11280				catch ( e ) {}
11281			}
11282		} ) );
11283
11284		// last, so that load event is fired before show...
11285		self.element.dequeue( "tabs" );
11286
11287		return this;
11288	},
11289
11290	abort: function() {
11291		// stop possibly running animations
11292		this.element.queue( [] );
11293		this.panels.stop( false, true );
11294
11295		// "tabs" queue must not contain more than two elements,
11296		// which are the callbacks for the latest clicked tab...
11297		this.element.queue( "tabs", this.element.queue( "tabs" ).splice( -2, 2 ) );
11298
11299		// terminate pending requests from other tabs
11300		if ( this.xhr ) {
11301			this.xhr.abort();
11302			delete this.xhr;
11303		}
11304
11305		// take care of tab labels
11306		this._cleanup();
11307		return this;
11308	},
11309
11310	url: function( index, url ) {
11311		this.anchors.eq( index ).removeData( "cache.tabs" ).data( "load.tabs", url );
11312		return this;
11313	},
11314
11315	length: function() {
11316		return this.anchors.length;
11317	}
11318});
11319
11320$.extend( $.ui.tabs, {
11321	version: "1.8.24"
11322});
11323
11324/*
11325 * Tabs Extensions
11326 */
11327
11328/*
11329 * Rotate
11330 */
11331$.extend( $.ui.tabs.prototype, {
11332	rotation: null,
11333	rotate: function( ms, continuing ) {
11334		var self = this,
11335			o = this.options;
11336
11337		var rotate = self._rotate || ( self._rotate = function( e ) {
11338			clearTimeout( self.rotation );
11339			self.rotation = setTimeout(function() {
11340				var t = o.selected;
11341				self.select( ++t < self.anchors.length ? t : 0 );
11342			}, ms );
11343			
11344			if ( e ) {
11345				e.stopPropagation();
11346			}
11347		});
11348
11349		var stop = self._unrotate || ( self._unrotate = !continuing
11350			? function(e) {
11351				if (e.clientX) { // in case of a true click
11352					self.rotate(null);
11353				}
11354			}
11355			: function( e ) {
11356				rotate();
11357			});
11358
11359		// start rotation
11360		if ( ms ) {
11361			this.element.bind( "tabsshow", rotate );
11362			this.anchors.bind( o.event + ".tabs", stop );
11363			rotate();
11364		// stop rotation
11365		} else {
11366			clearTimeout( self.rotation );
11367			this.element.unbind( "tabsshow", rotate );
11368			this.anchors.unbind( o.event + ".tabs", stop );
11369			delete this._rotate;
11370			delete this._unrotate;
11371		}
11372
11373		return this;
11374	}
11375});
11376
11377})( jQuery );

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.