balmet.com

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

jquery-ui.js (539425B)


      1 /*! jQuery UI - v1.12.1 - 2016-09-14
      2 * http://jqueryui.com
      3 * Includes: widget.js, position.js, data.js, disable-selection.js, effect.js, effects/effect-blind.js, effects/effect-bounce.js, effects/effect-clip.js, effects/effect-drop.js, effects/effect-explode.js, effects/effect-fade.js, effects/effect-fold.js, effects/effect-highlight.js, effects/effect-puff.js, effects/effect-pulsate.js, effects/effect-scale.js, effects/effect-shake.js, effects/effect-size.js, effects/effect-slide.js, effects/effect-transfer.js, focusable.js, form-reset-mixin.js, jquery-1-7.js, keycode.js, labels.js, scroll-parent.js, tabbable.js, unique-id.js, widgets/accordion.js, widgets/autocomplete.js, widgets/button.js, widgets/checkboxradio.js, widgets/controlgroup.js, widgets/datepicker.js, widgets/dialog.js, widgets/draggable.js, widgets/droppable.js, widgets/menu.js, widgets/mouse.js, widgets/progressbar.js, widgets/resizable.js, widgets/selectable.js, widgets/selectmenu.js, widgets/slider.js, widgets/sortable.js, widgets/spinner.js, widgets/tabs.js, widgets/tooltip.js
      4 * Copyright jQuery Foundation and other contributors; Licensed MIT */
      5 
      6 (function( factory ) {
      7 	if ( typeof define === "function" && define.amd ) {
      8 
      9 		// AMD. Register as an anonymous module.
     10 		define([ "jquery" ], factory );
     11 	} else {
     12 
     13 		// Browser globals
     14 		factory( jQuery );
     15 	}
     16 }(function( $ ) {
     17 
     18 $.ui = $.ui || {};
     19 
     20 var version = $.ui.version = "1.12.1";
     21 
     22 
     23 /*!
     24  * jQuery UI Widget 1.12.1
     25  * http://jqueryui.com
     26  *
     27  * Copyright jQuery Foundation and other contributors
     28  * Released under the MIT license.
     29  * http://jquery.org/license
     30  */
     31 
     32 //>>label: Widget
     33 //>>group: Core
     34 //>>description: Provides a factory for creating stateful widgets with a common API.
     35 //>>docs: http://api.jqueryui.com/jQuery.widget/
     36 //>>demos: http://jqueryui.com/widget/
     37 
     38 
     39 
     40 var widgetUuid = 0;
     41 var widgetSlice = Array.prototype.slice;
     42 
     43 $.cleanData = ( function( orig ) {
     44 	return function( elems ) {
     45 		var events, elem, i;
     46 		for ( i = 0; ( elem = elems[ i ] ) != null; i++ ) {
     47 			try {
     48 
     49 				// Only trigger remove when necessary to save time
     50 				events = $._data( elem, "events" );
     51 				if ( events && events.remove ) {
     52 					$( elem ).triggerHandler( "remove" );
     53 				}
     54 
     55 			// Http://bugs.jquery.com/ticket/8235
     56 			} catch ( e ) {}
     57 		}
     58 		orig( elems );
     59 	};
     60 } )( $.cleanData );
     61 
     62 $.widget = function( name, base, prototype ) {
     63 	var existingConstructor, constructor, basePrototype;
     64 
     65 	// ProxiedPrototype allows the provided prototype to remain unmodified
     66 	// so that it can be used as a mixin for multiple widgets (#8876)
     67 	var proxiedPrototype = {};
     68 
     69 	var namespace = name.split( "." )[ 0 ];
     70 	name = name.split( "." )[ 1 ];
     71 	var fullName = namespace + "-" + name;
     72 
     73 	if ( !prototype ) {
     74 		prototype = base;
     75 		base = $.Widget;
     76 	}
     77 
     78 	if ( $.isArray( prototype ) ) {
     79 		prototype = $.extend.apply( null, [ {} ].concat( prototype ) );
     80 	}
     81 
     82 	// Create selector for plugin
     83 	$.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
     84 		return !!$.data( elem, fullName );
     85 	};
     86 
     87 	$[ namespace ] = $[ namespace ] || {};
     88 	existingConstructor = $[ namespace ][ name ];
     89 	constructor = $[ namespace ][ name ] = function( options, element ) {
     90 
     91 		// Allow instantiation without "new" keyword
     92 		if ( !this._createWidget ) {
     93 			return new constructor( options, element );
     94 		}
     95 
     96 		// Allow instantiation without initializing for simple inheritance
     97 		// must use "new" keyword (the code above always passes args)
     98 		if ( arguments.length ) {
     99 			this._createWidget( options, element );
    100 		}
    101 	};
    102 
    103 	// Extend with the existing constructor to carry over any static properties
    104 	$.extend( constructor, existingConstructor, {
    105 		version: prototype.version,
    106 
    107 		// Copy the object used to create the prototype in case we need to
    108 		// redefine the widget later
    109 		_proto: $.extend( {}, prototype ),
    110 
    111 		// Track widgets that inherit from this widget in case this widget is
    112 		// redefined after a widget inherits from it
    113 		_childConstructors: []
    114 	} );
    115 
    116 	basePrototype = new base();
    117 
    118 	// We need to make the options hash a property directly on the new instance
    119 	// otherwise we'll modify the options hash on the prototype that we're
    120 	// inheriting from
    121 	basePrototype.options = $.widget.extend( {}, basePrototype.options );
    122 	$.each( prototype, function( prop, value ) {
    123 		if ( !$.isFunction( value ) ) {
    124 			proxiedPrototype[ prop ] = value;
    125 			return;
    126 		}
    127 		proxiedPrototype[ prop ] = ( function() {
    128 			function _super() {
    129 				return base.prototype[ prop ].apply( this, arguments );
    130 			}
    131 
    132 			function _superApply( args ) {
    133 				return base.prototype[ prop ].apply( this, args );
    134 			}
    135 
    136 			return function() {
    137 				var __super = this._super;
    138 				var __superApply = this._superApply;
    139 				var returnValue;
    140 
    141 				this._super = _super;
    142 				this._superApply = _superApply;
    143 
    144 				returnValue = value.apply( this, arguments );
    145 
    146 				this._super = __super;
    147 				this._superApply = __superApply;
    148 
    149 				return returnValue;
    150 			};
    151 		} )();
    152 	} );
    153 	constructor.prototype = $.widget.extend( basePrototype, {
    154 
    155 		// TODO: remove support for widgetEventPrefix
    156 		// always use the name + a colon as the prefix, e.g., draggable:start
    157 		// don't prefix for widgets that aren't DOM-based
    158 		widgetEventPrefix: existingConstructor ? ( basePrototype.widgetEventPrefix || name ) : name
    159 	}, proxiedPrototype, {
    160 		constructor: constructor,
    161 		namespace: namespace,
    162 		widgetName: name,
    163 		widgetFullName: fullName
    164 	} );
    165 
    166 	// If this widget is being redefined then we need to find all widgets that
    167 	// are inheriting from it and redefine all of them so that they inherit from
    168 	// the new version of this widget. We're essentially trying to replace one
    169 	// level in the prototype chain.
    170 	if ( existingConstructor ) {
    171 		$.each( existingConstructor._childConstructors, function( i, child ) {
    172 			var childPrototype = child.prototype;
    173 
    174 			// Redefine the child widget using the same prototype that was
    175 			// originally used, but inherit from the new version of the base
    176 			$.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor,
    177 				child._proto );
    178 		} );
    179 
    180 		// Remove the list of existing child constructors from the old constructor
    181 		// so the old child constructors can be garbage collected
    182 		delete existingConstructor._childConstructors;
    183 	} else {
    184 		base._childConstructors.push( constructor );
    185 	}
    186 
    187 	$.widget.bridge( name, constructor );
    188 
    189 	return constructor;
    190 };
    191 
    192 $.widget.extend = function( target ) {
    193 	var input = widgetSlice.call( arguments, 1 );
    194 	var inputIndex = 0;
    195 	var inputLength = input.length;
    196 	var key;
    197 	var value;
    198 
    199 	for ( ; inputIndex < inputLength; inputIndex++ ) {
    200 		for ( key in input[ inputIndex ] ) {
    201 			value = input[ inputIndex ][ key ];
    202 			if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
    203 
    204 				// Clone objects
    205 				if ( $.isPlainObject( value ) ) {
    206 					target[ key ] = $.isPlainObject( target[ key ] ) ?
    207 						$.widget.extend( {}, target[ key ], value ) :
    208 
    209 						// Don't extend strings, arrays, etc. with objects
    210 						$.widget.extend( {}, value );
    211 
    212 				// Copy everything else by reference
    213 				} else {
    214 					target[ key ] = value;
    215 				}
    216 			}
    217 		}
    218 	}
    219 	return target;
    220 };
    221 
    222 $.widget.bridge = function( name, object ) {
    223 	var fullName = object.prototype.widgetFullName || name;
    224 	$.fn[ name ] = function( options ) {
    225 		var isMethodCall = typeof options === "string";
    226 		var args = widgetSlice.call( arguments, 1 );
    227 		var returnValue = this;
    228 
    229 		if ( isMethodCall ) {
    230 
    231 			// If this is an empty collection, we need to have the instance method
    232 			// return undefined instead of the jQuery instance
    233 			if ( !this.length && options === "instance" ) {
    234 				returnValue = undefined;
    235 			} else {
    236 				this.each( function() {
    237 					var methodValue;
    238 					var instance = $.data( this, fullName );
    239 
    240 					if ( options === "instance" ) {
    241 						returnValue = instance;
    242 						return false;
    243 					}
    244 
    245 					if ( !instance ) {
    246 						return $.error( "cannot call methods on " + name +
    247 							" prior to initialization; " +
    248 							"attempted to call method '" + options + "'" );
    249 					}
    250 
    251 					if ( !$.isFunction( instance[ options ] ) || options.charAt( 0 ) === "_" ) {
    252 						return $.error( "no such method '" + options + "' for " + name +
    253 							" widget instance" );
    254 					}
    255 
    256 					methodValue = instance[ options ].apply( instance, args );
    257 
    258 					if ( methodValue !== instance && methodValue !== undefined ) {
    259 						returnValue = methodValue && methodValue.jquery ?
    260 							returnValue.pushStack( methodValue.get() ) :
    261 							methodValue;
    262 						return false;
    263 					}
    264 				} );
    265 			}
    266 		} else {
    267 
    268 			// Allow multiple hashes to be passed on init
    269 			if ( args.length ) {
    270 				options = $.widget.extend.apply( null, [ options ].concat( args ) );
    271 			}
    272 
    273 			this.each( function() {
    274 				var instance = $.data( this, fullName );
    275 				if ( instance ) {
    276 					instance.option( options || {} );
    277 					if ( instance._init ) {
    278 						instance._init();
    279 					}
    280 				} else {
    281 					$.data( this, fullName, new object( options, this ) );
    282 				}
    283 			} );
    284 		}
    285 
    286 		return returnValue;
    287 	};
    288 };
    289 
    290 $.Widget = function( /* options, element */ ) {};
    291 $.Widget._childConstructors = [];
    292 
    293 $.Widget.prototype = {
    294 	widgetName: "widget",
    295 	widgetEventPrefix: "",
    296 	defaultElement: "<div>",
    297 
    298 	options: {
    299 		classes: {},
    300 		disabled: false,
    301 
    302 		// Callbacks
    303 		create: null
    304 	},
    305 
    306 	_createWidget: function( options, element ) {
    307 		element = $( element || this.defaultElement || this )[ 0 ];
    308 		this.element = $( element );
    309 		this.uuid = widgetUuid++;
    310 		this.eventNamespace = "." + this.widgetName + this.uuid;
    311 
    312 		this.bindings = $();
    313 		this.hoverable = $();
    314 		this.focusable = $();
    315 		this.classesElementLookup = {};
    316 
    317 		if ( element !== this ) {
    318 			$.data( element, this.widgetFullName, this );
    319 			this._on( true, this.element, {
    320 				remove: function( event ) {
    321 					if ( event.target === element ) {
    322 						this.destroy();
    323 					}
    324 				}
    325 			} );
    326 			this.document = $( element.style ?
    327 
    328 				// Element within the document
    329 				element.ownerDocument :
    330 
    331 				// Element is window or document
    332 				element.document || element );
    333 			this.window = $( this.document[ 0 ].defaultView || this.document[ 0 ].parentWindow );
    334 		}
    335 
    336 		this.options = $.widget.extend( {},
    337 			this.options,
    338 			this._getCreateOptions(),
    339 			options );
    340 
    341 		this._create();
    342 
    343 		if ( this.options.disabled ) {
    344 			this._setOptionDisabled( this.options.disabled );
    345 		}
    346 
    347 		this._trigger( "create", null, this._getCreateEventData() );
    348 		this._init();
    349 	},
    350 
    351 	_getCreateOptions: function() {
    352 		return {};
    353 	},
    354 
    355 	_getCreateEventData: $.noop,
    356 
    357 	_create: $.noop,
    358 
    359 	_init: $.noop,
    360 
    361 	destroy: function() {
    362 		var that = this;
    363 
    364 		this._destroy();
    365 		$.each( this.classesElementLookup, function( key, value ) {
    366 			that._removeClass( value, key );
    367 		} );
    368 
    369 		// We can probably remove the unbind calls in 2.0
    370 		// all event bindings should go through this._on()
    371 		this.element
    372 			.off( this.eventNamespace )
    373 			.removeData( this.widgetFullName );
    374 		this.widget()
    375 			.off( this.eventNamespace )
    376 			.removeAttr( "aria-disabled" );
    377 
    378 		// Clean up events and states
    379 		this.bindings.off( this.eventNamespace );
    380 	},
    381 
    382 	_destroy: $.noop,
    383 
    384 	widget: function() {
    385 		return this.element;
    386 	},
    387 
    388 	option: function( key, value ) {
    389 		var options = key;
    390 		var parts;
    391 		var curOption;
    392 		var i;
    393 
    394 		if ( arguments.length === 0 ) {
    395 
    396 			// Don't return a reference to the internal hash
    397 			return $.widget.extend( {}, this.options );
    398 		}
    399 
    400 		if ( typeof key === "string" ) {
    401 
    402 			// Handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
    403 			options = {};
    404 			parts = key.split( "." );
    405 			key = parts.shift();
    406 			if ( parts.length ) {
    407 				curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
    408 				for ( i = 0; i < parts.length - 1; i++ ) {
    409 					curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
    410 					curOption = curOption[ parts[ i ] ];
    411 				}
    412 				key = parts.pop();
    413 				if ( arguments.length === 1 ) {
    414 					return curOption[ key ] === undefined ? null : curOption[ key ];
    415 				}
    416 				curOption[ key ] = value;
    417 			} else {
    418 				if ( arguments.length === 1 ) {
    419 					return this.options[ key ] === undefined ? null : this.options[ key ];
    420 				}
    421 				options[ key ] = value;
    422 			}
    423 		}
    424 
    425 		this._setOptions( options );
    426 
    427 		return this;
    428 	},
    429 
    430 	_setOptions: function( options ) {
    431 		var key;
    432 
    433 		for ( key in options ) {
    434 			this._setOption( key, options[ key ] );
    435 		}
    436 
    437 		return this;
    438 	},
    439 
    440 	_setOption: function( key, value ) {
    441 		if ( key === "classes" ) {
    442 			this._setOptionClasses( value );
    443 		}
    444 
    445 		this.options[ key ] = value;
    446 
    447 		if ( key === "disabled" ) {
    448 			this._setOptionDisabled( value );
    449 		}
    450 
    451 		return this;
    452 	},
    453 
    454 	_setOptionClasses: function( value ) {
    455 		var classKey, elements, currentElements;
    456 
    457 		for ( classKey in value ) {
    458 			currentElements = this.classesElementLookup[ classKey ];
    459 			if ( value[ classKey ] === this.options.classes[ classKey ] ||
    460 					!currentElements ||
    461 					!currentElements.length ) {
    462 				continue;
    463 			}
    464 
    465 			// We are doing this to create a new jQuery object because the _removeClass() call
    466 			// on the next line is going to destroy the reference to the current elements being
    467 			// tracked. We need to save a copy of this collection so that we can add the new classes
    468 			// below.
    469 			elements = $( currentElements.get() );
    470 			this._removeClass( currentElements, classKey );
    471 
    472 			// We don't use _addClass() here, because that uses this.options.classes
    473 			// for generating the string of classes. We want to use the value passed in from
    474 			// _setOption(), this is the new value of the classes option which was passed to
    475 			// _setOption(). We pass this value directly to _classes().
    476 			elements.addClass( this._classes( {
    477 				element: elements,
    478 				keys: classKey,
    479 				classes: value,
    480 				add: true
    481 			} ) );
    482 		}
    483 	},
    484 
    485 	_setOptionDisabled: function( value ) {
    486 		this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null, !!value );
    487 
    488 		// If the widget is becoming disabled, then nothing is interactive
    489 		if ( value ) {
    490 			this._removeClass( this.hoverable, null, "ui-state-hover" );
    491 			this._removeClass( this.focusable, null, "ui-state-focus" );
    492 		}
    493 	},
    494 
    495 	enable: function() {
    496 		return this._setOptions( { disabled: false } );
    497 	},
    498 
    499 	disable: function() {
    500 		return this._setOptions( { disabled: true } );
    501 	},
    502 
    503 	_classes: function( options ) {
    504 		var full = [];
    505 		var that = this;
    506 
    507 		options = $.extend( {
    508 			element: this.element,
    509 			classes: this.options.classes || {}
    510 		}, options );
    511 
    512 		function processClassString( classes, checkOption ) {
    513 			var current, i;
    514 			for ( i = 0; i < classes.length; i++ ) {
    515 				current = that.classesElementLookup[ classes[ i ] ] || $();
    516 				if ( options.add ) {
    517 					current = $( $.unique( current.get().concat( options.element.get() ) ) );
    518 				} else {
    519 					current = $( current.not( options.element ).get() );
    520 				}
    521 				that.classesElementLookup[ classes[ i ] ] = current;
    522 				full.push( classes[ i ] );
    523 				if ( checkOption && options.classes[ classes[ i ] ] ) {
    524 					full.push( options.classes[ classes[ i ] ] );
    525 				}
    526 			}
    527 		}
    528 
    529 		this._on( options.element, {
    530 			"remove": "_untrackClassesElement"
    531 		} );
    532 
    533 		if ( options.keys ) {
    534 			processClassString( options.keys.match( /\S+/g ) || [], true );
    535 		}
    536 		if ( options.extra ) {
    537 			processClassString( options.extra.match( /\S+/g ) || [] );
    538 		}
    539 
    540 		return full.join( " " );
    541 	},
    542 
    543 	_untrackClassesElement: function( event ) {
    544 		var that = this;
    545 		$.each( that.classesElementLookup, function( key, value ) {
    546 			if ( $.inArray( event.target, value ) !== -1 ) {
    547 				that.classesElementLookup[ key ] = $( value.not( event.target ).get() );
    548 			}
    549 		} );
    550 	},
    551 
    552 	_removeClass: function( element, keys, extra ) {
    553 		return this._toggleClass( element, keys, extra, false );
    554 	},
    555 
    556 	_addClass: function( element, keys, extra ) {
    557 		return this._toggleClass( element, keys, extra, true );
    558 	},
    559 
    560 	_toggleClass: function( element, keys, extra, add ) {
    561 		add = ( typeof add === "boolean" ) ? add : extra;
    562 		var shift = ( typeof element === "string" || element === null ),
    563 			options = {
    564 				extra: shift ? keys : extra,
    565 				keys: shift ? element : keys,
    566 				element: shift ? this.element : element,
    567 				add: add
    568 			};
    569 		options.element.toggleClass( this._classes( options ), add );
    570 		return this;
    571 	},
    572 
    573 	_on: function( suppressDisabledCheck, element, handlers ) {
    574 		var delegateElement;
    575 		var instance = this;
    576 
    577 		// No suppressDisabledCheck flag, shuffle arguments
    578 		if ( typeof suppressDisabledCheck !== "boolean" ) {
    579 			handlers = element;
    580 			element = suppressDisabledCheck;
    581 			suppressDisabledCheck = false;
    582 		}
    583 
    584 		// No element argument, shuffle and use this.element
    585 		if ( !handlers ) {
    586 			handlers = element;
    587 			element = this.element;
    588 			delegateElement = this.widget();
    589 		} else {
    590 			element = delegateElement = $( element );
    591 			this.bindings = this.bindings.add( element );
    592 		}
    593 
    594 		$.each( handlers, function( event, handler ) {
    595 			function handlerProxy() {
    596 
    597 				// Allow widgets to customize the disabled handling
    598 				// - disabled as an array instead of boolean
    599 				// - disabled class as method for disabling individual parts
    600 				if ( !suppressDisabledCheck &&
    601 						( instance.options.disabled === true ||
    602 						$( this ).hasClass( "ui-state-disabled" ) ) ) {
    603 					return;
    604 				}
    605 				return ( typeof handler === "string" ? instance[ handler ] : handler )
    606 					.apply( instance, arguments );
    607 			}
    608 
    609 			// Copy the guid so direct unbinding works
    610 			if ( typeof handler !== "string" ) {
    611 				handlerProxy.guid = handler.guid =
    612 					handler.guid || handlerProxy.guid || $.guid++;
    613 			}
    614 
    615 			var match = event.match( /^([\w:-]*)\s*(.*)$/ );
    616 			var eventName = match[ 1 ] + instance.eventNamespace;
    617 			var selector = match[ 2 ];
    618 
    619 			if ( selector ) {
    620 				delegateElement.on( eventName, selector, handlerProxy );
    621 			} else {
    622 				element.on( eventName, handlerProxy );
    623 			}
    624 		} );
    625 	},
    626 
    627 	_off: function( element, eventName ) {
    628 		eventName = ( eventName || "" ).split( " " ).join( this.eventNamespace + " " ) +
    629 			this.eventNamespace;
    630 		element.off( eventName ).off( eventName );
    631 
    632 		// Clear the stack to avoid memory leaks (#10056)
    633 		this.bindings = $( this.bindings.not( element ).get() );
    634 		this.focusable = $( this.focusable.not( element ).get() );
    635 		this.hoverable = $( this.hoverable.not( element ).get() );
    636 	},
    637 
    638 	_delay: function( handler, delay ) {
    639 		function handlerProxy() {
    640 			return ( typeof handler === "string" ? instance[ handler ] : handler )
    641 				.apply( instance, arguments );
    642 		}
    643 		var instance = this;
    644 		return setTimeout( handlerProxy, delay || 0 );
    645 	},
    646 
    647 	_hoverable: function( element ) {
    648 		this.hoverable = this.hoverable.add( element );
    649 		this._on( element, {
    650 			mouseenter: function( event ) {
    651 				this._addClass( $( event.currentTarget ), null, "ui-state-hover" );
    652 			},
    653 			mouseleave: function( event ) {
    654 				this._removeClass( $( event.currentTarget ), null, "ui-state-hover" );
    655 			}
    656 		} );
    657 	},
    658 
    659 	_focusable: function( element ) {
    660 		this.focusable = this.focusable.add( element );
    661 		this._on( element, {
    662 			focusin: function( event ) {
    663 				this._addClass( $( event.currentTarget ), null, "ui-state-focus" );
    664 			},
    665 			focusout: function( event ) {
    666 				this._removeClass( $( event.currentTarget ), null, "ui-state-focus" );
    667 			}
    668 		} );
    669 	},
    670 
    671 	_trigger: function( type, event, data ) {
    672 		var prop, orig;
    673 		var callback = this.options[ type ];
    674 
    675 		data = data || {};
    676 		event = $.Event( event );
    677 		event.type = ( type === this.widgetEventPrefix ?
    678 			type :
    679 			this.widgetEventPrefix + type ).toLowerCase();
    680 
    681 		// The original event may come from any element
    682 		// so we need to reset the target on the new event
    683 		event.target = this.element[ 0 ];
    684 
    685 		// Copy original event properties over to the new event
    686 		orig = event.originalEvent;
    687 		if ( orig ) {
    688 			for ( prop in orig ) {
    689 				if ( !( prop in event ) ) {
    690 					event[ prop ] = orig[ prop ];
    691 				}
    692 			}
    693 		}
    694 
    695 		this.element.trigger( event, data );
    696 		return !( $.isFunction( callback ) &&
    697 			callback.apply( this.element[ 0 ], [ event ].concat( data ) ) === false ||
    698 			event.isDefaultPrevented() );
    699 	}
    700 };
    701 
    702 $.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
    703 	$.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
    704 		if ( typeof options === "string" ) {
    705 			options = { effect: options };
    706 		}
    707 
    708 		var hasOptions;
    709 		var effectName = !options ?
    710 			method :
    711 			options === true || typeof options === "number" ?
    712 				defaultEffect :
    713 				options.effect || defaultEffect;
    714 
    715 		options = options || {};
    716 		if ( typeof options === "number" ) {
    717 			options = { duration: options };
    718 		}
    719 
    720 		hasOptions = !$.isEmptyObject( options );
    721 		options.complete = callback;
    722 
    723 		if ( options.delay ) {
    724 			element.delay( options.delay );
    725 		}
    726 
    727 		if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
    728 			element[ method ]( options );
    729 		} else if ( effectName !== method && element[ effectName ] ) {
    730 			element[ effectName ]( options.duration, options.easing, callback );
    731 		} else {
    732 			element.queue( function( next ) {
    733 				$( this )[ method ]();
    734 				if ( callback ) {
    735 					callback.call( element[ 0 ] );
    736 				}
    737 				next();
    738 			} );
    739 		}
    740 	};
    741 } );
    742 
    743 var widget = $.widget;
    744 
    745 
    746 /*!
    747  * jQuery UI Position 1.12.1
    748  * http://jqueryui.com
    749  *
    750  * Copyright jQuery Foundation and other contributors
    751  * Released under the MIT license.
    752  * http://jquery.org/license
    753  *
    754  * http://api.jqueryui.com/position/
    755  */
    756 
    757 //>>label: Position
    758 //>>group: Core
    759 //>>description: Positions elements relative to other elements.
    760 //>>docs: http://api.jqueryui.com/position/
    761 //>>demos: http://jqueryui.com/position/
    762 
    763 
    764 ( function() {
    765 var cachedScrollbarWidth,
    766 	max = Math.max,
    767 	abs = Math.abs,
    768 	rhorizontal = /left|center|right/,
    769 	rvertical = /top|center|bottom/,
    770 	roffset = /[\+\-]\d+(\.[\d]+)?%?/,
    771 	rposition = /^\w+/,
    772 	rpercent = /%$/,
    773 	_position = $.fn.position;
    774 
    775 function getOffsets( offsets, width, height ) {
    776 	return [
    777 		parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),
    778 		parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )
    779 	];
    780 }
    781 
    782 function parseCss( element, property ) {
    783 	return parseInt( $.css( element, property ), 10 ) || 0;
    784 }
    785 
    786 function getDimensions( elem ) {
    787 	var raw = elem[ 0 ];
    788 	if ( raw.nodeType === 9 ) {
    789 		return {
    790 			width: elem.width(),
    791 			height: elem.height(),
    792 			offset: { top: 0, left: 0 }
    793 		};
    794 	}
    795 	if ( $.isWindow( raw ) ) {
    796 		return {
    797 			width: elem.width(),
    798 			height: elem.height(),
    799 			offset: { top: elem.scrollTop(), left: elem.scrollLeft() }
    800 		};
    801 	}
    802 	if ( raw.preventDefault ) {
    803 		return {
    804 			width: 0,
    805 			height: 0,
    806 			offset: { top: raw.pageY, left: raw.pageX }
    807 		};
    808 	}
    809 	return {
    810 		width: elem.outerWidth(),
    811 		height: elem.outerHeight(),
    812 		offset: elem.offset()
    813 	};
    814 }
    815 
    816 $.position = {
    817 	scrollbarWidth: function() {
    818 		if ( cachedScrollbarWidth !== undefined ) {
    819 			return cachedScrollbarWidth;
    820 		}
    821 		var w1, w2,
    822 			div = $( "<div " +
    823 				"style='display:block;position:absolute;width:50px;height:50px;overflow:hidden;'>" +
    824 				"<div style='height:100px;width:auto;'></div></div>" ),
    825 			innerDiv = div.children()[ 0 ];
    826 
    827 		$( "body" ).append( div );
    828 		w1 = innerDiv.offsetWidth;
    829 		div.css( "overflow", "scroll" );
    830 
    831 		w2 = innerDiv.offsetWidth;
    832 
    833 		if ( w1 === w2 ) {
    834 			w2 = div[ 0 ].clientWidth;
    835 		}
    836 
    837 		div.remove();
    838 
    839 		return ( cachedScrollbarWidth = w1 - w2 );
    840 	},
    841 	getScrollInfo: function( within ) {
    842 		var overflowX = within.isWindow || within.isDocument ? "" :
    843 				within.element.css( "overflow-x" ),
    844 			overflowY = within.isWindow || within.isDocument ? "" :
    845 				within.element.css( "overflow-y" ),
    846 			hasOverflowX = overflowX === "scroll" ||
    847 				( overflowX === "auto" && within.width < within.element[ 0 ].scrollWidth ),
    848 			hasOverflowY = overflowY === "scroll" ||
    849 				( overflowY === "auto" && within.height < within.element[ 0 ].scrollHeight );
    850 		return {
    851 			width: hasOverflowY ? $.position.scrollbarWidth() : 0,
    852 			height: hasOverflowX ? $.position.scrollbarWidth() : 0
    853 		};
    854 	},
    855 	getWithinInfo: function( element ) {
    856 		var withinElement = $( element || window ),
    857 			isWindow = $.isWindow( withinElement[ 0 ] ),
    858 			isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9,
    859 			hasOffset = !isWindow && !isDocument;
    860 		return {
    861 			element: withinElement,
    862 			isWindow: isWindow,
    863 			isDocument: isDocument,
    864 			offset: hasOffset ? $( element ).offset() : { left: 0, top: 0 },
    865 			scrollLeft: withinElement.scrollLeft(),
    866 			scrollTop: withinElement.scrollTop(),
    867 			width: withinElement.outerWidth(),
    868 			height: withinElement.outerHeight()
    869 		};
    870 	}
    871 };
    872 
    873 $.fn.position = function( options ) {
    874 	if ( !options || !options.of ) {
    875 		return _position.apply( this, arguments );
    876 	}
    877 
    878 	// Make a copy, we don't want to modify arguments
    879 	options = $.extend( {}, options );
    880 
    881 	var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,
    882 		target = $( options.of ),
    883 		within = $.position.getWithinInfo( options.within ),
    884 		scrollInfo = $.position.getScrollInfo( within ),
    885 		collision = ( options.collision || "flip" ).split( " " ),
    886 		offsets = {};
    887 
    888 	dimensions = getDimensions( target );
    889 	if ( target[ 0 ].preventDefault ) {
    890 
    891 		// Force left top to allow flipping
    892 		options.at = "left top";
    893 	}
    894 	targetWidth = dimensions.width;
    895 	targetHeight = dimensions.height;
    896 	targetOffset = dimensions.offset;
    897 
    898 	// Clone to reuse original targetOffset later
    899 	basePosition = $.extend( {}, targetOffset );
    900 
    901 	// Force my and at to have valid horizontal and vertical positions
    902 	// if a value is missing or invalid, it will be converted to center
    903 	$.each( [ "my", "at" ], function() {
    904 		var pos = ( options[ this ] || "" ).split( " " ),
    905 			horizontalOffset,
    906 			verticalOffset;
    907 
    908 		if ( pos.length === 1 ) {
    909 			pos = rhorizontal.test( pos[ 0 ] ) ?
    910 				pos.concat( [ "center" ] ) :
    911 				rvertical.test( pos[ 0 ] ) ?
    912 					[ "center" ].concat( pos ) :
    913 					[ "center", "center" ];
    914 		}
    915 		pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center";
    916 		pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";
    917 
    918 		// Calculate offsets
    919 		horizontalOffset = roffset.exec( pos[ 0 ] );
    920 		verticalOffset = roffset.exec( pos[ 1 ] );
    921 		offsets[ this ] = [
    922 			horizontalOffset ? horizontalOffset[ 0 ] : 0,
    923 			verticalOffset ? verticalOffset[ 0 ] : 0
    924 		];
    925 
    926 		// Reduce to just the positions without the offsets
    927 		options[ this ] = [
    928 			rposition.exec( pos[ 0 ] )[ 0 ],
    929 			rposition.exec( pos[ 1 ] )[ 0 ]
    930 		];
    931 	} );
    932 
    933 	// Normalize collision option
    934 	if ( collision.length === 1 ) {
    935 		collision[ 1 ] = collision[ 0 ];
    936 	}
    937 
    938 	if ( options.at[ 0 ] === "right" ) {
    939 		basePosition.left += targetWidth;
    940 	} else if ( options.at[ 0 ] === "center" ) {
    941 		basePosition.left += targetWidth / 2;
    942 	}
    943 
    944 	if ( options.at[ 1 ] === "bottom" ) {
    945 		basePosition.top += targetHeight;
    946 	} else if ( options.at[ 1 ] === "center" ) {
    947 		basePosition.top += targetHeight / 2;
    948 	}
    949 
    950 	atOffset = getOffsets( offsets.at, targetWidth, targetHeight );
    951 	basePosition.left += atOffset[ 0 ];
    952 	basePosition.top += atOffset[ 1 ];
    953 
    954 	return this.each( function() {
    955 		var collisionPosition, using,
    956 			elem = $( this ),
    957 			elemWidth = elem.outerWidth(),
    958 			elemHeight = elem.outerHeight(),
    959 			marginLeft = parseCss( this, "marginLeft" ),
    960 			marginTop = parseCss( this, "marginTop" ),
    961 			collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) +
    962 				scrollInfo.width,
    963 			collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) +
    964 				scrollInfo.height,
    965 			position = $.extend( {}, basePosition ),
    966 			myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );
    967 
    968 		if ( options.my[ 0 ] === "right" ) {
    969 			position.left -= elemWidth;
    970 		} else if ( options.my[ 0 ] === "center" ) {
    971 			position.left -= elemWidth / 2;
    972 		}
    973 
    974 		if ( options.my[ 1 ] === "bottom" ) {
    975 			position.top -= elemHeight;
    976 		} else if ( options.my[ 1 ] === "center" ) {
    977 			position.top -= elemHeight / 2;
    978 		}
    979 
    980 		position.left += myOffset[ 0 ];
    981 		position.top += myOffset[ 1 ];
    982 
    983 		collisionPosition = {
    984 			marginLeft: marginLeft,
    985 			marginTop: marginTop
    986 		};
    987 
    988 		$.each( [ "left", "top" ], function( i, dir ) {
    989 			if ( $.ui.position[ collision[ i ] ] ) {
    990 				$.ui.position[ collision[ i ] ][ dir ]( position, {
    991 					targetWidth: targetWidth,
    992 					targetHeight: targetHeight,
    993 					elemWidth: elemWidth,
    994 					elemHeight: elemHeight,
    995 					collisionPosition: collisionPosition,
    996 					collisionWidth: collisionWidth,
    997 					collisionHeight: collisionHeight,
    998 					offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],
    999 					my: options.my,
   1000 					at: options.at,
   1001 					within: within,
   1002 					elem: elem
   1003 				} );
   1004 			}
   1005 		} );
   1006 
   1007 		if ( options.using ) {
   1008 
   1009 			// Adds feedback as second argument to using callback, if present
   1010 			using = function( props ) {
   1011 				var left = targetOffset.left - position.left,
   1012 					right = left + targetWidth - elemWidth,
   1013 					top = targetOffset.top - position.top,
   1014 					bottom = top + targetHeight - elemHeight,
   1015 					feedback = {
   1016 						target: {
   1017 							element: target,
   1018 							left: targetOffset.left,
   1019 							top: targetOffset.top,
   1020 							width: targetWidth,
   1021 							height: targetHeight
   1022 						},
   1023 						element: {
   1024 							element: elem,
   1025 							left: position.left,
   1026 							top: position.top,
   1027 							width: elemWidth,
   1028 							height: elemHeight
   1029 						},
   1030 						horizontal: right < 0 ? "left" : left > 0 ? "right" : "center",
   1031 						vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle"
   1032 					};
   1033 				if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {
   1034 					feedback.horizontal = "center";
   1035 				}
   1036 				if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {
   1037 					feedback.vertical = "middle";
   1038 				}
   1039 				if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {
   1040 					feedback.important = "horizontal";
   1041 				} else {
   1042 					feedback.important = "vertical";
   1043 				}
   1044 				options.using.call( this, props, feedback );
   1045 			};
   1046 		}
   1047 
   1048 		elem.offset( $.extend( position, { using: using } ) );
   1049 	} );
   1050 };
   1051 
   1052 $.ui.position = {
   1053 	fit: {
   1054 		left: function( position, data ) {
   1055 			var within = data.within,
   1056 				withinOffset = within.isWindow ? within.scrollLeft : within.offset.left,
   1057 				outerWidth = within.width,
   1058 				collisionPosLeft = position.left - data.collisionPosition.marginLeft,
   1059 				overLeft = withinOffset - collisionPosLeft,
   1060 				overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
   1061 				newOverRight;
   1062 
   1063 			// Element is wider than within
   1064 			if ( data.collisionWidth > outerWidth ) {
   1065 
   1066 				// Element is initially over the left side of within
   1067 				if ( overLeft > 0 && overRight <= 0 ) {
   1068 					newOverRight = position.left + overLeft + data.collisionWidth - outerWidth -
   1069 						withinOffset;
   1070 					position.left += overLeft - newOverRight;
   1071 
   1072 				// Element is initially over right side of within
   1073 				} else if ( overRight > 0 && overLeft <= 0 ) {
   1074 					position.left = withinOffset;
   1075 
   1076 				// Element is initially over both left and right sides of within
   1077 				} else {
   1078 					if ( overLeft > overRight ) {
   1079 						position.left = withinOffset + outerWidth - data.collisionWidth;
   1080 					} else {
   1081 						position.left = withinOffset;
   1082 					}
   1083 				}
   1084 
   1085 			// Too far left -> align with left edge
   1086 			} else if ( overLeft > 0 ) {
   1087 				position.left += overLeft;
   1088 
   1089 			// Too far right -> align with right edge
   1090 			} else if ( overRight > 0 ) {
   1091 				position.left -= overRight;
   1092 
   1093 			// Adjust based on position and margin
   1094 			} else {
   1095 				position.left = max( position.left - collisionPosLeft, position.left );
   1096 			}
   1097 		},
   1098 		top: function( position, data ) {
   1099 			var within = data.within,
   1100 				withinOffset = within.isWindow ? within.scrollTop : within.offset.top,
   1101 				outerHeight = data.within.height,
   1102 				collisionPosTop = position.top - data.collisionPosition.marginTop,
   1103 				overTop = withinOffset - collisionPosTop,
   1104 				overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
   1105 				newOverBottom;
   1106 
   1107 			// Element is taller than within
   1108 			if ( data.collisionHeight > outerHeight ) {
   1109 
   1110 				// Element is initially over the top of within
   1111 				if ( overTop > 0 && overBottom <= 0 ) {
   1112 					newOverBottom = position.top + overTop + data.collisionHeight - outerHeight -
   1113 						withinOffset;
   1114 					position.top += overTop - newOverBottom;
   1115 
   1116 				// Element is initially over bottom of within
   1117 				} else if ( overBottom > 0 && overTop <= 0 ) {
   1118 					position.top = withinOffset;
   1119 
   1120 				// Element is initially over both top and bottom of within
   1121 				} else {
   1122 					if ( overTop > overBottom ) {
   1123 						position.top = withinOffset + outerHeight - data.collisionHeight;
   1124 					} else {
   1125 						position.top = withinOffset;
   1126 					}
   1127 				}
   1128 
   1129 			// Too far up -> align with top
   1130 			} else if ( overTop > 0 ) {
   1131 				position.top += overTop;
   1132 
   1133 			// Too far down -> align with bottom edge
   1134 			} else if ( overBottom > 0 ) {
   1135 				position.top -= overBottom;
   1136 
   1137 			// Adjust based on position and margin
   1138 			} else {
   1139 				position.top = max( position.top - collisionPosTop, position.top );
   1140 			}
   1141 		}
   1142 	},
   1143 	flip: {
   1144 		left: function( position, data ) {
   1145 			var within = data.within,
   1146 				withinOffset = within.offset.left + within.scrollLeft,
   1147 				outerWidth = within.width,
   1148 				offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,
   1149 				collisionPosLeft = position.left - data.collisionPosition.marginLeft,
   1150 				overLeft = collisionPosLeft - offsetLeft,
   1151 				overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,
   1152 				myOffset = data.my[ 0 ] === "left" ?
   1153 					-data.elemWidth :
   1154 					data.my[ 0 ] === "right" ?
   1155 						data.elemWidth :
   1156 						0,
   1157 				atOffset = data.at[ 0 ] === "left" ?
   1158 					data.targetWidth :
   1159 					data.at[ 0 ] === "right" ?
   1160 						-data.targetWidth :
   1161 						0,
   1162 				offset = -2 * data.offset[ 0 ],
   1163 				newOverRight,
   1164 				newOverLeft;
   1165 
   1166 			if ( overLeft < 0 ) {
   1167 				newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth -
   1168 					outerWidth - withinOffset;
   1169 				if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {
   1170 					position.left += myOffset + atOffset + offset;
   1171 				}
   1172 			} else if ( overRight > 0 ) {
   1173 				newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset +
   1174 					atOffset + offset - offsetLeft;
   1175 				if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {
   1176 					position.left += myOffset + atOffset + offset;
   1177 				}
   1178 			}
   1179 		},
   1180 		top: function( position, data ) {
   1181 			var within = data.within,
   1182 				withinOffset = within.offset.top + within.scrollTop,
   1183 				outerHeight = within.height,
   1184 				offsetTop = within.isWindow ? within.scrollTop : within.offset.top,
   1185 				collisionPosTop = position.top - data.collisionPosition.marginTop,
   1186 				overTop = collisionPosTop - offsetTop,
   1187 				overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,
   1188 				top = data.my[ 1 ] === "top",
   1189 				myOffset = top ?
   1190 					-data.elemHeight :
   1191 					data.my[ 1 ] === "bottom" ?
   1192 						data.elemHeight :
   1193 						0,
   1194 				atOffset = data.at[ 1 ] === "top" ?
   1195 					data.targetHeight :
   1196 					data.at[ 1 ] === "bottom" ?
   1197 						-data.targetHeight :
   1198 						0,
   1199 				offset = -2 * data.offset[ 1 ],
   1200 				newOverTop,
   1201 				newOverBottom;
   1202 			if ( overTop < 0 ) {
   1203 				newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight -
   1204 					outerHeight - withinOffset;
   1205 				if ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) {
   1206 					position.top += myOffset + atOffset + offset;
   1207 				}
   1208 			} else if ( overBottom > 0 ) {
   1209 				newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset +
   1210 					offset - offsetTop;
   1211 				if ( newOverTop > 0 || abs( newOverTop ) < overBottom ) {
   1212 					position.top += myOffset + atOffset + offset;
   1213 				}
   1214 			}
   1215 		}
   1216 	},
   1217 	flipfit: {
   1218 		left: function() {
   1219 			$.ui.position.flip.left.apply( this, arguments );
   1220 			$.ui.position.fit.left.apply( this, arguments );
   1221 		},
   1222 		top: function() {
   1223 			$.ui.position.flip.top.apply( this, arguments );
   1224 			$.ui.position.fit.top.apply( this, arguments );
   1225 		}
   1226 	}
   1227 };
   1228 
   1229 } )();
   1230 
   1231 var position = $.ui.position;
   1232 
   1233 
   1234 /*!
   1235  * jQuery UI :data 1.12.1
   1236  * http://jqueryui.com
   1237  *
   1238  * Copyright jQuery Foundation and other contributors
   1239  * Released under the MIT license.
   1240  * http://jquery.org/license
   1241  */
   1242 
   1243 //>>label: :data Selector
   1244 //>>group: Core
   1245 //>>description: Selects elements which have data stored under the specified key.
   1246 //>>docs: http://api.jqueryui.com/data-selector/
   1247 
   1248 
   1249 var data = $.extend( $.expr[ ":" ], {
   1250 	data: $.expr.createPseudo ?
   1251 		$.expr.createPseudo( function( dataName ) {
   1252 			return function( elem ) {
   1253 				return !!$.data( elem, dataName );
   1254 			};
   1255 		} ) :
   1256 
   1257 		// Support: jQuery <1.8
   1258 		function( elem, i, match ) {
   1259 			return !!$.data( elem, match[ 3 ] );
   1260 		}
   1261 } );
   1262 
   1263 /*!
   1264  * jQuery UI Disable Selection 1.12.1
   1265  * http://jqueryui.com
   1266  *
   1267  * Copyright jQuery Foundation and other contributors
   1268  * Released under the MIT license.
   1269  * http://jquery.org/license
   1270  */
   1271 
   1272 //>>label: disableSelection
   1273 //>>group: Core
   1274 //>>description: Disable selection of text content within the set of matched elements.
   1275 //>>docs: http://api.jqueryui.com/disableSelection/
   1276 
   1277 // This file is deprecated
   1278 
   1279 
   1280 var disableSelection = $.fn.extend( {
   1281 	disableSelection: ( function() {
   1282 		var eventType = "onselectstart" in document.createElement( "div" ) ?
   1283 			"selectstart" :
   1284 			"mousedown";
   1285 
   1286 		return function() {
   1287 			return this.on( eventType + ".ui-disableSelection", function( event ) {
   1288 				event.preventDefault();
   1289 			} );
   1290 		};
   1291 	} )(),
   1292 
   1293 	enableSelection: function() {
   1294 		return this.off( ".ui-disableSelection" );
   1295 	}
   1296 } );
   1297 
   1298 
   1299 /*!
   1300  * jQuery UI Effects 1.12.1
   1301  * http://jqueryui.com
   1302  *
   1303  * Copyright jQuery Foundation and other contributors
   1304  * Released under the MIT license.
   1305  * http://jquery.org/license
   1306  */
   1307 
   1308 //>>label: Effects Core
   1309 //>>group: Effects
   1310 // jscs:disable maximumLineLength
   1311 //>>description: Extends the internal jQuery effects. Includes morphing and easing. Required by all other effects.
   1312 // jscs:enable maximumLineLength
   1313 //>>docs: http://api.jqueryui.com/category/effects-core/
   1314 //>>demos: http://jqueryui.com/effect/
   1315 
   1316 
   1317 
   1318 var dataSpace = "ui-effects-",
   1319 	dataSpaceStyle = "ui-effects-style",
   1320 	dataSpaceAnimated = "ui-effects-animated",
   1321 
   1322 	// Create a local jQuery because jQuery Color relies on it and the
   1323 	// global may not exist with AMD and a custom build (#10199)
   1324 	jQuery = $;
   1325 
   1326 $.effects = {
   1327 	effect: {}
   1328 };
   1329 
   1330 /*!
   1331  * jQuery Color Animations v2.1.2
   1332  * https://github.com/jquery/jquery-color
   1333  *
   1334  * Copyright 2014 jQuery Foundation and other contributors
   1335  * Released under the MIT license.
   1336  * http://jquery.org/license
   1337  *
   1338  * Date: Wed Jan 16 08:47:09 2013 -0600
   1339  */
   1340 ( function( jQuery, undefined ) {
   1341 
   1342 	var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor " +
   1343 		"borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor",
   1344 
   1345 	// Plusequals test for += 100 -= 100
   1346 	rplusequals = /^([\-+])=\s*(\d+\.?\d*)/,
   1347 
   1348 	// A set of RE's that can match strings and generate color tuples.
   1349 	stringParsers = [ {
   1350 			re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
   1351 			parse: function( execResult ) {
   1352 				return [
   1353 					execResult[ 1 ],
   1354 					execResult[ 2 ],
   1355 					execResult[ 3 ],
   1356 					execResult[ 4 ]
   1357 				];
   1358 			}
   1359 		}, {
   1360 			re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
   1361 			parse: function( execResult ) {
   1362 				return [
   1363 					execResult[ 1 ] * 2.55,
   1364 					execResult[ 2 ] * 2.55,
   1365 					execResult[ 3 ] * 2.55,
   1366 					execResult[ 4 ]
   1367 				];
   1368 			}
   1369 		}, {
   1370 
   1371 			// This regex ignores A-F because it's compared against an already lowercased string
   1372 			re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/,
   1373 			parse: function( execResult ) {
   1374 				return [
   1375 					parseInt( execResult[ 1 ], 16 ),
   1376 					parseInt( execResult[ 2 ], 16 ),
   1377 					parseInt( execResult[ 3 ], 16 )
   1378 				];
   1379 			}
   1380 		}, {
   1381 
   1382 			// This regex ignores A-F because it's compared against an already lowercased string
   1383 			re: /#([a-f0-9])([a-f0-9])([a-f0-9])/,
   1384 			parse: function( execResult ) {
   1385 				return [
   1386 					parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ),
   1387 					parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ),
   1388 					parseInt( execResult[ 3 ] + execResult[ 3 ], 16 )
   1389 				];
   1390 			}
   1391 		}, {
   1392 			re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
   1393 			space: "hsla",
   1394 			parse: function( execResult ) {
   1395 				return [
   1396 					execResult[ 1 ],
   1397 					execResult[ 2 ] / 100,
   1398 					execResult[ 3 ] / 100,
   1399 					execResult[ 4 ]
   1400 				];
   1401 			}
   1402 		} ],
   1403 
   1404 	// JQuery.Color( )
   1405 	color = jQuery.Color = function( color, green, blue, alpha ) {
   1406 		return new jQuery.Color.fn.parse( color, green, blue, alpha );
   1407 	},
   1408 	spaces = {
   1409 		rgba: {
   1410 			props: {
   1411 				red: {
   1412 					idx: 0,
   1413 					type: "byte"
   1414 				},
   1415 				green: {
   1416 					idx: 1,
   1417 					type: "byte"
   1418 				},
   1419 				blue: {
   1420 					idx: 2,
   1421 					type: "byte"
   1422 				}
   1423 			}
   1424 		},
   1425 
   1426 		hsla: {
   1427 			props: {
   1428 				hue: {
   1429 					idx: 0,
   1430 					type: "degrees"
   1431 				},
   1432 				saturation: {
   1433 					idx: 1,
   1434 					type: "percent"
   1435 				},
   1436 				lightness: {
   1437 					idx: 2,
   1438 					type: "percent"
   1439 				}
   1440 			}
   1441 		}
   1442 	},
   1443 	propTypes = {
   1444 		"byte": {
   1445 			floor: true,
   1446 			max: 255
   1447 		},
   1448 		"percent": {
   1449 			max: 1
   1450 		},
   1451 		"degrees": {
   1452 			mod: 360,
   1453 			floor: true
   1454 		}
   1455 	},
   1456 	support = color.support = {},
   1457 
   1458 	// Element for support tests
   1459 	supportElem = jQuery( "<p>" )[ 0 ],
   1460 
   1461 	// Colors = jQuery.Color.names
   1462 	colors,
   1463 
   1464 	// Local aliases of functions called often
   1465 	each = jQuery.each;
   1466 
   1467 // Determine rgba support immediately
   1468 supportElem.style.cssText = "background-color:rgba(1,1,1,.5)";
   1469 support.rgba = supportElem.style.backgroundColor.indexOf( "rgba" ) > -1;
   1470 
   1471 // Define cache name and alpha properties
   1472 // for rgba and hsla spaces
   1473 each( spaces, function( spaceName, space ) {
   1474 	space.cache = "_" + spaceName;
   1475 	space.props.alpha = {
   1476 		idx: 3,
   1477 		type: "percent",
   1478 		def: 1
   1479 	};
   1480 } );
   1481 
   1482 function clamp( value, prop, allowEmpty ) {
   1483 	var type = propTypes[ prop.type ] || {};
   1484 
   1485 	if ( value == null ) {
   1486 		return ( allowEmpty || !prop.def ) ? null : prop.def;
   1487 	}
   1488 
   1489 	// ~~ is an short way of doing floor for positive numbers
   1490 	value = type.floor ? ~~value : parseFloat( value );
   1491 
   1492 	// IE will pass in empty strings as value for alpha,
   1493 	// which will hit this case
   1494 	if ( isNaN( value ) ) {
   1495 		return prop.def;
   1496 	}
   1497 
   1498 	if ( type.mod ) {
   1499 
   1500 		// We add mod before modding to make sure that negatives values
   1501 		// get converted properly: -10 -> 350
   1502 		return ( value + type.mod ) % type.mod;
   1503 	}
   1504 
   1505 	// For now all property types without mod have min and max
   1506 	return 0 > value ? 0 : type.max < value ? type.max : value;
   1507 }
   1508 
   1509 function stringParse( string ) {
   1510 	var inst = color(),
   1511 		rgba = inst._rgba = [];
   1512 
   1513 	string = string.toLowerCase();
   1514 
   1515 	each( stringParsers, function( i, parser ) {
   1516 		var parsed,
   1517 			match = parser.re.exec( string ),
   1518 			values = match && parser.parse( match ),
   1519 			spaceName = parser.space || "rgba";
   1520 
   1521 		if ( values ) {
   1522 			parsed = inst[ spaceName ]( values );
   1523 
   1524 			// If this was an rgba parse the assignment might happen twice
   1525 			// oh well....
   1526 			inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ];
   1527 			rgba = inst._rgba = parsed._rgba;
   1528 
   1529 			// Exit each( stringParsers ) here because we matched
   1530 			return false;
   1531 		}
   1532 	} );
   1533 
   1534 	// Found a stringParser that handled it
   1535 	if ( rgba.length ) {
   1536 
   1537 		// If this came from a parsed string, force "transparent" when alpha is 0
   1538 		// chrome, (and maybe others) return "transparent" as rgba(0,0,0,0)
   1539 		if ( rgba.join() === "0,0,0,0" ) {
   1540 			jQuery.extend( rgba, colors.transparent );
   1541 		}
   1542 		return inst;
   1543 	}
   1544 
   1545 	// Named colors
   1546 	return colors[ string ];
   1547 }
   1548 
   1549 color.fn = jQuery.extend( color.prototype, {
   1550 	parse: function( red, green, blue, alpha ) {
   1551 		if ( red === undefined ) {
   1552 			this._rgba = [ null, null, null, null ];
   1553 			return this;
   1554 		}
   1555 		if ( red.jquery || red.nodeType ) {
   1556 			red = jQuery( red ).css( green );
   1557 			green = undefined;
   1558 		}
   1559 
   1560 		var inst = this,
   1561 			type = jQuery.type( red ),
   1562 			rgba = this._rgba = [];
   1563 
   1564 		// More than 1 argument specified - assume ( red, green, blue, alpha )
   1565 		if ( green !== undefined ) {
   1566 			red = [ red, green, blue, alpha ];
   1567 			type = "array";
   1568 		}
   1569 
   1570 		if ( type === "string" ) {
   1571 			return this.parse( stringParse( red ) || colors._default );
   1572 		}
   1573 
   1574 		if ( type === "array" ) {
   1575 			each( spaces.rgba.props, function( key, prop ) {
   1576 				rgba[ prop.idx ] = clamp( red[ prop.idx ], prop );
   1577 			} );
   1578 			return this;
   1579 		}
   1580 
   1581 		if ( type === "object" ) {
   1582 			if ( red instanceof color ) {
   1583 				each( spaces, function( spaceName, space ) {
   1584 					if ( red[ space.cache ] ) {
   1585 						inst[ space.cache ] = red[ space.cache ].slice();
   1586 					}
   1587 				} );
   1588 			} else {
   1589 				each( spaces, function( spaceName, space ) {
   1590 					var cache = space.cache;
   1591 					each( space.props, function( key, prop ) {
   1592 
   1593 						// If the cache doesn't exist, and we know how to convert
   1594 						if ( !inst[ cache ] && space.to ) {
   1595 
   1596 							// If the value was null, we don't need to copy it
   1597 							// if the key was alpha, we don't need to copy it either
   1598 							if ( key === "alpha" || red[ key ] == null ) {
   1599 								return;
   1600 							}
   1601 							inst[ cache ] = space.to( inst._rgba );
   1602 						}
   1603 
   1604 						// This is the only case where we allow nulls for ALL properties.
   1605 						// call clamp with alwaysAllowEmpty
   1606 						inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true );
   1607 					} );
   1608 
   1609 					// Everything defined but alpha?
   1610 					if ( inst[ cache ] &&
   1611 							jQuery.inArray( null, inst[ cache ].slice( 0, 3 ) ) < 0 ) {
   1612 
   1613 						// Use the default of 1
   1614 						inst[ cache ][ 3 ] = 1;
   1615 						if ( space.from ) {
   1616 							inst._rgba = space.from( inst[ cache ] );
   1617 						}
   1618 					}
   1619 				} );
   1620 			}
   1621 			return this;
   1622 		}
   1623 	},
   1624 	is: function( compare ) {
   1625 		var is = color( compare ),
   1626 			same = true,
   1627 			inst = this;
   1628 
   1629 		each( spaces, function( _, space ) {
   1630 			var localCache,
   1631 				isCache = is[ space.cache ];
   1632 			if ( isCache ) {
   1633 				localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || [];
   1634 				each( space.props, function( _, prop ) {
   1635 					if ( isCache[ prop.idx ] != null ) {
   1636 						same = ( isCache[ prop.idx ] === localCache[ prop.idx ] );
   1637 						return same;
   1638 					}
   1639 				} );
   1640 			}
   1641 			return same;
   1642 		} );
   1643 		return same;
   1644 	},
   1645 	_space: function() {
   1646 		var used = [],
   1647 			inst = this;
   1648 		each( spaces, function( spaceName, space ) {
   1649 			if ( inst[ space.cache ] ) {
   1650 				used.push( spaceName );
   1651 			}
   1652 		} );
   1653 		return used.pop();
   1654 	},
   1655 	transition: function( other, distance ) {
   1656 		var end = color( other ),
   1657 			spaceName = end._space(),
   1658 			space = spaces[ spaceName ],
   1659 			startColor = this.alpha() === 0 ? color( "transparent" ) : this,
   1660 			start = startColor[ space.cache ] || space.to( startColor._rgba ),
   1661 			result = start.slice();
   1662 
   1663 		end = end[ space.cache ];
   1664 		each( space.props, function( key, prop ) {
   1665 			var index = prop.idx,
   1666 				startValue = start[ index ],
   1667 				endValue = end[ index ],
   1668 				type = propTypes[ prop.type ] || {};
   1669 
   1670 			// If null, don't override start value
   1671 			if ( endValue === null ) {
   1672 				return;
   1673 			}
   1674 
   1675 			// If null - use end
   1676 			if ( startValue === null ) {
   1677 				result[ index ] = endValue;
   1678 			} else {
   1679 				if ( type.mod ) {
   1680 					if ( endValue - startValue > type.mod / 2 ) {
   1681 						startValue += type.mod;
   1682 					} else if ( startValue - endValue > type.mod / 2 ) {
   1683 						startValue -= type.mod;
   1684 					}
   1685 				}
   1686 				result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop );
   1687 			}
   1688 		} );
   1689 		return this[ spaceName ]( result );
   1690 	},
   1691 	blend: function( opaque ) {
   1692 
   1693 		// If we are already opaque - return ourself
   1694 		if ( this._rgba[ 3 ] === 1 ) {
   1695 			return this;
   1696 		}
   1697 
   1698 		var rgb = this._rgba.slice(),
   1699 			a = rgb.pop(),
   1700 			blend = color( opaque )._rgba;
   1701 
   1702 		return color( jQuery.map( rgb, function( v, i ) {
   1703 			return ( 1 - a ) * blend[ i ] + a * v;
   1704 		} ) );
   1705 	},
   1706 	toRgbaString: function() {
   1707 		var prefix = "rgba(",
   1708 			rgba = jQuery.map( this._rgba, function( v, i ) {
   1709 				return v == null ? ( i > 2 ? 1 : 0 ) : v;
   1710 			} );
   1711 
   1712 		if ( rgba[ 3 ] === 1 ) {
   1713 			rgba.pop();
   1714 			prefix = "rgb(";
   1715 		}
   1716 
   1717 		return prefix + rgba.join() + ")";
   1718 	},
   1719 	toHslaString: function() {
   1720 		var prefix = "hsla(",
   1721 			hsla = jQuery.map( this.hsla(), function( v, i ) {
   1722 				if ( v == null ) {
   1723 					v = i > 2 ? 1 : 0;
   1724 				}
   1725 
   1726 				// Catch 1 and 2
   1727 				if ( i && i < 3 ) {
   1728 					v = Math.round( v * 100 ) + "%";
   1729 				}
   1730 				return v;
   1731 			} );
   1732 
   1733 		if ( hsla[ 3 ] === 1 ) {
   1734 			hsla.pop();
   1735 			prefix = "hsl(";
   1736 		}
   1737 		return prefix + hsla.join() + ")";
   1738 	},
   1739 	toHexString: function( includeAlpha ) {
   1740 		var rgba = this._rgba.slice(),
   1741 			alpha = rgba.pop();
   1742 
   1743 		if ( includeAlpha ) {
   1744 			rgba.push( ~~( alpha * 255 ) );
   1745 		}
   1746 
   1747 		return "#" + jQuery.map( rgba, function( v ) {
   1748 
   1749 			// Default to 0 when nulls exist
   1750 			v = ( v || 0 ).toString( 16 );
   1751 			return v.length === 1 ? "0" + v : v;
   1752 		} ).join( "" );
   1753 	},
   1754 	toString: function() {
   1755 		return this._rgba[ 3 ] === 0 ? "transparent" : this.toRgbaString();
   1756 	}
   1757 } );
   1758 color.fn.parse.prototype = color.fn;
   1759 
   1760 // Hsla conversions adapted from:
   1761 // https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021
   1762 
   1763 function hue2rgb( p, q, h ) {
   1764 	h = ( h + 1 ) % 1;
   1765 	if ( h * 6 < 1 ) {
   1766 		return p + ( q - p ) * h * 6;
   1767 	}
   1768 	if ( h * 2 < 1 ) {
   1769 		return q;
   1770 	}
   1771 	if ( h * 3 < 2 ) {
   1772 		return p + ( q - p ) * ( ( 2 / 3 ) - h ) * 6;
   1773 	}
   1774 	return p;
   1775 }
   1776 
   1777 spaces.hsla.to = function( rgba ) {
   1778 	if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) {
   1779 		return [ null, null, null, rgba[ 3 ] ];
   1780 	}
   1781 	var r = rgba[ 0 ] / 255,
   1782 		g = rgba[ 1 ] / 255,
   1783 		b = rgba[ 2 ] / 255,
   1784 		a = rgba[ 3 ],
   1785 		max = Math.max( r, g, b ),
   1786 		min = Math.min( r, g, b ),
   1787 		diff = max - min,
   1788 		add = max + min,
   1789 		l = add * 0.5,
   1790 		h, s;
   1791 
   1792 	if ( min === max ) {
   1793 		h = 0;
   1794 	} else if ( r === max ) {
   1795 		h = ( 60 * ( g - b ) / diff ) + 360;
   1796 	} else if ( g === max ) {
   1797 		h = ( 60 * ( b - r ) / diff ) + 120;
   1798 	} else {
   1799 		h = ( 60 * ( r - g ) / diff ) + 240;
   1800 	}
   1801 
   1802 	// Chroma (diff) == 0 means greyscale which, by definition, saturation = 0%
   1803 	// otherwise, saturation is based on the ratio of chroma (diff) to lightness (add)
   1804 	if ( diff === 0 ) {
   1805 		s = 0;
   1806 	} else if ( l <= 0.5 ) {
   1807 		s = diff / add;
   1808 	} else {
   1809 		s = diff / ( 2 - add );
   1810 	}
   1811 	return [ Math.round( h ) % 360, s, l, a == null ? 1 : a ];
   1812 };
   1813 
   1814 spaces.hsla.from = function( hsla ) {
   1815 	if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) {
   1816 		return [ null, null, null, hsla[ 3 ] ];
   1817 	}
   1818 	var h = hsla[ 0 ] / 360,
   1819 		s = hsla[ 1 ],
   1820 		l = hsla[ 2 ],
   1821 		a = hsla[ 3 ],
   1822 		q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s,
   1823 		p = 2 * l - q;
   1824 
   1825 	return [
   1826 		Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ),
   1827 		Math.round( hue2rgb( p, q, h ) * 255 ),
   1828 		Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ),
   1829 		a
   1830 	];
   1831 };
   1832 
   1833 each( spaces, function( spaceName, space ) {
   1834 	var props = space.props,
   1835 		cache = space.cache,
   1836 		to = space.to,
   1837 		from = space.from;
   1838 
   1839 	// Makes rgba() and hsla()
   1840 	color.fn[ spaceName ] = function( value ) {
   1841 
   1842 		// Generate a cache for this space if it doesn't exist
   1843 		if ( to && !this[ cache ] ) {
   1844 			this[ cache ] = to( this._rgba );
   1845 		}
   1846 		if ( value === undefined ) {
   1847 			return this[ cache ].slice();
   1848 		}
   1849 
   1850 		var ret,
   1851 			type = jQuery.type( value ),
   1852 			arr = ( type === "array" || type === "object" ) ? value : arguments,
   1853 			local = this[ cache ].slice();
   1854 
   1855 		each( props, function( key, prop ) {
   1856 			var val = arr[ type === "object" ? key : prop.idx ];
   1857 			if ( val == null ) {
   1858 				val = local[ prop.idx ];
   1859 			}
   1860 			local[ prop.idx ] = clamp( val, prop );
   1861 		} );
   1862 
   1863 		if ( from ) {
   1864 			ret = color( from( local ) );
   1865 			ret[ cache ] = local;
   1866 			return ret;
   1867 		} else {
   1868 			return color( local );
   1869 		}
   1870 	};
   1871 
   1872 	// Makes red() green() blue() alpha() hue() saturation() lightness()
   1873 	each( props, function( key, prop ) {
   1874 
   1875 		// Alpha is included in more than one space
   1876 		if ( color.fn[ key ] ) {
   1877 			return;
   1878 		}
   1879 		color.fn[ key ] = function( value ) {
   1880 			var vtype = jQuery.type( value ),
   1881 				fn = ( key === "alpha" ? ( this._hsla ? "hsla" : "rgba" ) : spaceName ),
   1882 				local = this[ fn ](),
   1883 				cur = local[ prop.idx ],
   1884 				match;
   1885 
   1886 			if ( vtype === "undefined" ) {
   1887 				return cur;
   1888 			}
   1889 
   1890 			if ( vtype === "function" ) {
   1891 				value = value.call( this, cur );
   1892 				vtype = jQuery.type( value );
   1893 			}
   1894 			if ( value == null && prop.empty ) {
   1895 				return this;
   1896 			}
   1897 			if ( vtype === "string" ) {
   1898 				match = rplusequals.exec( value );
   1899 				if ( match ) {
   1900 					value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 );
   1901 				}
   1902 			}
   1903 			local[ prop.idx ] = value;
   1904 			return this[ fn ]( local );
   1905 		};
   1906 	} );
   1907 } );
   1908 
   1909 // Add cssHook and .fx.step function for each named hook.
   1910 // accept a space separated string of properties
   1911 color.hook = function( hook ) {
   1912 	var hooks = hook.split( " " );
   1913 	each( hooks, function( i, hook ) {
   1914 		jQuery.cssHooks[ hook ] = {
   1915 			set: function( elem, value ) {
   1916 				var parsed, curElem,
   1917 					backgroundColor = "";
   1918 
   1919 				if ( value !== "transparent" && ( jQuery.type( value ) !== "string" ||
   1920 						( parsed = stringParse( value ) ) ) ) {
   1921 					value = color( parsed || value );
   1922 					if ( !support.rgba && value._rgba[ 3 ] !== 1 ) {
   1923 						curElem = hook === "backgroundColor" ? elem.parentNode : elem;
   1924 						while (
   1925 							( backgroundColor === "" || backgroundColor === "transparent" ) &&
   1926 							curElem && curElem.style
   1927 						) {
   1928 							try {
   1929 								backgroundColor = jQuery.css( curElem, "backgroundColor" );
   1930 								curElem = curElem.parentNode;
   1931 							} catch ( e ) {
   1932 							}
   1933 						}
   1934 
   1935 						value = value.blend( backgroundColor && backgroundColor !== "transparent" ?
   1936 							backgroundColor :
   1937 							"_default" );
   1938 					}
   1939 
   1940 					value = value.toRgbaString();
   1941 				}
   1942 				try {
   1943 					elem.style[ hook ] = value;
   1944 				} catch ( e ) {
   1945 
   1946 					// Wrapped to prevent IE from throwing errors on "invalid" values like
   1947 					// 'auto' or 'inherit'
   1948 				}
   1949 			}
   1950 		};
   1951 		jQuery.fx.step[ hook ] = function( fx ) {
   1952 			if ( !fx.colorInit ) {
   1953 				fx.start = color( fx.elem, hook );
   1954 				fx.end = color( fx.end );
   1955 				fx.colorInit = true;
   1956 			}
   1957 			jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) );
   1958 		};
   1959 	} );
   1960 
   1961 };
   1962 
   1963 color.hook( stepHooks );
   1964 
   1965 jQuery.cssHooks.borderColor = {
   1966 	expand: function( value ) {
   1967 		var expanded = {};
   1968 
   1969 		each( [ "Top", "Right", "Bottom", "Left" ], function( i, part ) {
   1970 			expanded[ "border" + part + "Color" ] = value;
   1971 		} );
   1972 		return expanded;
   1973 	}
   1974 };
   1975 
   1976 // Basic color names only.
   1977 // Usage of any of the other color names requires adding yourself or including
   1978 // jquery.color.svg-names.js.
   1979 colors = jQuery.Color.names = {
   1980 
   1981 	// 4.1. Basic color keywords
   1982 	aqua: "#00ffff",
   1983 	black: "#000000",
   1984 	blue: "#0000ff",
   1985 	fuchsia: "#ff00ff",
   1986 	gray: "#808080",
   1987 	green: "#008000",
   1988 	lime: "#00ff00",
   1989 	maroon: "#800000",
   1990 	navy: "#000080",
   1991 	olive: "#808000",
   1992 	purple: "#800080",
   1993 	red: "#ff0000",
   1994 	silver: "#c0c0c0",
   1995 	teal: "#008080",
   1996 	white: "#ffffff",
   1997 	yellow: "#ffff00",
   1998 
   1999 	// 4.2.3. "transparent" color keyword
   2000 	transparent: [ null, null, null, 0 ],
   2001 
   2002 	_default: "#ffffff"
   2003 };
   2004 
   2005 } )( jQuery );
   2006 
   2007 /******************************************************************************/
   2008 /****************************** CLASS ANIMATIONS ******************************/
   2009 /******************************************************************************/
   2010 ( function() {
   2011 
   2012 var classAnimationActions = [ "add", "remove", "toggle" ],
   2013 	shorthandStyles = {
   2014 		border: 1,
   2015 		borderBottom: 1,
   2016 		borderColor: 1,
   2017 		borderLeft: 1,
   2018 		borderRight: 1,
   2019 		borderTop: 1,
   2020 		borderWidth: 1,
   2021 		margin: 1,
   2022 		padding: 1
   2023 	};
   2024 
   2025 $.each(
   2026 	[ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ],
   2027 	function( _, prop ) {
   2028 		$.fx.step[ prop ] = function( fx ) {
   2029 			if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) {
   2030 				jQuery.style( fx.elem, prop, fx.end );
   2031 				fx.setAttr = true;
   2032 			}
   2033 		};
   2034 	}
   2035 );
   2036 
   2037 function getElementStyles( elem ) {
   2038 	var key, len,
   2039 		style = elem.ownerDocument.defaultView ?
   2040 			elem.ownerDocument.defaultView.getComputedStyle( elem, null ) :
   2041 			elem.currentStyle,
   2042 		styles = {};
   2043 
   2044 	if ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) {
   2045 		len = style.length;
   2046 		while ( len-- ) {
   2047 			key = style[ len ];
   2048 			if ( typeof style[ key ] === "string" ) {
   2049 				styles[ $.camelCase( key ) ] = style[ key ];
   2050 			}
   2051 		}
   2052 
   2053 	// Support: Opera, IE <9
   2054 	} else {
   2055 		for ( key in style ) {
   2056 			if ( typeof style[ key ] === "string" ) {
   2057 				styles[ key ] = style[ key ];
   2058 			}
   2059 		}
   2060 	}
   2061 
   2062 	return styles;
   2063 }
   2064 
   2065 function styleDifference( oldStyle, newStyle ) {
   2066 	var diff = {},
   2067 		name, value;
   2068 
   2069 	for ( name in newStyle ) {
   2070 		value = newStyle[ name ];
   2071 		if ( oldStyle[ name ] !== value ) {
   2072 			if ( !shorthandStyles[ name ] ) {
   2073 				if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) {
   2074 					diff[ name ] = value;
   2075 				}
   2076 			}
   2077 		}
   2078 	}
   2079 
   2080 	return diff;
   2081 }
   2082 
   2083 // Support: jQuery <1.8
   2084 if ( !$.fn.addBack ) {
   2085 	$.fn.addBack = function( selector ) {
   2086 		return this.add( selector == null ?
   2087 			this.prevObject : this.prevObject.filter( selector )
   2088 		);
   2089 	};
   2090 }
   2091 
   2092 $.effects.animateClass = function( value, duration, easing, callback ) {
   2093 	var o = $.speed( duration, easing, callback );
   2094 
   2095 	return this.queue( function() {
   2096 		var animated = $( this ),
   2097 			baseClass = animated.attr( "class" ) || "",
   2098 			applyClassChange,
   2099 			allAnimations = o.children ? animated.find( "*" ).addBack() : animated;
   2100 
   2101 		// Map the animated objects to store the original styles.
   2102 		allAnimations = allAnimations.map( function() {
   2103 			var el = $( this );
   2104 			return {
   2105 				el: el,
   2106 				start: getElementStyles( this )
   2107 			};
   2108 		} );
   2109 
   2110 		// Apply class change
   2111 		applyClassChange = function() {
   2112 			$.each( classAnimationActions, function( i, action ) {
   2113 				if ( value[ action ] ) {
   2114 					animated[ action + "Class" ]( value[ action ] );
   2115 				}
   2116 			} );
   2117 		};
   2118 		applyClassChange();
   2119 
   2120 		// Map all animated objects again - calculate new styles and diff
   2121 		allAnimations = allAnimations.map( function() {
   2122 			this.end = getElementStyles( this.el[ 0 ] );
   2123 			this.diff = styleDifference( this.start, this.end );
   2124 			return this;
   2125 		} );
   2126 
   2127 		// Apply original class
   2128 		animated.attr( "class", baseClass );
   2129 
   2130 		// Map all animated objects again - this time collecting a promise
   2131 		allAnimations = allAnimations.map( function() {
   2132 			var styleInfo = this,
   2133 				dfd = $.Deferred(),
   2134 				opts = $.extend( {}, o, {
   2135 					queue: false,
   2136 					complete: function() {
   2137 						dfd.resolve( styleInfo );
   2138 					}
   2139 				} );
   2140 
   2141 			this.el.animate( this.diff, opts );
   2142 			return dfd.promise();
   2143 		} );
   2144 
   2145 		// Once all animations have completed:
   2146 		$.when.apply( $, allAnimations.get() ).done( function() {
   2147 
   2148 			// Set the final class
   2149 			applyClassChange();
   2150 
   2151 			// For each animated element,
   2152 			// clear all css properties that were animated
   2153 			$.each( arguments, function() {
   2154 				var el = this.el;
   2155 				$.each( this.diff, function( key ) {
   2156 					el.css( key, "" );
   2157 				} );
   2158 			} );
   2159 
   2160 			// This is guarnteed to be there if you use jQuery.speed()
   2161 			// it also handles dequeuing the next anim...
   2162 			o.complete.call( animated[ 0 ] );
   2163 		} );
   2164 	} );
   2165 };
   2166 
   2167 $.fn.extend( {
   2168 	addClass: ( function( orig ) {
   2169 		return function( classNames, speed, easing, callback ) {
   2170 			return speed ?
   2171 				$.effects.animateClass.call( this,
   2172 					{ add: classNames }, speed, easing, callback ) :
   2173 				orig.apply( this, arguments );
   2174 		};
   2175 	} )( $.fn.addClass ),
   2176 
   2177 	removeClass: ( function( orig ) {
   2178 		return function( classNames, speed, easing, callback ) {
   2179 			return arguments.length > 1 ?
   2180 				$.effects.animateClass.call( this,
   2181 					{ remove: classNames }, speed, easing, callback ) :
   2182 				orig.apply( this, arguments );
   2183 		};
   2184 	} )( $.fn.removeClass ),
   2185 
   2186 	toggleClass: ( function( orig ) {
   2187 		return function( classNames, force, speed, easing, callback ) {
   2188 			if ( typeof force === "boolean" || force === undefined ) {
   2189 				if ( !speed ) {
   2190 
   2191 					// Without speed parameter
   2192 					return orig.apply( this, arguments );
   2193 				} else {
   2194 					return $.effects.animateClass.call( this,
   2195 						( force ? { add: classNames } : { remove: classNames } ),
   2196 						speed, easing, callback );
   2197 				}
   2198 			} else {
   2199 
   2200 				// Without force parameter
   2201 				return $.effects.animateClass.call( this,
   2202 					{ toggle: classNames }, force, speed, easing );
   2203 			}
   2204 		};
   2205 	} )( $.fn.toggleClass ),
   2206 
   2207 	switchClass: function( remove, add, speed, easing, callback ) {
   2208 		return $.effects.animateClass.call( this, {
   2209 			add: add,
   2210 			remove: remove
   2211 		}, speed, easing, callback );
   2212 	}
   2213 } );
   2214 
   2215 } )();
   2216 
   2217 /******************************************************************************/
   2218 /*********************************** EFFECTS **********************************/
   2219 /******************************************************************************/
   2220 
   2221 ( function() {
   2222 
   2223 if ( $.expr && $.expr.filters && $.expr.filters.animated ) {
   2224 	$.expr.filters.animated = ( function( orig ) {
   2225 		return function( elem ) {
   2226 			return !!$( elem ).data( dataSpaceAnimated ) || orig( elem );
   2227 		};
   2228 	} )( $.expr.filters.animated );
   2229 }
   2230 
   2231 if ( $.uiBackCompat !== false ) {
   2232 	$.extend( $.effects, {
   2233 
   2234 		// Saves a set of properties in a data storage
   2235 		save: function( element, set ) {
   2236 			var i = 0, length = set.length;
   2237 			for ( ; i < length; i++ ) {
   2238 				if ( set[ i ] !== null ) {
   2239 					element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] );
   2240 				}
   2241 			}
   2242 		},
   2243 
   2244 		// Restores a set of previously saved properties from a data storage
   2245 		restore: function( element, set ) {
   2246 			var val, i = 0, length = set.length;
   2247 			for ( ; i < length; i++ ) {
   2248 				if ( set[ i ] !== null ) {
   2249 					val = element.data( dataSpace + set[ i ] );
   2250 					element.css( set[ i ], val );
   2251 				}
   2252 			}
   2253 		},
   2254 
   2255 		setMode: function( el, mode ) {
   2256 			if ( mode === "toggle" ) {
   2257 				mode = el.is( ":hidden" ) ? "show" : "hide";
   2258 			}
   2259 			return mode;
   2260 		},
   2261 
   2262 		// Wraps the element around a wrapper that copies position properties
   2263 		createWrapper: function( element ) {
   2264 
   2265 			// If the element is already wrapped, return it
   2266 			if ( element.parent().is( ".ui-effects-wrapper" ) ) {
   2267 				return element.parent();
   2268 			}
   2269 
   2270 			// Wrap the element
   2271 			var props = {
   2272 					width: element.outerWidth( true ),
   2273 					height: element.outerHeight( true ),
   2274 					"float": element.css( "float" )
   2275 				},
   2276 				wrapper = $( "<div></div>" )
   2277 					.addClass( "ui-effects-wrapper" )
   2278 					.css( {
   2279 						fontSize: "100%",
   2280 						background: "transparent",
   2281 						border: "none",
   2282 						margin: 0,
   2283 						padding: 0
   2284 					} ),
   2285 
   2286 				// Store the size in case width/height are defined in % - Fixes #5245
   2287 				size = {
   2288 					width: element.width(),
   2289 					height: element.height()
   2290 				},
   2291 				active = document.activeElement;
   2292 
   2293 			// Support: Firefox
   2294 			// Firefox incorrectly exposes anonymous content
   2295 			// https://bugzilla.mozilla.org/show_bug.cgi?id=561664
   2296 			try {
   2297 				active.id;
   2298 			} catch ( e ) {
   2299 				active = document.body;
   2300 			}
   2301 
   2302 			element.wrap( wrapper );
   2303 
   2304 			// Fixes #7595 - Elements lose focus when wrapped.
   2305 			if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
   2306 				$( active ).trigger( "focus" );
   2307 			}
   2308 
   2309 			// Hotfix for jQuery 1.4 since some change in wrap() seems to actually
   2310 			// lose the reference to the wrapped element
   2311 			wrapper = element.parent();
   2312 
   2313 			// Transfer positioning properties to the wrapper
   2314 			if ( element.css( "position" ) === "static" ) {
   2315 				wrapper.css( { position: "relative" } );
   2316 				element.css( { position: "relative" } );
   2317 			} else {
   2318 				$.extend( props, {
   2319 					position: element.css( "position" ),
   2320 					zIndex: element.css( "z-index" )
   2321 				} );
   2322 				$.each( [ "top", "left", "bottom", "right" ], function( i, pos ) {
   2323 					props[ pos ] = element.css( pos );
   2324 					if ( isNaN( parseInt( props[ pos ], 10 ) ) ) {
   2325 						props[ pos ] = "auto";
   2326 					}
   2327 				} );
   2328 				element.css( {
   2329 					position: "relative",
   2330 					top: 0,
   2331 					left: 0,
   2332 					right: "auto",
   2333 					bottom: "auto"
   2334 				} );
   2335 			}
   2336 			element.css( size );
   2337 
   2338 			return wrapper.css( props ).show();
   2339 		},
   2340 
   2341 		removeWrapper: function( element ) {
   2342 			var active = document.activeElement;
   2343 
   2344 			if ( element.parent().is( ".ui-effects-wrapper" ) ) {
   2345 				element.parent().replaceWith( element );
   2346 
   2347 				// Fixes #7595 - Elements lose focus when wrapped.
   2348 				if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
   2349 					$( active ).trigger( "focus" );
   2350 				}
   2351 			}
   2352 
   2353 			return element;
   2354 		}
   2355 	} );
   2356 }
   2357 
   2358 $.extend( $.effects, {
   2359 	version: "1.12.1",
   2360 
   2361 	define: function( name, mode, effect ) {
   2362 		if ( !effect ) {
   2363 			effect = mode;
   2364 			mode = "effect";
   2365 		}
   2366 
   2367 		$.effects.effect[ name ] = effect;
   2368 		$.effects.effect[ name ].mode = mode;
   2369 
   2370 		return effect;
   2371 	},
   2372 
   2373 	scaledDimensions: function( element, percent, direction ) {
   2374 		if ( percent === 0 ) {
   2375 			return {
   2376 				height: 0,
   2377 				width: 0,
   2378 				outerHeight: 0,
   2379 				outerWidth: 0
   2380 			};
   2381 		}
   2382 
   2383 		var x = direction !== "horizontal" ? ( ( percent || 100 ) / 100 ) : 1,
   2384 			y = direction !== "vertical" ? ( ( percent || 100 ) / 100 ) : 1;
   2385 
   2386 		return {
   2387 			height: element.height() * y,
   2388 			width: element.width() * x,
   2389 			outerHeight: element.outerHeight() * y,
   2390 			outerWidth: element.outerWidth() * x
   2391 		};
   2392 
   2393 	},
   2394 
   2395 	clipToBox: function( animation ) {
   2396 		return {
   2397 			width: animation.clip.right - animation.clip.left,
   2398 			height: animation.clip.bottom - animation.clip.top,
   2399 			left: animation.clip.left,
   2400 			top: animation.clip.top
   2401 		};
   2402 	},
   2403 
   2404 	// Injects recently queued functions to be first in line (after "inprogress")
   2405 	unshift: function( element, queueLength, count ) {
   2406 		var queue = element.queue();
   2407 
   2408 		if ( queueLength > 1 ) {
   2409 			queue.splice.apply( queue,
   2410 				[ 1, 0 ].concat( queue.splice( queueLength, count ) ) );
   2411 		}
   2412 		element.dequeue();
   2413 	},
   2414 
   2415 	saveStyle: function( element ) {
   2416 		element.data( dataSpaceStyle, element[ 0 ].style.cssText );
   2417 	},
   2418 
   2419 	restoreStyle: function( element ) {
   2420 		element[ 0 ].style.cssText = element.data( dataSpaceStyle ) || "";
   2421 		element.removeData( dataSpaceStyle );
   2422 	},
   2423 
   2424 	mode: function( element, mode ) {
   2425 		var hidden = element.is( ":hidden" );
   2426 
   2427 		if ( mode === "toggle" ) {
   2428 			mode = hidden ? "show" : "hide";
   2429 		}
   2430 		if ( hidden ? mode === "hide" : mode === "show" ) {
   2431 			mode = "none";
   2432 		}
   2433 		return mode;
   2434 	},
   2435 
   2436 	// Translates a [top,left] array into a baseline value
   2437 	getBaseline: function( origin, original ) {
   2438 		var y, x;
   2439 
   2440 		switch ( origin[ 0 ] ) {
   2441 		case "top":
   2442 			y = 0;
   2443 			break;
   2444 		case "middle":
   2445 			y = 0.5;
   2446 			break;
   2447 		case "bottom":
   2448 			y = 1;
   2449 			break;
   2450 		default:
   2451 			y = origin[ 0 ] / original.height;
   2452 		}
   2453 
   2454 		switch ( origin[ 1 ] ) {
   2455 		case "left":
   2456 			x = 0;
   2457 			break;
   2458 		case "center":
   2459 			x = 0.5;
   2460 			break;
   2461 		case "right":
   2462 			x = 1;
   2463 			break;
   2464 		default:
   2465 			x = origin[ 1 ] / original.width;
   2466 		}
   2467 
   2468 		return {
   2469 			x: x,
   2470 			y: y
   2471 		};
   2472 	},
   2473 
   2474 	// Creates a placeholder element so that the original element can be made absolute
   2475 	createPlaceholder: function( element ) {
   2476 		var placeholder,
   2477 			cssPosition = element.css( "position" ),
   2478 			position = element.position();
   2479 
   2480 		// Lock in margins first to account for form elements, which
   2481 		// will change margin if you explicitly set height
   2482 		// see: http://jsfiddle.net/JZSMt/3/ https://bugs.webkit.org/show_bug.cgi?id=107380
   2483 		// Support: Safari
   2484 		element.css( {
   2485 			marginTop: element.css( "marginTop" ),
   2486 			marginBottom: element.css( "marginBottom" ),
   2487 			marginLeft: element.css( "marginLeft" ),
   2488 			marginRight: element.css( "marginRight" )
   2489 		} )
   2490 		.outerWidth( element.outerWidth() )
   2491 		.outerHeight( element.outerHeight() );
   2492 
   2493 		if ( /^(static|relative)/.test( cssPosition ) ) {
   2494 			cssPosition = "absolute";
   2495 
   2496 			placeholder = $( "<" + element[ 0 ].nodeName + ">" ).insertAfter( element ).css( {
   2497 
   2498 				// Convert inline to inline block to account for inline elements
   2499 				// that turn to inline block based on content (like img)
   2500 				display: /^(inline|ruby)/.test( element.css( "display" ) ) ?
   2501 					"inline-block" :
   2502 					"block",
   2503 				visibility: "hidden",
   2504 
   2505 				// Margins need to be set to account for margin collapse
   2506 				marginTop: element.css( "marginTop" ),
   2507 				marginBottom: element.css( "marginBottom" ),
   2508 				marginLeft: element.css( "marginLeft" ),
   2509 				marginRight: element.css( "marginRight" ),
   2510 				"float": element.css( "float" )
   2511 			} )
   2512 			.outerWidth( element.outerWidth() )
   2513 			.outerHeight( element.outerHeight() )
   2514 			.addClass( "ui-effects-placeholder" );
   2515 
   2516 			element.data( dataSpace + "placeholder", placeholder );
   2517 		}
   2518 
   2519 		element.css( {
   2520 			position: cssPosition,
   2521 			left: position.left,
   2522 			top: position.top
   2523 		} );
   2524 
   2525 		return placeholder;
   2526 	},
   2527 
   2528 	removePlaceholder: function( element ) {
   2529 		var dataKey = dataSpace + "placeholder",
   2530 				placeholder = element.data( dataKey );
   2531 
   2532 		if ( placeholder ) {
   2533 			placeholder.remove();
   2534 			element.removeData( dataKey );
   2535 		}
   2536 	},
   2537 
   2538 	// Removes a placeholder if it exists and restores
   2539 	// properties that were modified during placeholder creation
   2540 	cleanUp: function( element ) {
   2541 		$.effects.restoreStyle( element );
   2542 		$.effects.removePlaceholder( element );
   2543 	},
   2544 
   2545 	setTransition: function( element, list, factor, value ) {
   2546 		value = value || {};
   2547 		$.each( list, function( i, x ) {
   2548 			var unit = element.cssUnit( x );
   2549 			if ( unit[ 0 ] > 0 ) {
   2550 				value[ x ] = unit[ 0 ] * factor + unit[ 1 ];
   2551 			}
   2552 		} );
   2553 		return value;
   2554 	}
   2555 } );
   2556 
   2557 // Return an effect options object for the given parameters:
   2558 function _normalizeArguments( effect, options, speed, callback ) {
   2559 
   2560 	// Allow passing all options as the first parameter
   2561 	if ( $.isPlainObject( effect ) ) {
   2562 		options = effect;
   2563 		effect = effect.effect;
   2564 	}
   2565 
   2566 	// Convert to an object
   2567 	effect = { effect: effect };
   2568 
   2569 	// Catch (effect, null, ...)
   2570 	if ( options == null ) {
   2571 		options = {};
   2572 	}
   2573 
   2574 	// Catch (effect, callback)
   2575 	if ( $.isFunction( options ) ) {
   2576 		callback = options;
   2577 		speed = null;
   2578 		options = {};
   2579 	}
   2580 
   2581 	// Catch (effect, speed, ?)
   2582 	if ( typeof options === "number" || $.fx.speeds[ options ] ) {
   2583 		callback = speed;
   2584 		speed = options;
   2585 		options = {};
   2586 	}
   2587 
   2588 	// Catch (effect, options, callback)
   2589 	if ( $.isFunction( speed ) ) {
   2590 		callback = speed;
   2591 		speed = null;
   2592 	}
   2593 
   2594 	// Add options to effect
   2595 	if ( options ) {
   2596 		$.extend( effect, options );
   2597 	}
   2598 
   2599 	speed = speed || options.duration;
   2600 	effect.duration = $.fx.off ? 0 :
   2601 		typeof speed === "number" ? speed :
   2602 		speed in $.fx.speeds ? $.fx.speeds[ speed ] :
   2603 		$.fx.speeds._default;
   2604 
   2605 	effect.complete = callback || options.complete;
   2606 
   2607 	return effect;
   2608 }
   2609 
   2610 function standardAnimationOption( option ) {
   2611 
   2612 	// Valid standard speeds (nothing, number, named speed)
   2613 	if ( !option || typeof option === "number" || $.fx.speeds[ option ] ) {
   2614 		return true;
   2615 	}
   2616 
   2617 	// Invalid strings - treat as "normal" speed
   2618 	if ( typeof option === "string" && !$.effects.effect[ option ] ) {
   2619 		return true;
   2620 	}
   2621 
   2622 	// Complete callback
   2623 	if ( $.isFunction( option ) ) {
   2624 		return true;
   2625 	}
   2626 
   2627 	// Options hash (but not naming an effect)
   2628 	if ( typeof option === "object" && !option.effect ) {
   2629 		return true;
   2630 	}
   2631 
   2632 	// Didn't match any standard API
   2633 	return false;
   2634 }
   2635 
   2636 $.fn.extend( {
   2637 	effect: function( /* effect, options, speed, callback */ ) {
   2638 		var args = _normalizeArguments.apply( this, arguments ),
   2639 			effectMethod = $.effects.effect[ args.effect ],
   2640 			defaultMode = effectMethod.mode,
   2641 			queue = args.queue,
   2642 			queueName = queue || "fx",
   2643 			complete = args.complete,
   2644 			mode = args.mode,
   2645 			modes = [],
   2646 			prefilter = function( next ) {
   2647 				var el = $( this ),
   2648 					normalizedMode = $.effects.mode( el, mode ) || defaultMode;
   2649 
   2650 				// Sentinel for duck-punching the :animated psuedo-selector
   2651 				el.data( dataSpaceAnimated, true );
   2652 
   2653 				// Save effect mode for later use,
   2654 				// we can't just call $.effects.mode again later,
   2655 				// as the .show() below destroys the initial state
   2656 				modes.push( normalizedMode );
   2657 
   2658 				// See $.uiBackCompat inside of run() for removal of defaultMode in 1.13
   2659 				if ( defaultMode && ( normalizedMode === "show" ||
   2660 						( normalizedMode === defaultMode && normalizedMode === "hide" ) ) ) {
   2661 					el.show();
   2662 				}
   2663 
   2664 				if ( !defaultMode || normalizedMode !== "none" ) {
   2665 					$.effects.saveStyle( el );
   2666 				}
   2667 
   2668 				if ( $.isFunction( next ) ) {
   2669 					next();
   2670 				}
   2671 			};
   2672 
   2673 		if ( $.fx.off || !effectMethod ) {
   2674 
   2675 			// Delegate to the original method (e.g., .show()) if possible
   2676 			if ( mode ) {
   2677 				return this[ mode ]( args.duration, complete );
   2678 			} else {
   2679 				return this.each( function() {
   2680 					if ( complete ) {
   2681 						complete.call( this );
   2682 					}
   2683 				} );
   2684 			}
   2685 		}
   2686 
   2687 		function run( next ) {
   2688 			var elem = $( this );
   2689 
   2690 			function cleanup() {
   2691 				elem.removeData( dataSpaceAnimated );
   2692 
   2693 				$.effects.cleanUp( elem );
   2694 
   2695 				if ( args.mode === "hide" ) {
   2696 					elem.hide();
   2697 				}
   2698 
   2699 				done();
   2700 			}
   2701 
   2702 			function done() {
   2703 				if ( $.isFunction( complete ) ) {
   2704 					complete.call( elem[ 0 ] );
   2705 				}
   2706 
   2707 				if ( $.isFunction( next ) ) {
   2708 					next();
   2709 				}
   2710 			}
   2711 
   2712 			// Override mode option on a per element basis,
   2713 			// as toggle can be either show or hide depending on element state
   2714 			args.mode = modes.shift();
   2715 
   2716 			if ( $.uiBackCompat !== false && !defaultMode ) {
   2717 				if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) {
   2718 
   2719 					// Call the core method to track "olddisplay" properly
   2720 					elem[ mode ]();
   2721 					done();
   2722 				} else {
   2723 					effectMethod.call( elem[ 0 ], args, done );
   2724 				}
   2725 			} else {
   2726 				if ( args.mode === "none" ) {
   2727 
   2728 					// Call the core method to track "olddisplay" properly
   2729 					elem[ mode ]();
   2730 					done();
   2731 				} else {
   2732 					effectMethod.call( elem[ 0 ], args, cleanup );
   2733 				}
   2734 			}
   2735 		}
   2736 
   2737 		// Run prefilter on all elements first to ensure that
   2738 		// any showing or hiding happens before placeholder creation,
   2739 		// which ensures that any layout changes are correctly captured.
   2740 		return queue === false ?
   2741 			this.each( prefilter ).each( run ) :
   2742 			this.queue( queueName, prefilter ).queue( queueName, run );
   2743 	},
   2744 
   2745 	show: ( function( orig ) {
   2746 		return function( option ) {
   2747 			if ( standardAnimationOption( option ) ) {
   2748 				return orig.apply( this, arguments );
   2749 			} else {
   2750 				var args = _normalizeArguments.apply( this, arguments );
   2751 				args.mode = "show";
   2752 				return this.effect.call( this, args );
   2753 			}
   2754 		};
   2755 	} )( $.fn.show ),
   2756 
   2757 	hide: ( function( orig ) {
   2758 		return function( option ) {
   2759 			if ( standardAnimationOption( option ) ) {
   2760 				return orig.apply( this, arguments );
   2761 			} else {
   2762 				var args = _normalizeArguments.apply( this, arguments );
   2763 				args.mode = "hide";
   2764 				return this.effect.call( this, args );
   2765 			}
   2766 		};
   2767 	} )( $.fn.hide ),
   2768 
   2769 	toggle: ( function( orig ) {
   2770 		return function( option ) {
   2771 			if ( standardAnimationOption( option ) || typeof option === "boolean" ) {
   2772 				return orig.apply( this, arguments );
   2773 			} else {
   2774 				var args = _normalizeArguments.apply( this, arguments );
   2775 				args.mode = "toggle";
   2776 				return this.effect.call( this, args );
   2777 			}
   2778 		};
   2779 	} )( $.fn.toggle ),
   2780 
   2781 	cssUnit: function( key ) {
   2782 		var style = this.css( key ),
   2783 			val = [];
   2784 
   2785 		$.each( [ "em", "px", "%", "pt" ], function( i, unit ) {
   2786 			if ( style.indexOf( unit ) > 0 ) {
   2787 				val = [ parseFloat( style ), unit ];
   2788 			}
   2789 		} );
   2790 		return val;
   2791 	},
   2792 
   2793 	cssClip: function( clipObj ) {
   2794 		if ( clipObj ) {
   2795 			return this.css( "clip", "rect(" + clipObj.top + "px " + clipObj.right + "px " +
   2796 				clipObj.bottom + "px " + clipObj.left + "px)" );
   2797 		}
   2798 		return parseClip( this.css( "clip" ), this );
   2799 	},
   2800 
   2801 	transfer: function( options, done ) {
   2802 		var element = $( this ),
   2803 			target = $( options.to ),
   2804 			targetFixed = target.css( "position" ) === "fixed",
   2805 			body = $( "body" ),
   2806 			fixTop = targetFixed ? body.scrollTop() : 0,
   2807 			fixLeft = targetFixed ? body.scrollLeft() : 0,
   2808 			endPosition = target.offset(),
   2809 			animation = {
   2810 				top: endPosition.top - fixTop,
   2811 				left: endPosition.left - fixLeft,
   2812 				height: target.innerHeight(),
   2813 				width: target.innerWidth()
   2814 			},
   2815 			startPosition = element.offset(),
   2816 			transfer = $( "<div class='ui-effects-transfer'></div>" )
   2817 				.appendTo( "body" )
   2818 				.addClass( options.className )
   2819 				.css( {
   2820 					top: startPosition.top - fixTop,
   2821 					left: startPosition.left - fixLeft,
   2822 					height: element.innerHeight(),
   2823 					width: element.innerWidth(),
   2824 					position: targetFixed ? "fixed" : "absolute"
   2825 				} )
   2826 				.animate( animation, options.duration, options.easing, function() {
   2827 					transfer.remove();
   2828 					if ( $.isFunction( done ) ) {
   2829 						done();
   2830 					}
   2831 
   2832 				} );
   2833 	}
   2834 } );
   2835 
   2836 function parseClip( str, element ) {
   2837 		var outerWidth = element.outerWidth(),
   2838 			outerHeight = element.outerHeight(),
   2839 			clipRegex = /^rect\((-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto)\)$/,
   2840 			values = clipRegex.exec( str ) || [ "", 0, outerWidth, outerHeight, 0 ];
   2841 
   2842 		return {
   2843 			top: parseFloat( values[ 1 ] ) || 0,
   2844 			right: values[ 2 ] === "auto" ? outerWidth : parseFloat( values[ 2 ] ),
   2845 			bottom: values[ 3 ] === "auto" ? outerHeight : parseFloat( values[ 3 ] ),
   2846 			left: parseFloat( values[ 4 ] ) || 0
   2847 		};
   2848 }
   2849 
   2850 $.fx.step.clip = function( fx ) {
   2851 	if ( !fx.clipInit ) {
   2852 		fx.start = $( fx.elem ).cssClip();
   2853 		if ( typeof fx.end === "string" ) {
   2854 			fx.end = parseClip( fx.end, fx.elem );
   2855 		}
   2856 		fx.clipInit = true;
   2857 	}
   2858 
   2859 	$( fx.elem ).cssClip( {
   2860 		top: fx.pos * ( fx.end.top - fx.start.top ) + fx.start.top,
   2861 		right: fx.pos * ( fx.end.right - fx.start.right ) + fx.start.right,
   2862 		bottom: fx.pos * ( fx.end.bottom - fx.start.bottom ) + fx.start.bottom,
   2863 		left: fx.pos * ( fx.end.left - fx.start.left ) + fx.start.left
   2864 	} );
   2865 };
   2866 
   2867 } )();
   2868 
   2869 /******************************************************************************/
   2870 /*********************************** EASING ***********************************/
   2871 /******************************************************************************/
   2872 
   2873 ( function() {
   2874 
   2875 // Based on easing equations from Robert Penner (http://www.robertpenner.com/easing)
   2876 
   2877 var baseEasings = {};
   2878 
   2879 $.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) {
   2880 	baseEasings[ name ] = function( p ) {
   2881 		return Math.pow( p, i + 2 );
   2882 	};
   2883 } );
   2884 
   2885 $.extend( baseEasings, {
   2886 	Sine: function( p ) {
   2887 		return 1 - Math.cos( p * Math.PI / 2 );
   2888 	},
   2889 	Circ: function( p ) {
   2890 		return 1 - Math.sqrt( 1 - p * p );
   2891 	},
   2892 	Elastic: function( p ) {
   2893 		return p === 0 || p === 1 ? p :
   2894 			-Math.pow( 2, 8 * ( p - 1 ) ) * Math.sin( ( ( p - 1 ) * 80 - 7.5 ) * Math.PI / 15 );
   2895 	},
   2896 	Back: function( p ) {
   2897 		return p * p * ( 3 * p - 2 );
   2898 	},
   2899 	Bounce: function( p ) {
   2900 		var pow2,
   2901 			bounce = 4;
   2902 
   2903 		while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {}
   2904 		return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 );
   2905 	}
   2906 } );
   2907 
   2908 $.each( baseEasings, function( name, easeIn ) {
   2909 	$.easing[ "easeIn" + name ] = easeIn;
   2910 	$.easing[ "easeOut" + name ] = function( p ) {
   2911 		return 1 - easeIn( 1 - p );
   2912 	};
   2913 	$.easing[ "easeInOut" + name ] = function( p ) {
   2914 		return p < 0.5 ?
   2915 			easeIn( p * 2 ) / 2 :
   2916 			1 - easeIn( p * -2 + 2 ) / 2;
   2917 	};
   2918 } );
   2919 
   2920 } )();
   2921 
   2922 var effect = $.effects;
   2923 
   2924 
   2925 /*!
   2926  * jQuery UI Effects Blind 1.12.1
   2927  * http://jqueryui.com
   2928  *
   2929  * Copyright jQuery Foundation and other contributors
   2930  * Released under the MIT license.
   2931  * http://jquery.org/license
   2932  */
   2933 
   2934 //>>label: Blind Effect
   2935 //>>group: Effects
   2936 //>>description: Blinds the element.
   2937 //>>docs: http://api.jqueryui.com/blind-effect/
   2938 //>>demos: http://jqueryui.com/effect/
   2939 
   2940 
   2941 
   2942 var effectsEffectBlind = $.effects.define( "blind", "hide", function( options, done ) {
   2943 	var map = {
   2944 			up: [ "bottom", "top" ],
   2945 			vertical: [ "bottom", "top" ],
   2946 			down: [ "top", "bottom" ],
   2947 			left: [ "right", "left" ],
   2948 			horizontal: [ "right", "left" ],
   2949 			right: [ "left", "right" ]
   2950 		},
   2951 		element = $( this ),
   2952 		direction = options.direction || "up",
   2953 		start = element.cssClip(),
   2954 		animate = { clip: $.extend( {}, start ) },
   2955 		placeholder = $.effects.createPlaceholder( element );
   2956 
   2957 	animate.clip[ map[ direction ][ 0 ] ] = animate.clip[ map[ direction ][ 1 ] ];
   2958 
   2959 	if ( options.mode === "show" ) {
   2960 		element.cssClip( animate.clip );
   2961 		if ( placeholder ) {
   2962 			placeholder.css( $.effects.clipToBox( animate ) );
   2963 		}
   2964 
   2965 		animate.clip = start;
   2966 	}
   2967 
   2968 	if ( placeholder ) {
   2969 		placeholder.animate( $.effects.clipToBox( animate ), options.duration, options.easing );
   2970 	}
   2971 
   2972 	element.animate( animate, {
   2973 		queue: false,
   2974 		duration: options.duration,
   2975 		easing: options.easing,
   2976 		complete: done
   2977 	} );
   2978 } );
   2979 
   2980 
   2981 /*!
   2982  * jQuery UI Effects Bounce 1.12.1
   2983  * http://jqueryui.com
   2984  *
   2985  * Copyright jQuery Foundation and other contributors
   2986  * Released under the MIT license.
   2987  * http://jquery.org/license
   2988  */
   2989 
   2990 //>>label: Bounce Effect
   2991 //>>group: Effects
   2992 //>>description: Bounces an element horizontally or vertically n times.
   2993 //>>docs: http://api.jqueryui.com/bounce-effect/
   2994 //>>demos: http://jqueryui.com/effect/
   2995 
   2996 
   2997 
   2998 var effectsEffectBounce = $.effects.define( "bounce", function( options, done ) {
   2999 	var upAnim, downAnim, refValue,
   3000 		element = $( this ),
   3001 
   3002 		// Defaults:
   3003 		mode = options.mode,
   3004 		hide = mode === "hide",
   3005 		show = mode === "show",
   3006 		direction = options.direction || "up",
   3007 		distance = options.distance,
   3008 		times = options.times || 5,
   3009 
   3010 		// Number of internal animations
   3011 		anims = times * 2 + ( show || hide ? 1 : 0 ),
   3012 		speed = options.duration / anims,
   3013 		easing = options.easing,
   3014 
   3015 		// Utility:
   3016 		ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
   3017 		motion = ( direction === "up" || direction === "left" ),
   3018 		i = 0,
   3019 
   3020 		queuelen = element.queue().length;
   3021 
   3022 	$.effects.createPlaceholder( element );
   3023 
   3024 	refValue = element.css( ref );
   3025 
   3026 	// Default distance for the BIGGEST bounce is the outer Distance / 3
   3027 	if ( !distance ) {
   3028 		distance = element[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3;
   3029 	}
   3030 
   3031 	if ( show ) {
   3032 		downAnim = { opacity: 1 };
   3033 		downAnim[ ref ] = refValue;
   3034 
   3035 		// If we are showing, force opacity 0 and set the initial position
   3036 		// then do the "first" animation
   3037 		element
   3038 			.css( "opacity", 0 )
   3039 			.css( ref, motion ? -distance * 2 : distance * 2 )
   3040 			.animate( downAnim, speed, easing );
   3041 	}
   3042 
   3043 	// Start at the smallest distance if we are hiding
   3044 	if ( hide ) {
   3045 		distance = distance / Math.pow( 2, times - 1 );
   3046 	}
   3047 
   3048 	downAnim = {};
   3049 	downAnim[ ref ] = refValue;
   3050 
   3051 	// Bounces up/down/left/right then back to 0 -- times * 2 animations happen here
   3052 	for ( ; i < times; i++ ) {
   3053 		upAnim = {};
   3054 		upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
   3055 
   3056 		element
   3057 			.animate( upAnim, speed, easing )
   3058 			.animate( downAnim, speed, easing );
   3059 
   3060 		distance = hide ? distance * 2 : distance / 2;
   3061 	}
   3062 
   3063 	// Last Bounce when Hiding
   3064 	if ( hide ) {
   3065 		upAnim = { opacity: 0 };
   3066 		upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
   3067 
   3068 		element.animate( upAnim, speed, easing );
   3069 	}
   3070 
   3071 	element.queue( done );
   3072 
   3073 	$.effects.unshift( element, queuelen, anims + 1 );
   3074 } );
   3075 
   3076 
   3077 /*!
   3078  * jQuery UI Effects Clip 1.12.1
   3079  * http://jqueryui.com
   3080  *
   3081  * Copyright jQuery Foundation and other contributors
   3082  * Released under the MIT license.
   3083  * http://jquery.org/license
   3084  */
   3085 
   3086 //>>label: Clip Effect
   3087 //>>group: Effects
   3088 //>>description: Clips the element on and off like an old TV.
   3089 //>>docs: http://api.jqueryui.com/clip-effect/
   3090 //>>demos: http://jqueryui.com/effect/
   3091 
   3092 
   3093 
   3094 var effectsEffectClip = $.effects.define( "clip", "hide", function( options, done ) {
   3095 	var start,
   3096 		animate = {},
   3097 		element = $( this ),
   3098 		direction = options.direction || "vertical",
   3099 		both = direction === "both",
   3100 		horizontal = both || direction === "horizontal",
   3101 		vertical = both || direction === "vertical";
   3102 
   3103 	start = element.cssClip();
   3104 	animate.clip = {
   3105 		top: vertical ? ( start.bottom - start.top ) / 2 : start.top,
   3106 		right: horizontal ? ( start.right - start.left ) / 2 : start.right,
   3107 		bottom: vertical ? ( start.bottom - start.top ) / 2 : start.bottom,
   3108 		left: horizontal ? ( start.right - start.left ) / 2 : start.left
   3109 	};
   3110 
   3111 	$.effects.createPlaceholder( element );
   3112 
   3113 	if ( options.mode === "show" ) {
   3114 		element.cssClip( animate.clip );
   3115 		animate.clip = start;
   3116 	}
   3117 
   3118 	element.animate( animate, {
   3119 		queue: false,
   3120 		duration: options.duration,
   3121 		easing: options.easing,
   3122 		complete: done
   3123 	} );
   3124 
   3125 } );
   3126 
   3127 
   3128 /*!
   3129  * jQuery UI Effects Drop 1.12.1
   3130  * http://jqueryui.com
   3131  *
   3132  * Copyright jQuery Foundation and other contributors
   3133  * Released under the MIT license.
   3134  * http://jquery.org/license
   3135  */
   3136 
   3137 //>>label: Drop Effect
   3138 //>>group: Effects
   3139 //>>description: Moves an element in one direction and hides it at the same time.
   3140 //>>docs: http://api.jqueryui.com/drop-effect/
   3141 //>>demos: http://jqueryui.com/effect/
   3142 
   3143 
   3144 
   3145 var effectsEffectDrop = $.effects.define( "drop", "hide", function( options, done ) {
   3146 
   3147 	var distance,
   3148 		element = $( this ),
   3149 		mode = options.mode,
   3150 		show = mode === "show",
   3151 		direction = options.direction || "left",
   3152 		ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
   3153 		motion = ( direction === "up" || direction === "left" ) ? "-=" : "+=",
   3154 		oppositeMotion = ( motion === "+=" ) ? "-=" : "+=",
   3155 		animation = {
   3156 			opacity: 0
   3157 		};
   3158 
   3159 	$.effects.createPlaceholder( element );
   3160 
   3161 	distance = options.distance ||
   3162 		element[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ) / 2;
   3163 
   3164 	animation[ ref ] = motion + distance;
   3165 
   3166 	if ( show ) {
   3167 		element.css( animation );
   3168 
   3169 		animation[ ref ] = oppositeMotion + distance;
   3170 		animation.opacity = 1;
   3171 	}
   3172 
   3173 	// Animate
   3174 	element.animate( animation, {
   3175 		queue: false,
   3176 		duration: options.duration,
   3177 		easing: options.easing,
   3178 		complete: done
   3179 	} );
   3180 } );
   3181 
   3182 
   3183 /*!
   3184  * jQuery UI Effects Explode 1.12.1
   3185  * http://jqueryui.com
   3186  *
   3187  * Copyright jQuery Foundation and other contributors
   3188  * Released under the MIT license.
   3189  * http://jquery.org/license
   3190  */
   3191 
   3192 //>>label: Explode Effect
   3193 //>>group: Effects
   3194 // jscs:disable maximumLineLength
   3195 //>>description: Explodes an element in all directions into n pieces. Implodes an element to its original wholeness.
   3196 // jscs:enable maximumLineLength
   3197 //>>docs: http://api.jqueryui.com/explode-effect/
   3198 //>>demos: http://jqueryui.com/effect/
   3199 
   3200 
   3201 
   3202 var effectsEffectExplode = $.effects.define( "explode", "hide", function( options, done ) {
   3203 
   3204 	var i, j, left, top, mx, my,
   3205 		rows = options.pieces ? Math.round( Math.sqrt( options.pieces ) ) : 3,
   3206 		cells = rows,
   3207 		element = $( this ),
   3208 		mode = options.mode,
   3209 		show = mode === "show",
   3210 
   3211 		// Show and then visibility:hidden the element before calculating offset
   3212 		offset = element.show().css( "visibility", "hidden" ).offset(),
   3213 
   3214 		// Width and height of a piece
   3215 		width = Math.ceil( element.outerWidth() / cells ),
   3216 		height = Math.ceil( element.outerHeight() / rows ),
   3217 		pieces = [];
   3218 
   3219 	// Children animate complete:
   3220 	function childComplete() {
   3221 		pieces.push( this );
   3222 		if ( pieces.length === rows * cells ) {
   3223 			animComplete();
   3224 		}
   3225 	}
   3226 
   3227 	// Clone the element for each row and cell.
   3228 	for ( i = 0; i < rows; i++ ) { // ===>
   3229 		top = offset.top + i * height;
   3230 		my = i - ( rows - 1 ) / 2;
   3231 
   3232 		for ( j = 0; j < cells; j++ ) { // |||
   3233 			left = offset.left + j * width;
   3234 			mx = j - ( cells - 1 ) / 2;
   3235 
   3236 			// Create a clone of the now hidden main element that will be absolute positioned
   3237 			// within a wrapper div off the -left and -top equal to size of our pieces
   3238 			element
   3239 				.clone()
   3240 				.appendTo( "body" )
   3241 				.wrap( "<div></div>" )
   3242 				.css( {
   3243 					position: "absolute",
   3244 					visibility: "visible",
   3245 					left: -j * width,
   3246 					top: -i * height
   3247 				} )
   3248 
   3249 				// Select the wrapper - make it overflow: hidden and absolute positioned based on
   3250 				// where the original was located +left and +top equal to the size of pieces
   3251 				.parent()
   3252 					.addClass( "ui-effects-explode" )
   3253 					.css( {
   3254 						position: "absolute",
   3255 						overflow: "hidden",
   3256 						width: width,
   3257 						height: height,
   3258 						left: left + ( show ? mx * width : 0 ),
   3259 						top: top + ( show ? my * height : 0 ),
   3260 						opacity: show ? 0 : 1
   3261 					} )
   3262 					.animate( {
   3263 						left: left + ( show ? 0 : mx * width ),
   3264 						top: top + ( show ? 0 : my * height ),
   3265 						opacity: show ? 1 : 0
   3266 					}, options.duration || 500, options.easing, childComplete );
   3267 		}
   3268 	}
   3269 
   3270 	function animComplete() {
   3271 		element.css( {
   3272 			visibility: "visible"
   3273 		} );
   3274 		$( pieces ).remove();
   3275 		done();
   3276 	}
   3277 } );
   3278 
   3279 
   3280 /*!
   3281  * jQuery UI Effects Fade 1.12.1
   3282  * http://jqueryui.com
   3283  *
   3284  * Copyright jQuery Foundation and other contributors
   3285  * Released under the MIT license.
   3286  * http://jquery.org/license
   3287  */
   3288 
   3289 //>>label: Fade Effect
   3290 //>>group: Effects
   3291 //>>description: Fades the element.
   3292 //>>docs: http://api.jqueryui.com/fade-effect/
   3293 //>>demos: http://jqueryui.com/effect/
   3294 
   3295 
   3296 
   3297 var effectsEffectFade = $.effects.define( "fade", "toggle", function( options, done ) {
   3298 	var show = options.mode === "show";
   3299 
   3300 	$( this )
   3301 		.css( "opacity", show ? 0 : 1 )
   3302 		.animate( {
   3303 			opacity: show ? 1 : 0
   3304 		}, {
   3305 			queue: false,
   3306 			duration: options.duration,
   3307 			easing: options.easing,
   3308 			complete: done
   3309 		} );
   3310 } );
   3311 
   3312 
   3313 /*!
   3314  * jQuery UI Effects Fold 1.12.1
   3315  * http://jqueryui.com
   3316  *
   3317  * Copyright jQuery Foundation and other contributors
   3318  * Released under the MIT license.
   3319  * http://jquery.org/license
   3320  */
   3321 
   3322 //>>label: Fold Effect
   3323 //>>group: Effects
   3324 //>>description: Folds an element first horizontally and then vertically.
   3325 //>>docs: http://api.jqueryui.com/fold-effect/
   3326 //>>demos: http://jqueryui.com/effect/
   3327 
   3328 
   3329 
   3330 var effectsEffectFold = $.effects.define( "fold", "hide", function( options, done ) {
   3331 
   3332 	// Create element
   3333 	var element = $( this ),
   3334 		mode = options.mode,
   3335 		show = mode === "show",
   3336 		hide = mode === "hide",
   3337 		size = options.size || 15,
   3338 		percent = /([0-9]+)%/.exec( size ),
   3339 		horizFirst = !!options.horizFirst,
   3340 		ref = horizFirst ? [ "right", "bottom" ] : [ "bottom", "right" ],
   3341 		duration = options.duration / 2,
   3342 
   3343 		placeholder = $.effects.createPlaceholder( element ),
   3344 
   3345 		start = element.cssClip(),
   3346 		animation1 = { clip: $.extend( {}, start ) },
   3347 		animation2 = { clip: $.extend( {}, start ) },
   3348 
   3349 		distance = [ start[ ref[ 0 ] ], start[ ref[ 1 ] ] ],
   3350 
   3351 		queuelen = element.queue().length;
   3352 
   3353 	if ( percent ) {
   3354 		size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ];
   3355 	}
   3356 	animation1.clip[ ref[ 0 ] ] = size;
   3357 	animation2.clip[ ref[ 0 ] ] = size;
   3358 	animation2.clip[ ref[ 1 ] ] = 0;
   3359 
   3360 	if ( show ) {
   3361 		element.cssClip( animation2.clip );
   3362 		if ( placeholder ) {
   3363 			placeholder.css( $.effects.clipToBox( animation2 ) );
   3364 		}
   3365 
   3366 		animation2.clip = start;
   3367 	}
   3368 
   3369 	// Animate
   3370 	element
   3371 		.queue( function( next ) {
   3372 			if ( placeholder ) {
   3373 				placeholder
   3374 					.animate( $.effects.clipToBox( animation1 ), duration, options.easing )
   3375 					.animate( $.effects.clipToBox( animation2 ), duration, options.easing );
   3376 			}
   3377 
   3378 			next();
   3379 		} )
   3380 		.animate( animation1, duration, options.easing )
   3381 		.animate( animation2, duration, options.easing )
   3382 		.queue( done );
   3383 
   3384 	$.effects.unshift( element, queuelen, 4 );
   3385 } );
   3386 
   3387 
   3388 /*!
   3389  * jQuery UI Effects Highlight 1.12.1
   3390  * http://jqueryui.com
   3391  *
   3392  * Copyright jQuery Foundation and other contributors
   3393  * Released under the MIT license.
   3394  * http://jquery.org/license
   3395  */
   3396 
   3397 //>>label: Highlight Effect
   3398 //>>group: Effects
   3399 //>>description: Highlights the background of an element in a defined color for a custom duration.
   3400 //>>docs: http://api.jqueryui.com/highlight-effect/
   3401 //>>demos: http://jqueryui.com/effect/
   3402 
   3403 
   3404 
   3405 var effectsEffectHighlight = $.effects.define( "highlight", "show", function( options, done ) {
   3406 	var element = $( this ),
   3407 		animation = {
   3408 			backgroundColor: element.css( "backgroundColor" )
   3409 		};
   3410 
   3411 	if ( options.mode === "hide" ) {
   3412 		animation.opacity = 0;
   3413 	}
   3414 
   3415 	$.effects.saveStyle( element );
   3416 
   3417 	element
   3418 		.css( {
   3419 			backgroundImage: "none",
   3420 			backgroundColor: options.color || "#ffff99"
   3421 		} )
   3422 		.animate( animation, {
   3423 			queue: false,
   3424 			duration: options.duration,
   3425 			easing: options.easing,
   3426 			complete: done
   3427 		} );
   3428 } );
   3429 
   3430 
   3431 /*!
   3432  * jQuery UI Effects Size 1.12.1
   3433  * http://jqueryui.com
   3434  *
   3435  * Copyright jQuery Foundation and other contributors
   3436  * Released under the MIT license.
   3437  * http://jquery.org/license
   3438  */
   3439 
   3440 //>>label: Size Effect
   3441 //>>group: Effects
   3442 //>>description: Resize an element to a specified width and height.
   3443 //>>docs: http://api.jqueryui.com/size-effect/
   3444 //>>demos: http://jqueryui.com/effect/
   3445 
   3446 
   3447 
   3448 var effectsEffectSize = $.effects.define( "size", function( options, done ) {
   3449 
   3450 	// Create element
   3451 	var baseline, factor, temp,
   3452 		element = $( this ),
   3453 
   3454 		// Copy for children
   3455 		cProps = [ "fontSize" ],
   3456 		vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ],
   3457 		hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ],
   3458 
   3459 		// Set options
   3460 		mode = options.mode,
   3461 		restore = mode !== "effect",
   3462 		scale = options.scale || "both",
   3463 		origin = options.origin || [ "middle", "center" ],
   3464 		position = element.css( "position" ),
   3465 		pos = element.position(),
   3466 		original = $.effects.scaledDimensions( element ),
   3467 		from = options.from || original,
   3468 		to = options.to || $.effects.scaledDimensions( element, 0 );
   3469 
   3470 	$.effects.createPlaceholder( element );
   3471 
   3472 	if ( mode === "show" ) {
   3473 		temp = from;
   3474 		from = to;
   3475 		to = temp;
   3476 	}
   3477 
   3478 	// Set scaling factor
   3479 	factor = {
   3480 		from: {
   3481 			y: from.height / original.height,
   3482 			x: from.width / original.width
   3483 		},
   3484 		to: {
   3485 			y: to.height / original.height,
   3486 			x: to.width / original.width
   3487 		}
   3488 	};
   3489 
   3490 	// Scale the css box
   3491 	if ( scale === "box" || scale === "both" ) {
   3492 
   3493 		// Vertical props scaling
   3494 		if ( factor.from.y !== factor.to.y ) {
   3495 			from = $.effects.setTransition( element, vProps, factor.from.y, from );
   3496 			to = $.effects.setTransition( element, vProps, factor.to.y, to );
   3497 		}
   3498 
   3499 		// Horizontal props scaling
   3500 		if ( factor.from.x !== factor.to.x ) {
   3501 			from = $.effects.setTransition( element, hProps, factor.from.x, from );
   3502 			to = $.effects.setTransition( element, hProps, factor.to.x, to );
   3503 		}
   3504 	}
   3505 
   3506 	// Scale the content
   3507 	if ( scale === "content" || scale === "both" ) {
   3508 
   3509 		// Vertical props scaling
   3510 		if ( factor.from.y !== factor.to.y ) {
   3511 			from = $.effects.setTransition( element, cProps, factor.from.y, from );
   3512 			to = $.effects.setTransition( element, cProps, factor.to.y, to );
   3513 		}
   3514 	}
   3515 
   3516 	// Adjust the position properties based on the provided origin points
   3517 	if ( origin ) {
   3518 		baseline = $.effects.getBaseline( origin, original );
   3519 		from.top = ( original.outerHeight - from.outerHeight ) * baseline.y + pos.top;
   3520 		from.left = ( original.outerWidth - from.outerWidth ) * baseline.x + pos.left;
   3521 		to.top = ( original.outerHeight - to.outerHeight ) * baseline.y + pos.top;
   3522 		to.left = ( original.outerWidth - to.outerWidth ) * baseline.x + pos.left;
   3523 	}
   3524 	element.css( from );
   3525 
   3526 	// Animate the children if desired
   3527 	if ( scale === "content" || scale === "both" ) {
   3528 
   3529 		vProps = vProps.concat( [ "marginTop", "marginBottom" ] ).concat( cProps );
   3530 		hProps = hProps.concat( [ "marginLeft", "marginRight" ] );
   3531 
   3532 		// Only animate children with width attributes specified
   3533 		// TODO: is this right? should we include anything with css width specified as well
   3534 		element.find( "*[width]" ).each( function() {
   3535 			var child = $( this ),
   3536 				childOriginal = $.effects.scaledDimensions( child ),
   3537 				childFrom = {
   3538 					height: childOriginal.height * factor.from.y,
   3539 					width: childOriginal.width * factor.from.x,
   3540 					outerHeight: childOriginal.outerHeight * factor.from.y,
   3541 					outerWidth: childOriginal.outerWidth * factor.from.x
   3542 				},
   3543 				childTo = {
   3544 					height: childOriginal.height * factor.to.y,
   3545 					width: childOriginal.width * factor.to.x,
   3546 					outerHeight: childOriginal.height * factor.to.y,
   3547 					outerWidth: childOriginal.width * factor.to.x
   3548 				};
   3549 
   3550 			// Vertical props scaling
   3551 			if ( factor.from.y !== factor.to.y ) {
   3552 				childFrom = $.effects.setTransition( child, vProps, factor.from.y, childFrom );
   3553 				childTo = $.effects.setTransition( child, vProps, factor.to.y, childTo );
   3554 			}
   3555 
   3556 			// Horizontal props scaling
   3557 			if ( factor.from.x !== factor.to.x ) {
   3558 				childFrom = $.effects.setTransition( child, hProps, factor.from.x, childFrom );
   3559 				childTo = $.effects.setTransition( child, hProps, factor.to.x, childTo );
   3560 			}
   3561 
   3562 			if ( restore ) {
   3563 				$.effects.saveStyle( child );
   3564 			}
   3565 
   3566 			// Animate children
   3567 			child.css( childFrom );
   3568 			child.animate( childTo, options.duration, options.easing, function() {
   3569 
   3570 				// Restore children
   3571 				if ( restore ) {
   3572 					$.effects.restoreStyle( child );
   3573 				}
   3574 			} );
   3575 		} );
   3576 	}
   3577 
   3578 	// Animate
   3579 	element.animate( to, {
   3580 		queue: false,
   3581 		duration: options.duration,
   3582 		easing: options.easing,
   3583 		complete: function() {
   3584 
   3585 			var offset = element.offset();
   3586 
   3587 			if ( to.opacity === 0 ) {
   3588 				element.css( "opacity", from.opacity );
   3589 			}
   3590 
   3591 			if ( !restore ) {
   3592 				element
   3593 					.css( "position", position === "static" ? "relative" : position )
   3594 					.offset( offset );
   3595 
   3596 				// Need to save style here so that automatic style restoration
   3597 				// doesn't restore to the original styles from before the animation.
   3598 				$.effects.saveStyle( element );
   3599 			}
   3600 
   3601 			done();
   3602 		}
   3603 	} );
   3604 
   3605 } );
   3606 
   3607 
   3608 /*!
   3609  * jQuery UI Effects Scale 1.12.1
   3610  * http://jqueryui.com
   3611  *
   3612  * Copyright jQuery Foundation and other contributors
   3613  * Released under the MIT license.
   3614  * http://jquery.org/license
   3615  */
   3616 
   3617 //>>label: Scale Effect
   3618 //>>group: Effects
   3619 //>>description: Grows or shrinks an element and its content.
   3620 //>>docs: http://api.jqueryui.com/scale-effect/
   3621 //>>demos: http://jqueryui.com/effect/
   3622 
   3623 
   3624 
   3625 var effectsEffectScale = $.effects.define( "scale", function( options, done ) {
   3626 
   3627 	// Create element
   3628 	var el = $( this ),
   3629 		mode = options.mode,
   3630 		percent = parseInt( options.percent, 10 ) ||
   3631 			( parseInt( options.percent, 10 ) === 0 ? 0 : ( mode !== "effect" ? 0 : 100 ) ),
   3632 
   3633 		newOptions = $.extend( true, {
   3634 			from: $.effects.scaledDimensions( el ),
   3635 			to: $.effects.scaledDimensions( el, percent, options.direction || "both" ),
   3636 			origin: options.origin || [ "middle", "center" ]
   3637 		}, options );
   3638 
   3639 	// Fade option to support puff
   3640 	if ( options.fade ) {
   3641 		newOptions.from.opacity = 1;
   3642 		newOptions.to.opacity = 0;
   3643 	}
   3644 
   3645 	$.effects.effect.size.call( this, newOptions, done );
   3646 } );
   3647 
   3648 
   3649 /*!
   3650  * jQuery UI Effects Puff 1.12.1
   3651  * http://jqueryui.com
   3652  *
   3653  * Copyright jQuery Foundation and other contributors
   3654  * Released under the MIT license.
   3655  * http://jquery.org/license
   3656  */
   3657 
   3658 //>>label: Puff Effect
   3659 //>>group: Effects
   3660 //>>description: Creates a puff effect by scaling the element up and hiding it at the same time.
   3661 //>>docs: http://api.jqueryui.com/puff-effect/
   3662 //>>demos: http://jqueryui.com/effect/
   3663 
   3664 
   3665 
   3666 var effectsEffectPuff = $.effects.define( "puff", "hide", function( options, done ) {
   3667 	var newOptions = $.extend( true, {}, options, {
   3668 		fade: true,
   3669 		percent: parseInt( options.percent, 10 ) || 150
   3670 	} );
   3671 
   3672 	$.effects.effect.scale.call( this, newOptions, done );
   3673 } );
   3674 
   3675 
   3676 /*!
   3677  * jQuery UI Effects Pulsate 1.12.1
   3678  * http://jqueryui.com
   3679  *
   3680  * Copyright jQuery Foundation and other contributors
   3681  * Released under the MIT license.
   3682  * http://jquery.org/license
   3683  */
   3684 
   3685 //>>label: Pulsate Effect
   3686 //>>group: Effects
   3687 //>>description: Pulsates an element n times by changing the opacity to zero and back.
   3688 //>>docs: http://api.jqueryui.com/pulsate-effect/
   3689 //>>demos: http://jqueryui.com/effect/
   3690 
   3691 
   3692 
   3693 var effectsEffectPulsate = $.effects.define( "pulsate", "show", function( options, done ) {
   3694 	var element = $( this ),
   3695 		mode = options.mode,
   3696 		show = mode === "show",
   3697 		hide = mode === "hide",
   3698 		showhide = show || hide,
   3699 
   3700 		// Showing or hiding leaves off the "last" animation
   3701 		anims = ( ( options.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ),
   3702 		duration = options.duration / anims,
   3703 		animateTo = 0,
   3704 		i = 1,
   3705 		queuelen = element.queue().length;
   3706 
   3707 	if ( show || !element.is( ":visible" ) ) {
   3708 		element.css( "opacity", 0 ).show();
   3709 		animateTo = 1;
   3710 	}
   3711 
   3712 	// Anims - 1 opacity "toggles"
   3713 	for ( ; i < anims; i++ ) {
   3714 		element.animate( { opacity: animateTo }, duration, options.easing );
   3715 		animateTo = 1 - animateTo;
   3716 	}
   3717 
   3718 	element.animate( { opacity: animateTo }, duration, options.easing );
   3719 
   3720 	element.queue( done );
   3721 
   3722 	$.effects.unshift( element, queuelen, anims + 1 );
   3723 } );
   3724 
   3725 
   3726 /*!
   3727  * jQuery UI Effects Shake 1.12.1
   3728  * http://jqueryui.com
   3729  *
   3730  * Copyright jQuery Foundation and other contributors
   3731  * Released under the MIT license.
   3732  * http://jquery.org/license
   3733  */
   3734 
   3735 //>>label: Shake Effect
   3736 //>>group: Effects
   3737 //>>description: Shakes an element horizontally or vertically n times.
   3738 //>>docs: http://api.jqueryui.com/shake-effect/
   3739 //>>demos: http://jqueryui.com/effect/
   3740 
   3741 
   3742 
   3743 var effectsEffectShake = $.effects.define( "shake", function( options, done ) {
   3744 
   3745 	var i = 1,
   3746 		element = $( this ),
   3747 		direction = options.direction || "left",
   3748 		distance = options.distance || 20,
   3749 		times = options.times || 3,
   3750 		anims = times * 2 + 1,
   3751 		speed = Math.round( options.duration / anims ),
   3752 		ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
   3753 		positiveMotion = ( direction === "up" || direction === "left" ),
   3754 		animation = {},
   3755 		animation1 = {},
   3756 		animation2 = {},
   3757 
   3758 		queuelen = element.queue().length;
   3759 
   3760 	$.effects.createPlaceholder( element );
   3761 
   3762 	// Animation
   3763 	animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance;
   3764 	animation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2;
   3765 	animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2;
   3766 
   3767 	// Animate
   3768 	element.animate( animation, speed, options.easing );
   3769 
   3770 	// Shakes
   3771 	for ( ; i < times; i++ ) {
   3772 		element
   3773 			.animate( animation1, speed, options.easing )
   3774 			.animate( animation2, speed, options.easing );
   3775 	}
   3776 
   3777 	element
   3778 		.animate( animation1, speed, options.easing )
   3779 		.animate( animation, speed / 2, options.easing )
   3780 		.queue( done );
   3781 
   3782 	$.effects.unshift( element, queuelen, anims + 1 );
   3783 } );
   3784 
   3785 
   3786 /*!
   3787  * jQuery UI Effects Slide 1.12.1
   3788  * http://jqueryui.com
   3789  *
   3790  * Copyright jQuery Foundation and other contributors
   3791  * Released under the MIT license.
   3792  * http://jquery.org/license
   3793  */
   3794 
   3795 //>>label: Slide Effect
   3796 //>>group: Effects
   3797 //>>description: Slides an element in and out of the viewport.
   3798 //>>docs: http://api.jqueryui.com/slide-effect/
   3799 //>>demos: http://jqueryui.com/effect/
   3800 
   3801 
   3802 
   3803 var effectsEffectSlide = $.effects.define( "slide", "show", function( options, done ) {
   3804 	var startClip, startRef,
   3805 		element = $( this ),
   3806 		map = {
   3807 			up: [ "bottom", "top" ],
   3808 			down: [ "top", "bottom" ],
   3809 			left: [ "right", "left" ],
   3810 			right: [ "left", "right" ]
   3811 		},
   3812 		mode = options.mode,
   3813 		direction = options.direction || "left",
   3814 		ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
   3815 		positiveMotion = ( direction === "up" || direction === "left" ),
   3816 		distance = options.distance ||
   3817 			element[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ),
   3818 		animation = {};
   3819 
   3820 	$.effects.createPlaceholder( element );
   3821 
   3822 	startClip = element.cssClip();
   3823 	startRef = element.position()[ ref ];
   3824 
   3825 	// Define hide animation
   3826 	animation[ ref ] = ( positiveMotion ? -1 : 1 ) * distance + startRef;
   3827 	animation.clip = element.cssClip();
   3828 	animation.clip[ map[ direction ][ 1 ] ] = animation.clip[ map[ direction ][ 0 ] ];
   3829 
   3830 	// Reverse the animation if we're showing
   3831 	if ( mode === "show" ) {
   3832 		element.cssClip( animation.clip );
   3833 		element.css( ref, animation[ ref ] );
   3834 		animation.clip = startClip;
   3835 		animation[ ref ] = startRef;
   3836 	}
   3837 
   3838 	// Actually animate
   3839 	element.animate( animation, {
   3840 		queue: false,
   3841 		duration: options.duration,
   3842 		easing: options.easing,
   3843 		complete: done
   3844 	} );
   3845 } );
   3846 
   3847 
   3848 /*!
   3849  * jQuery UI Effects Transfer 1.12.1
   3850  * http://jqueryui.com
   3851  *
   3852  * Copyright jQuery Foundation and other contributors
   3853  * Released under the MIT license.
   3854  * http://jquery.org/license
   3855  */
   3856 
   3857 //>>label: Transfer Effect
   3858 //>>group: Effects
   3859 //>>description: Displays a transfer effect from one element to another.
   3860 //>>docs: http://api.jqueryui.com/transfer-effect/
   3861 //>>demos: http://jqueryui.com/effect/
   3862 
   3863 
   3864 
   3865 var effect;
   3866 if ( $.uiBackCompat !== false ) {
   3867 	effect = $.effects.define( "transfer", function( options, done ) {
   3868 		$( this ).transfer( options, done );
   3869 	} );
   3870 }
   3871 var effectsEffectTransfer = effect;
   3872 
   3873 
   3874 /*!
   3875  * jQuery UI Focusable 1.12.1
   3876  * http://jqueryui.com
   3877  *
   3878  * Copyright jQuery Foundation and other contributors
   3879  * Released under the MIT license.
   3880  * http://jquery.org/license
   3881  */
   3882 
   3883 //>>label: :focusable Selector
   3884 //>>group: Core
   3885 //>>description: Selects elements which can be focused.
   3886 //>>docs: http://api.jqueryui.com/focusable-selector/
   3887 
   3888 
   3889 
   3890 // Selectors
   3891 $.ui.focusable = function( element, hasTabindex ) {
   3892 	var map, mapName, img, focusableIfVisible, fieldset,
   3893 		nodeName = element.nodeName.toLowerCase();
   3894 
   3895 	if ( "area" === nodeName ) {
   3896 		map = element.parentNode;
   3897 		mapName = map.name;
   3898 		if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
   3899 			return false;
   3900 		}
   3901 		img = $( "img[usemap='#" + mapName + "']" );
   3902 		return img.length > 0 && img.is( ":visible" );
   3903 	}
   3904 
   3905 	if ( /^(input|select|textarea|button|object)$/.test( nodeName ) ) {
   3906 		focusableIfVisible = !element.disabled;
   3907 
   3908 		if ( focusableIfVisible ) {
   3909 
   3910 			// Form controls within a disabled fieldset are disabled.
   3911 			// However, controls within the fieldset's legend do not get disabled.
   3912 			// Since controls generally aren't placed inside legends, we skip
   3913 			// this portion of the check.
   3914 			fieldset = $( element ).closest( "fieldset" )[ 0 ];
   3915 			if ( fieldset ) {
   3916 				focusableIfVisible = !fieldset.disabled;
   3917 			}
   3918 		}
   3919 	} else if ( "a" === nodeName ) {
   3920 		focusableIfVisible = element.href || hasTabindex;
   3921 	} else {
   3922 		focusableIfVisible = hasTabindex;
   3923 	}
   3924 
   3925 	return focusableIfVisible && $( element ).is( ":visible" ) && visible( $( element ) );
   3926 };
   3927 
   3928 // Support: IE 8 only
   3929 // IE 8 doesn't resolve inherit to visible/hidden for computed values
   3930 function visible( element ) {
   3931 	var visibility = element.css( "visibility" );
   3932 	while ( visibility === "inherit" ) {
   3933 		element = element.parent();
   3934 		visibility = element.css( "visibility" );
   3935 	}
   3936 	return visibility !== "hidden";
   3937 }
   3938 
   3939 $.extend( $.expr[ ":" ], {
   3940 	focusable: function( element ) {
   3941 		return $.ui.focusable( element, $.attr( element, "tabindex" ) != null );
   3942 	}
   3943 } );
   3944 
   3945 var focusable = $.ui.focusable;
   3946 
   3947 
   3948 
   3949 
   3950 // Support: IE8 Only
   3951 // IE8 does not support the form attribute and when it is supplied. It overwrites the form prop
   3952 // with a string, so we need to find the proper form.
   3953 var form = $.fn.form = function() {
   3954 	return typeof this[ 0 ].form === "string" ? this.closest( "form" ) : $( this[ 0 ].form );
   3955 };
   3956 
   3957 
   3958 /*!
   3959  * jQuery UI Form Reset Mixin 1.12.1
   3960  * http://jqueryui.com
   3961  *
   3962  * Copyright jQuery Foundation and other contributors
   3963  * Released under the MIT license.
   3964  * http://jquery.org/license
   3965  */
   3966 
   3967 //>>label: Form Reset Mixin
   3968 //>>group: Core
   3969 //>>description: Refresh input widgets when their form is reset
   3970 //>>docs: http://api.jqueryui.com/form-reset-mixin/
   3971 
   3972 
   3973 
   3974 var formResetMixin = $.ui.formResetMixin = {
   3975 	_formResetHandler: function() {
   3976 		var form = $( this );
   3977 
   3978 		// Wait for the form reset to actually happen before refreshing
   3979 		setTimeout( function() {
   3980 			var instances = form.data( "ui-form-reset-instances" );
   3981 			$.each( instances, function() {
   3982 				this.refresh();
   3983 			} );
   3984 		} );
   3985 	},
   3986 
   3987 	_bindFormResetHandler: function() {
   3988 		this.form = this.element.form();
   3989 		if ( !this.form.length ) {
   3990 			return;
   3991 		}
   3992 
   3993 		var instances = this.form.data( "ui-form-reset-instances" ) || [];
   3994 		if ( !instances.length ) {
   3995 
   3996 			// We don't use _on() here because we use a single event handler per form
   3997 			this.form.on( "reset.ui-form-reset", this._formResetHandler );
   3998 		}
   3999 		instances.push( this );
   4000 		this.form.data( "ui-form-reset-instances", instances );
   4001 	},
   4002 
   4003 	_unbindFormResetHandler: function() {
   4004 		if ( !this.form.length ) {
   4005 			return;
   4006 		}
   4007 
   4008 		var instances = this.form.data( "ui-form-reset-instances" );
   4009 		instances.splice( $.inArray( this, instances ), 1 );
   4010 		if ( instances.length ) {
   4011 			this.form.data( "ui-form-reset-instances", instances );
   4012 		} else {
   4013 			this.form
   4014 				.removeData( "ui-form-reset-instances" )
   4015 				.off( "reset.ui-form-reset" );
   4016 		}
   4017 	}
   4018 };
   4019 
   4020 
   4021 /*!
   4022  * jQuery UI Support for jQuery core 1.7.x 1.12.1
   4023  * http://jqueryui.com
   4024  *
   4025  * Copyright jQuery Foundation and other contributors
   4026  * Released under the MIT license.
   4027  * http://jquery.org/license
   4028  *
   4029  */
   4030 
   4031 //>>label: jQuery 1.7 Support
   4032 //>>group: Core
   4033 //>>description: Support version 1.7.x of jQuery core
   4034 
   4035 
   4036 
   4037 // Support: jQuery 1.7 only
   4038 // Not a great way to check versions, but since we only support 1.7+ and only
   4039 // need to detect <1.8, this is a simple check that should suffice. Checking
   4040 // for "1.7." would be a bit safer, but the version string is 1.7, not 1.7.0
   4041 // and we'll never reach 1.70.0 (if we do, we certainly won't be supporting
   4042 // 1.7 anymore). See #11197 for why we're not using feature detection.
   4043 if ( $.fn.jquery.substring( 0, 3 ) === "1.7" ) {
   4044 
   4045 	// Setters for .innerWidth(), .innerHeight(), .outerWidth(), .outerHeight()
   4046 	// Unlike jQuery Core 1.8+, these only support numeric values to set the
   4047 	// dimensions in pixels
   4048 	$.each( [ "Width", "Height" ], function( i, name ) {
   4049 		var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
   4050 			type = name.toLowerCase(),
   4051 			orig = {
   4052 				innerWidth: $.fn.innerWidth,
   4053 				innerHeight: $.fn.innerHeight,
   4054 				outerWidth: $.fn.outerWidth,
   4055 				outerHeight: $.fn.outerHeight
   4056 			};
   4057 
   4058 		function reduce( elem, size, border, margin ) {
   4059 			$.each( side, function() {
   4060 				size -= parseFloat( $.css( elem, "padding" + this ) ) || 0;
   4061 				if ( border ) {
   4062 					size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0;
   4063 				}
   4064 				if ( margin ) {
   4065 					size -= parseFloat( $.css( elem, "margin" + this ) ) || 0;
   4066 				}
   4067 			} );
   4068 			return size;
   4069 		}
   4070 
   4071 		$.fn[ "inner" + name ] = function( size ) {
   4072 			if ( size === undefined ) {
   4073 				return orig[ "inner" + name ].call( this );
   4074 			}
   4075 
   4076 			return this.each( function() {
   4077 				$( this ).css( type, reduce( this, size ) + "px" );
   4078 			} );
   4079 		};
   4080 
   4081 		$.fn[ "outer" + name ] = function( size, margin ) {
   4082 			if ( typeof size !== "number" ) {
   4083 				return orig[ "outer" + name ].call( this, size );
   4084 			}
   4085 
   4086 			return this.each( function() {
   4087 				$( this ).css( type, reduce( this, size, true, margin ) + "px" );
   4088 			} );
   4089 		};
   4090 	} );
   4091 
   4092 	$.fn.addBack = function( selector ) {
   4093 		return this.add( selector == null ?
   4094 			this.prevObject : this.prevObject.filter( selector )
   4095 		);
   4096 	};
   4097 }
   4098 
   4099 ;
   4100 /*!
   4101  * jQuery UI Keycode 1.12.1
   4102  * http://jqueryui.com
   4103  *
   4104  * Copyright jQuery Foundation and other contributors
   4105  * Released under the MIT license.
   4106  * http://jquery.org/license
   4107  */
   4108 
   4109 //>>label: Keycode
   4110 //>>group: Core
   4111 //>>description: Provide keycodes as keynames
   4112 //>>docs: http://api.jqueryui.com/jQuery.ui.keyCode/
   4113 
   4114 
   4115 var keycode = $.ui.keyCode = {
   4116 	BACKSPACE: 8,
   4117 	COMMA: 188,
   4118 	DELETE: 46,
   4119 	DOWN: 40,
   4120 	END: 35,
   4121 	ENTER: 13,
   4122 	ESCAPE: 27,
   4123 	HOME: 36,
   4124 	LEFT: 37,
   4125 	PAGE_DOWN: 34,
   4126 	PAGE_UP: 33,
   4127 	PERIOD: 190,
   4128 	RIGHT: 39,
   4129 	SPACE: 32,
   4130 	TAB: 9,
   4131 	UP: 38
   4132 };
   4133 
   4134 
   4135 
   4136 
   4137 // Internal use only
   4138 var escapeSelector = $.ui.escapeSelector = ( function() {
   4139 	var selectorEscape = /([!"#$%&'()*+,./:;<=>?@[\]^`{|}~])/g;
   4140 	return function( selector ) {
   4141 		return selector.replace( selectorEscape, "\\$1" );
   4142 	};
   4143 } )();
   4144 
   4145 
   4146 /*!
   4147  * jQuery UI Labels 1.12.1
   4148  * http://jqueryui.com
   4149  *
   4150  * Copyright jQuery Foundation and other contributors
   4151  * Released under the MIT license.
   4152  * http://jquery.org/license
   4153  */
   4154 
   4155 //>>label: labels
   4156 //>>group: Core
   4157 //>>description: Find all the labels associated with a given input
   4158 //>>docs: http://api.jqueryui.com/labels/
   4159 
   4160 
   4161 
   4162 var labels = $.fn.labels = function() {
   4163 	var ancestor, selector, id, labels, ancestors;
   4164 
   4165 	// Check control.labels first
   4166 	if ( this[ 0 ].labels && this[ 0 ].labels.length ) {
   4167 		return this.pushStack( this[ 0 ].labels );
   4168 	}
   4169 
   4170 	// Support: IE <= 11, FF <= 37, Android <= 2.3 only
   4171 	// Above browsers do not support control.labels. Everything below is to support them
   4172 	// as well as document fragments. control.labels does not work on document fragments
   4173 	labels = this.eq( 0 ).parents( "label" );
   4174 
   4175 	// Look for the label based on the id
   4176 	id = this.attr( "id" );
   4177 	if ( id ) {
   4178 
   4179 		// We don't search against the document in case the element
   4180 		// is disconnected from the DOM
   4181 		ancestor = this.eq( 0 ).parents().last();
   4182 
   4183 		// Get a full set of top level ancestors
   4184 		ancestors = ancestor.add( ancestor.length ? ancestor.siblings() : this.siblings() );
   4185 
   4186 		// Create a selector for the label based on the id
   4187 		selector = "label[for='" + $.ui.escapeSelector( id ) + "']";
   4188 
   4189 		labels = labels.add( ancestors.find( selector ).addBack( selector ) );
   4190 
   4191 	}
   4192 
   4193 	// Return whatever we have found for labels
   4194 	return this.pushStack( labels );
   4195 };
   4196 
   4197 
   4198 /*!
   4199  * jQuery UI Scroll Parent 1.12.1
   4200  * http://jqueryui.com
   4201  *
   4202  * Copyright jQuery Foundation and other contributors
   4203  * Released under the MIT license.
   4204  * http://jquery.org/license
   4205  */
   4206 
   4207 //>>label: scrollParent
   4208 //>>group: Core
   4209 //>>description: Get the closest ancestor element that is scrollable.
   4210 //>>docs: http://api.jqueryui.com/scrollParent/
   4211 
   4212 
   4213 
   4214 var scrollParent = $.fn.scrollParent = function( includeHidden ) {
   4215 	var position = this.css( "position" ),
   4216 		excludeStaticParent = position === "absolute",
   4217 		overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/,
   4218 		scrollParent = this.parents().filter( function() {
   4219 			var parent = $( this );
   4220 			if ( excludeStaticParent && parent.css( "position" ) === "static" ) {
   4221 				return false;
   4222 			}
   4223 			return overflowRegex.test( parent.css( "overflow" ) + parent.css( "overflow-y" ) +
   4224 				parent.css( "overflow-x" ) );
   4225 		} ).eq( 0 );
   4226 
   4227 	return position === "fixed" || !scrollParent.length ?
   4228 		$( this[ 0 ].ownerDocument || document ) :
   4229 		scrollParent;
   4230 };
   4231 
   4232 
   4233 /*!
   4234  * jQuery UI Tabbable 1.12.1
   4235  * http://jqueryui.com
   4236  *
   4237  * Copyright jQuery Foundation and other contributors
   4238  * Released under the MIT license.
   4239  * http://jquery.org/license
   4240  */
   4241 
   4242 //>>label: :tabbable Selector
   4243 //>>group: Core
   4244 //>>description: Selects elements which can be tabbed to.
   4245 //>>docs: http://api.jqueryui.com/tabbable-selector/
   4246 
   4247 
   4248 
   4249 var tabbable = $.extend( $.expr[ ":" ], {
   4250 	tabbable: function( element ) {
   4251 		var tabIndex = $.attr( element, "tabindex" ),
   4252 			hasTabindex = tabIndex != null;
   4253 		return ( !hasTabindex || tabIndex >= 0 ) && $.ui.focusable( element, hasTabindex );
   4254 	}
   4255 } );
   4256 
   4257 
   4258 /*!
   4259  * jQuery UI Unique ID 1.12.1
   4260  * http://jqueryui.com
   4261  *
   4262  * Copyright jQuery Foundation and other contributors
   4263  * Released under the MIT license.
   4264  * http://jquery.org/license
   4265  */
   4266 
   4267 //>>label: uniqueId
   4268 //>>group: Core
   4269 //>>description: Functions to generate and remove uniqueId's
   4270 //>>docs: http://api.jqueryui.com/uniqueId/
   4271 
   4272 
   4273 
   4274 var uniqueId = $.fn.extend( {
   4275 	uniqueId: ( function() {
   4276 		var uuid = 0;
   4277 
   4278 		return function() {
   4279 			return this.each( function() {
   4280 				if ( !this.id ) {
   4281 					this.id = "ui-id-" + ( ++uuid );
   4282 				}
   4283 			} );
   4284 		};
   4285 	} )(),
   4286 
   4287 	removeUniqueId: function() {
   4288 		return this.each( function() {
   4289 			if ( /^ui-id-\d+$/.test( this.id ) ) {
   4290 				$( this ).removeAttr( "id" );
   4291 			}
   4292 		} );
   4293 	}
   4294 } );
   4295 
   4296 
   4297 /*!
   4298  * jQuery UI Accordion 1.12.1
   4299  * http://jqueryui.com
   4300  *
   4301  * Copyright jQuery Foundation and other contributors
   4302  * Released under the MIT license.
   4303  * http://jquery.org/license
   4304  */
   4305 
   4306 //>>label: Accordion
   4307 //>>group: Widgets
   4308 // jscs:disable maximumLineLength
   4309 //>>description: Displays collapsible content panels for presenting information in a limited amount of space.
   4310 // jscs:enable maximumLineLength
   4311 //>>docs: http://api.jqueryui.com/accordion/
   4312 //>>demos: http://jqueryui.com/accordion/
   4313 //>>css.structure: ../../themes/base/core.css
   4314 //>>css.structure: ../../themes/base/accordion.css
   4315 //>>css.theme: ../../themes/base/theme.css
   4316 
   4317 
   4318 
   4319 var widgetsAccordion = $.widget( "ui.accordion", {
   4320 	version: "1.12.1",
   4321 	options: {
   4322 		active: 0,
   4323 		animate: {},
   4324 		classes: {
   4325 			"ui-accordion-header": "ui-corner-top",
   4326 			"ui-accordion-header-collapsed": "ui-corner-all",
   4327 			"ui-accordion-content": "ui-corner-bottom"
   4328 		},
   4329 		collapsible: false,
   4330 		event: "click",
   4331 		header: "> li > :first-child, > :not(li):even",
   4332 		heightStyle: "auto",
   4333 		icons: {
   4334 			activeHeader: "ui-icon-triangle-1-s",
   4335 			header: "ui-icon-triangle-1-e"
   4336 		},
   4337 
   4338 		// Callbacks
   4339 		activate: null,
   4340 		beforeActivate: null
   4341 	},
   4342 
   4343 	hideProps: {
   4344 		borderTopWidth: "hide",
   4345 		borderBottomWidth: "hide",
   4346 		paddingTop: "hide",
   4347 		paddingBottom: "hide",
   4348 		height: "hide"
   4349 	},
   4350 
   4351 	showProps: {
   4352 		borderTopWidth: "show",
   4353 		borderBottomWidth: "show",
   4354 		paddingTop: "show",
   4355 		paddingBottom: "show",
   4356 		height: "show"
   4357 	},
   4358 
   4359 	_create: function() {
   4360 		var options = this.options;
   4361 
   4362 		this.prevShow = this.prevHide = $();
   4363 		this._addClass( "ui-accordion", "ui-widget ui-helper-reset" );
   4364 		this.element.attr( "role", "tablist" );
   4365 
   4366 		// Don't allow collapsible: false and active: false / null
   4367 		if ( !options.collapsible && ( options.active === false || options.active == null ) ) {
   4368 			options.active = 0;
   4369 		}
   4370 
   4371 		this._processPanels();
   4372 
   4373 		// handle negative values
   4374 		if ( options.active < 0 ) {
   4375 			options.active += this.headers.length;
   4376 		}
   4377 		this._refresh();
   4378 	},
   4379 
   4380 	_getCreateEventData: function() {
   4381 		return {
   4382 			header: this.active,
   4383 			panel: !this.active.length ? $() : this.active.next()
   4384 		};
   4385 	},
   4386 
   4387 	_createIcons: function() {
   4388 		var icon, children,
   4389 			icons = this.options.icons;
   4390 
   4391 		if ( icons ) {
   4392 			icon = $( "<span>" );
   4393 			this._addClass( icon, "ui-accordion-header-icon", "ui-icon " + icons.header );
   4394 			icon.prependTo( this.headers );
   4395 			children = this.active.children( ".ui-accordion-header-icon" );
   4396 			this._removeClass( children, icons.header )
   4397 				._addClass( children, null, icons.activeHeader )
   4398 				._addClass( this.headers, "ui-accordion-icons" );
   4399 		}
   4400 	},
   4401 
   4402 	_destroyIcons: function() {
   4403 		this._removeClass( this.headers, "ui-accordion-icons" );
   4404 		this.headers.children( ".ui-accordion-header-icon" ).remove();
   4405 	},
   4406 
   4407 	_destroy: function() {
   4408 		var contents;
   4409 
   4410 		// Clean up main element
   4411 		this.element.removeAttr( "role" );
   4412 
   4413 		// Clean up headers
   4414 		this.headers
   4415 			.removeAttr( "role aria-expanded aria-selected aria-controls tabIndex" )
   4416 			.removeUniqueId();
   4417 
   4418 		this._destroyIcons();
   4419 
   4420 		// Clean up content panels
   4421 		contents = this.headers.next()
   4422 			.css( "display", "" )
   4423 			.removeAttr( "role aria-hidden aria-labelledby" )
   4424 			.removeUniqueId();
   4425 
   4426 		if ( this.options.heightStyle !== "content" ) {
   4427 			contents.css( "height", "" );
   4428 		}
   4429 	},
   4430 
   4431 	_setOption: function( key, value ) {
   4432 		if ( key === "active" ) {
   4433 
   4434 			// _activate() will handle invalid values and update this.options
   4435 			this._activate( value );
   4436 			return;
   4437 		}
   4438 
   4439 		if ( key === "event" ) {
   4440 			if ( this.options.event ) {
   4441 				this._off( this.headers, this.options.event );
   4442 			}
   4443 			this._setupEvents( value );
   4444 		}
   4445 
   4446 		this._super( key, value );
   4447 
   4448 		// Setting collapsible: false while collapsed; open first panel
   4449 		if ( key === "collapsible" && !value && this.options.active === false ) {
   4450 			this._activate( 0 );
   4451 		}
   4452 
   4453 		if ( key === "icons" ) {
   4454 			this._destroyIcons();
   4455 			if ( value ) {
   4456 				this._createIcons();
   4457 			}
   4458 		}
   4459 	},
   4460 
   4461 	_setOptionDisabled: function( value ) {
   4462 		this._super( value );
   4463 
   4464 		this.element.attr( "aria-disabled", value );
   4465 
   4466 		// Support: IE8 Only
   4467 		// #5332 / #6059 - opacity doesn't cascade to positioned elements in IE
   4468 		// so we need to add the disabled class to the headers and panels
   4469 		this._toggleClass( null, "ui-state-disabled", !!value );
   4470 		this._toggleClass( this.headers.add( this.headers.next() ), null, "ui-state-disabled",
   4471 			!!value );
   4472 	},
   4473 
   4474 	_keydown: function( event ) {
   4475 		if ( event.altKey || event.ctrlKey ) {
   4476 			return;
   4477 		}
   4478 
   4479 		var keyCode = $.ui.keyCode,
   4480 			length = this.headers.length,
   4481 			currentIndex = this.headers.index( event.target ),
   4482 			toFocus = false;
   4483 
   4484 		switch ( event.keyCode ) {
   4485 		case keyCode.RIGHT:
   4486 		case keyCode.DOWN:
   4487 			toFocus = this.headers[ ( currentIndex + 1 ) % length ];
   4488 			break;
   4489 		case keyCode.LEFT:
   4490 		case keyCode.UP:
   4491 			toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
   4492 			break;
   4493 		case keyCode.SPACE:
   4494 		case keyCode.ENTER:
   4495 			this._eventHandler( event );
   4496 			break;
   4497 		case keyCode.HOME:
   4498 			toFocus = this.headers[ 0 ];
   4499 			break;
   4500 		case keyCode.END:
   4501 			toFocus = this.headers[ length - 1 ];
   4502 			break;
   4503 		}
   4504 
   4505 		if ( toFocus ) {
   4506 			$( event.target ).attr( "tabIndex", -1 );
   4507 			$( toFocus ).attr( "tabIndex", 0 );
   4508 			$( toFocus ).trigger( "focus" );
   4509 			event.preventDefault();
   4510 		}
   4511 	},
   4512 
   4513 	_panelKeyDown: function( event ) {
   4514 		if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) {
   4515 			$( event.currentTarget ).prev().trigger( "focus" );
   4516 		}
   4517 	},
   4518 
   4519 	refresh: function() {
   4520 		var options = this.options;
   4521 		this._processPanels();
   4522 
   4523 		// Was collapsed or no panel
   4524 		if ( ( options.active === false && options.collapsible === true ) ||
   4525 				!this.headers.length ) {
   4526 			options.active = false;
   4527 			this.active = $();
   4528 
   4529 		// active false only when collapsible is true
   4530 		} else if ( options.active === false ) {
   4531 			this._activate( 0 );
   4532 
   4533 		// was active, but active panel is gone
   4534 		} else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
   4535 
   4536 			// all remaining panel are disabled
   4537 			if ( this.headers.length === this.headers.find( ".ui-state-disabled" ).length ) {
   4538 				options.active = false;
   4539 				this.active = $();
   4540 
   4541 			// activate previous panel
   4542 			} else {
   4543 				this._activate( Math.max( 0, options.active - 1 ) );
   4544 			}
   4545 
   4546 		// was active, active panel still exists
   4547 		} else {
   4548 
   4549 			// make sure active index is correct
   4550 			options.active = this.headers.index( this.active );
   4551 		}
   4552 
   4553 		this._destroyIcons();
   4554 
   4555 		this._refresh();
   4556 	},
   4557 
   4558 	_processPanels: function() {
   4559 		var prevHeaders = this.headers,
   4560 			prevPanels = this.panels;
   4561 
   4562 		this.headers = this.element.find( this.options.header );
   4563 		this._addClass( this.headers, "ui-accordion-header ui-accordion-header-collapsed",
   4564 			"ui-state-default" );
   4565 
   4566 		this.panels = this.headers.next().filter( ":not(.ui-accordion-content-active)" ).hide();
   4567 		this._addClass( this.panels, "ui-accordion-content", "ui-helper-reset ui-widget-content" );
   4568 
   4569 		// Avoid memory leaks (#10056)
   4570 		if ( prevPanels ) {
   4571 			this._off( prevHeaders.not( this.headers ) );
   4572 			this._off( prevPanels.not( this.panels ) );
   4573 		}
   4574 	},
   4575 
   4576 	_refresh: function() {
   4577 		var maxHeight,
   4578 			options = this.options,
   4579 			heightStyle = options.heightStyle,
   4580 			parent = this.element.parent();
   4581 
   4582 		this.active = this._findActive( options.active );
   4583 		this._addClass( this.active, "ui-accordion-header-active", "ui-state-active" )
   4584 			._removeClass( this.active, "ui-accordion-header-collapsed" );
   4585 		this._addClass( this.active.next(), "ui-accordion-content-active" );
   4586 		this.active.next().show();
   4587 
   4588 		this.headers
   4589 			.attr( "role", "tab" )
   4590 			.each( function() {
   4591 				var header = $( this ),
   4592 					headerId = header.uniqueId().attr( "id" ),
   4593 					panel = header.next(),
   4594 					panelId = panel.uniqueId().attr( "id" );
   4595 				header.attr( "aria-controls", panelId );
   4596 				panel.attr( "aria-labelledby", headerId );
   4597 			} )
   4598 			.next()
   4599 				.attr( "role", "tabpanel" );
   4600 
   4601 		this.headers
   4602 			.not( this.active )
   4603 				.attr( {
   4604 					"aria-selected": "false",
   4605 					"aria-expanded": "false",
   4606 					tabIndex: -1
   4607 				} )
   4608 				.next()
   4609 					.attr( {
   4610 						"aria-hidden": "true"
   4611 					} )
   4612 					.hide();
   4613 
   4614 		// Make sure at least one header is in the tab order
   4615 		if ( !this.active.length ) {
   4616 			this.headers.eq( 0 ).attr( "tabIndex", 0 );
   4617 		} else {
   4618 			this.active.attr( {
   4619 				"aria-selected": "true",
   4620 				"aria-expanded": "true",
   4621 				tabIndex: 0
   4622 			} )
   4623 				.next()
   4624 					.attr( {
   4625 						"aria-hidden": "false"
   4626 					} );
   4627 		}
   4628 
   4629 		this._createIcons();
   4630 
   4631 		this._setupEvents( options.event );
   4632 
   4633 		if ( heightStyle === "fill" ) {
   4634 			maxHeight = parent.height();
   4635 			this.element.siblings( ":visible" ).each( function() {
   4636 				var elem = $( this ),
   4637 					position = elem.css( "position" );
   4638 
   4639 				if ( position === "absolute" || position === "fixed" ) {
   4640 					return;
   4641 				}
   4642 				maxHeight -= elem.outerHeight( true );
   4643 			} );
   4644 
   4645 			this.headers.each( function() {
   4646 				maxHeight -= $( this ).outerHeight( true );
   4647 			} );
   4648 
   4649 			this.headers.next()
   4650 				.each( function() {
   4651 					$( this ).height( Math.max( 0, maxHeight -
   4652 						$( this ).innerHeight() + $( this ).height() ) );
   4653 				} )
   4654 				.css( "overflow", "auto" );
   4655 		} else if ( heightStyle === "auto" ) {
   4656 			maxHeight = 0;
   4657 			this.headers.next()
   4658 				.each( function() {
   4659 					var isVisible = $( this ).is( ":visible" );
   4660 					if ( !isVisible ) {
   4661 						$( this ).show();
   4662 					}
   4663 					maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() );
   4664 					if ( !isVisible ) {
   4665 						$( this ).hide();
   4666 					}
   4667 				} )
   4668 				.height( maxHeight );
   4669 		}
   4670 	},
   4671 
   4672 	_activate: function( index ) {
   4673 		var active = this._findActive( index )[ 0 ];
   4674 
   4675 		// Trying to activate the already active panel
   4676 		if ( active === this.active[ 0 ] ) {
   4677 			return;
   4678 		}
   4679 
   4680 		// Trying to collapse, simulate a click on the currently active header
   4681 		active = active || this.active[ 0 ];
   4682 
   4683 		this._eventHandler( {
   4684 			target: active,
   4685 			currentTarget: active,
   4686 			preventDefault: $.noop
   4687 		} );
   4688 	},
   4689 
   4690 	_findActive: function( selector ) {
   4691 		return typeof selector === "number" ? this.headers.eq( selector ) : $();
   4692 	},
   4693 
   4694 	_setupEvents: function( event ) {
   4695 		var events = {
   4696 			keydown: "_keydown"
   4697 		};
   4698 		if ( event ) {
   4699 			$.each( event.split( " " ), function( index, eventName ) {
   4700 				events[ eventName ] = "_eventHandler";
   4701 			} );
   4702 		}
   4703 
   4704 		this._off( this.headers.add( this.headers.next() ) );
   4705 		this._on( this.headers, events );
   4706 		this._on( this.headers.next(), { keydown: "_panelKeyDown" } );
   4707 		this._hoverable( this.headers );
   4708 		this._focusable( this.headers );
   4709 	},
   4710 
   4711 	_eventHandler: function( event ) {
   4712 		var activeChildren, clickedChildren,
   4713 			options = this.options,
   4714 			active = this.active,
   4715 			clicked = $( event.currentTarget ),
   4716 			clickedIsActive = clicked[ 0 ] === active[ 0 ],
   4717 			collapsing = clickedIsActive && options.collapsible,
   4718 			toShow = collapsing ? $() : clicked.next(),
   4719 			toHide = active.next(),
   4720 			eventData = {
   4721 				oldHeader: active,
   4722 				oldPanel: toHide,
   4723 				newHeader: collapsing ? $() : clicked,
   4724 				newPanel: toShow
   4725 			};
   4726 
   4727 		event.preventDefault();
   4728 
   4729 		if (
   4730 
   4731 				// click on active header, but not collapsible
   4732 				( clickedIsActive && !options.collapsible ) ||
   4733 
   4734 				// allow canceling activation
   4735 				( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
   4736 			return;
   4737 		}
   4738 
   4739 		options.active = collapsing ? false : this.headers.index( clicked );
   4740 
   4741 		// When the call to ._toggle() comes after the class changes
   4742 		// it causes a very odd bug in IE 8 (see #6720)
   4743 		this.active = clickedIsActive ? $() : clicked;
   4744 		this._toggle( eventData );
   4745 
   4746 		// Switch classes
   4747 		// corner classes on the previously active header stay after the animation
   4748 		this._removeClass( active, "ui-accordion-header-active", "ui-state-active" );
   4749 		if ( options.icons ) {
   4750 			activeChildren = active.children( ".ui-accordion-header-icon" );
   4751 			this._removeClass( activeChildren, null, options.icons.activeHeader )
   4752 				._addClass( activeChildren, null, options.icons.header );
   4753 		}
   4754 
   4755 		if ( !clickedIsActive ) {
   4756 			this._removeClass( clicked, "ui-accordion-header-collapsed" )
   4757 				._addClass( clicked, "ui-accordion-header-active", "ui-state-active" );
   4758 			if ( options.icons ) {
   4759 				clickedChildren = clicked.children( ".ui-accordion-header-icon" );
   4760 				this._removeClass( clickedChildren, null, options.icons.header )
   4761 					._addClass( clickedChildren, null, options.icons.activeHeader );
   4762 			}
   4763 
   4764 			this._addClass( clicked.next(), "ui-accordion-content-active" );
   4765 		}
   4766 	},
   4767 
   4768 	_toggle: function( data ) {
   4769 		var toShow = data.newPanel,
   4770 			toHide = this.prevShow.length ? this.prevShow : data.oldPanel;
   4771 
   4772 		// Handle activating a panel during the animation for another activation
   4773 		this.prevShow.add( this.prevHide ).stop( true, true );
   4774 		this.prevShow = toShow;
   4775 		this.prevHide = toHide;
   4776 
   4777 		if ( this.options.animate ) {
   4778 			this._animate( toShow, toHide, data );
   4779 		} else {
   4780 			toHide.hide();
   4781 			toShow.show();
   4782 			this._toggleComplete( data );
   4783 		}
   4784 
   4785 		toHide.attr( {
   4786 			"aria-hidden": "true"
   4787 		} );
   4788 		toHide.prev().attr( {
   4789 			"aria-selected": "false",
   4790 			"aria-expanded": "false"
   4791 		} );
   4792 
   4793 		// if we're switching panels, remove the old header from the tab order
   4794 		// if we're opening from collapsed state, remove the previous header from the tab order
   4795 		// if we're collapsing, then keep the collapsing header in the tab order
   4796 		if ( toShow.length && toHide.length ) {
   4797 			toHide.prev().attr( {
   4798 				"tabIndex": -1,
   4799 				"aria-expanded": "false"
   4800 			} );
   4801 		} else if ( toShow.length ) {
   4802 			this.headers.filter( function() {
   4803 				return parseInt( $( this ).attr( "tabIndex" ), 10 ) === 0;
   4804 			} )
   4805 				.attr( "tabIndex", -1 );
   4806 		}
   4807 
   4808 		toShow
   4809 			.attr( "aria-hidden", "false" )
   4810 			.prev()
   4811 				.attr( {
   4812 					"aria-selected": "true",
   4813 					"aria-expanded": "true",
   4814 					tabIndex: 0
   4815 				} );
   4816 	},
   4817 
   4818 	_animate: function( toShow, toHide, data ) {
   4819 		var total, easing, duration,
   4820 			that = this,
   4821 			adjust = 0,
   4822 			boxSizing = toShow.css( "box-sizing" ),
   4823 			down = toShow.length &&
   4824 				( !toHide.length || ( toShow.index() < toHide.index() ) ),
   4825 			animate = this.options.animate || {},
   4826 			options = down && animate.down || animate,
   4827 			complete = function() {
   4828 				that._toggleComplete( data );
   4829 			};
   4830 
   4831 		if ( typeof options === "number" ) {
   4832 			duration = options;
   4833 		}
   4834 		if ( typeof options === "string" ) {
   4835 			easing = options;
   4836 		}
   4837 
   4838 		// fall back from options to animation in case of partial down settings
   4839 		easing = easing || options.easing || animate.easing;
   4840 		duration = duration || options.duration || animate.duration;
   4841 
   4842 		if ( !toHide.length ) {
   4843 			return toShow.animate( this.showProps, duration, easing, complete );
   4844 		}
   4845 		if ( !toShow.length ) {
   4846 			return toHide.animate( this.hideProps, duration, easing, complete );
   4847 		}
   4848 
   4849 		total = toShow.show().outerHeight();
   4850 		toHide.animate( this.hideProps, {
   4851 			duration: duration,
   4852 			easing: easing,
   4853 			step: function( now, fx ) {
   4854 				fx.now = Math.round( now );
   4855 			}
   4856 		} );
   4857 		toShow
   4858 			.hide()
   4859 			.animate( this.showProps, {
   4860 				duration: duration,
   4861 				easing: easing,
   4862 				complete: complete,
   4863 				step: function( now, fx ) {
   4864 					fx.now = Math.round( now );
   4865 					if ( fx.prop !== "height" ) {
   4866 						if ( boxSizing === "content-box" ) {
   4867 							adjust += fx.now;
   4868 						}
   4869 					} else if ( that.options.heightStyle !== "content" ) {
   4870 						fx.now = Math.round( total - toHide.outerHeight() - adjust );
   4871 						adjust = 0;
   4872 					}
   4873 				}
   4874 			} );
   4875 	},
   4876 
   4877 	_toggleComplete: function( data ) {
   4878 		var toHide = data.oldPanel,
   4879 			prev = toHide.prev();
   4880 
   4881 		this._removeClass( toHide, "ui-accordion-content-active" );
   4882 		this._removeClass( prev, "ui-accordion-header-active" )
   4883 			._addClass( prev, "ui-accordion-header-collapsed" );
   4884 
   4885 		// Work around for rendering bug in IE (#5421)
   4886 		if ( toHide.length ) {
   4887 			toHide.parent()[ 0 ].className = toHide.parent()[ 0 ].className;
   4888 		}
   4889 		this._trigger( "activate", null, data );
   4890 	}
   4891 } );
   4892 
   4893 
   4894 
   4895 var safeActiveElement = $.ui.safeActiveElement = function( document ) {
   4896 	var activeElement;
   4897 
   4898 	// Support: IE 9 only
   4899 	// IE9 throws an "Unspecified error" accessing document.activeElement from an <iframe>
   4900 	try {
   4901 		activeElement = document.activeElement;
   4902 	} catch ( error ) {
   4903 		activeElement = document.body;
   4904 	}
   4905 
   4906 	// Support: IE 9 - 11 only
   4907 	// IE may return null instead of an element
   4908 	// Interestingly, this only seems to occur when NOT in an iframe
   4909 	if ( !activeElement ) {
   4910 		activeElement = document.body;
   4911 	}
   4912 
   4913 	// Support: IE 11 only
   4914 	// IE11 returns a seemingly empty object in some cases when accessing
   4915 	// document.activeElement from an <iframe>
   4916 	if ( !activeElement.nodeName ) {
   4917 		activeElement = document.body;
   4918 	}
   4919 
   4920 	return activeElement;
   4921 };
   4922 
   4923 
   4924 /*!
   4925  * jQuery UI Menu 1.12.1
   4926  * http://jqueryui.com
   4927  *
   4928  * Copyright jQuery Foundation and other contributors
   4929  * Released under the MIT license.
   4930  * http://jquery.org/license
   4931  */
   4932 
   4933 //>>label: Menu
   4934 //>>group: Widgets
   4935 //>>description: Creates nestable menus.
   4936 //>>docs: http://api.jqueryui.com/menu/
   4937 //>>demos: http://jqueryui.com/menu/
   4938 //>>css.structure: ../../themes/base/core.css
   4939 //>>css.structure: ../../themes/base/menu.css
   4940 //>>css.theme: ../../themes/base/theme.css
   4941 
   4942 
   4943 
   4944 var widgetsMenu = $.widget( "ui.menu", {
   4945 	version: "1.12.1",
   4946 	defaultElement: "<ul>",
   4947 	delay: 300,
   4948 	options: {
   4949 		icons: {
   4950 			submenu: "ui-icon-caret-1-e"
   4951 		},
   4952 		items: "> *",
   4953 		menus: "ul",
   4954 		position: {
   4955 			my: "left top",
   4956 			at: "right top"
   4957 		},
   4958 		role: "menu",
   4959 
   4960 		// Callbacks
   4961 		blur: null,
   4962 		focus: null,
   4963 		select: null
   4964 	},
   4965 
   4966 	_create: function() {
   4967 		this.activeMenu = this.element;
   4968 
   4969 		// Flag used to prevent firing of the click handler
   4970 		// as the event bubbles up through nested menus
   4971 		this.mouseHandled = false;
   4972 		this.element
   4973 			.uniqueId()
   4974 			.attr( {
   4975 				role: this.options.role,
   4976 				tabIndex: 0
   4977 			} );
   4978 
   4979 		this._addClass( "ui-menu", "ui-widget ui-widget-content" );
   4980 		this._on( {
   4981 
   4982 			// Prevent focus from sticking to links inside menu after clicking
   4983 			// them (focus should always stay on UL during navigation).
   4984 			"mousedown .ui-menu-item": function( event ) {
   4985 				event.preventDefault();
   4986 			},
   4987 			"click .ui-menu-item": function( event ) {
   4988 				var target = $( event.target );
   4989 				var active = $( $.ui.safeActiveElement( this.document[ 0 ] ) );
   4990 				if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) {
   4991 					this.select( event );
   4992 
   4993 					// Only set the mouseHandled flag if the event will bubble, see #9469.
   4994 					if ( !event.isPropagationStopped() ) {
   4995 						this.mouseHandled = true;
   4996 					}
   4997 
   4998 					// Open submenu on click
   4999 					if ( target.has( ".ui-menu" ).length ) {
   5000 						this.expand( event );
   5001 					} else if ( !this.element.is( ":focus" ) &&
   5002 							active.closest( ".ui-menu" ).length ) {
   5003 
   5004 						// Redirect focus to the menu
   5005 						this.element.trigger( "focus", [ true ] );
   5006 
   5007 						// If the active item is on the top level, let it stay active.
   5008 						// Otherwise, blur the active item since it is no longer visible.
   5009 						if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) {
   5010 							clearTimeout( this.timer );
   5011 						}
   5012 					}
   5013 				}
   5014 			},
   5015 			"mouseenter .ui-menu-item": function( event ) {
   5016 
   5017 				// Ignore mouse events while typeahead is active, see #10458.
   5018 				// Prevents focusing the wrong item when typeahead causes a scroll while the mouse
   5019 				// is over an item in the menu
   5020 				if ( this.previousFilter ) {
   5021 					return;
   5022 				}
   5023 
   5024 				var actualTarget = $( event.target ).closest( ".ui-menu-item" ),
   5025 					target = $( event.currentTarget );
   5026 
   5027 				// Ignore bubbled events on parent items, see #11641
   5028 				if ( actualTarget[ 0 ] !== target[ 0 ] ) {
   5029 					return;
   5030 				}
   5031 
   5032 				// Remove ui-state-active class from siblings of the newly focused menu item
   5033 				// to avoid a jump caused by adjacent elements both having a class with a border
   5034 				this._removeClass( target.siblings().children( ".ui-state-active" ),
   5035 					null, "ui-state-active" );
   5036 				this.focus( event, target );
   5037 			},
   5038 			mouseleave: "collapseAll",
   5039 			"mouseleave .ui-menu": "collapseAll",
   5040 			focus: function( event, keepActiveItem ) {
   5041 
   5042 				// If there's already an active item, keep it active
   5043 				// If not, activate the first item
   5044 				var item = this.active || this.element.find( this.options.items ).eq( 0 );
   5045 
   5046 				if ( !keepActiveItem ) {
   5047 					this.focus( event, item );
   5048 				}
   5049 			},
   5050 			blur: function( event ) {
   5051 				this._delay( function() {
   5052 					var notContained = !$.contains(
   5053 						this.element[ 0 ],
   5054 						$.ui.safeActiveElement( this.document[ 0 ] )
   5055 					);
   5056 					if ( notContained ) {
   5057 						this.collapseAll( event );
   5058 					}
   5059 				} );
   5060 			},
   5061 			keydown: "_keydown"
   5062 		} );
   5063 
   5064 		this.refresh();
   5065 
   5066 		// Clicks outside of a menu collapse any open menus
   5067 		this._on( this.document, {
   5068 			click: function( event ) {
   5069 				if ( this._closeOnDocumentClick( event ) ) {
   5070 					this.collapseAll( event );
   5071 				}
   5072 
   5073 				// Reset the mouseHandled flag
   5074 				this.mouseHandled = false;
   5075 			}
   5076 		} );
   5077 	},
   5078 
   5079 	_destroy: function() {
   5080 		var items = this.element.find( ".ui-menu-item" )
   5081 				.removeAttr( "role aria-disabled" ),
   5082 			submenus = items.children( ".ui-menu-item-wrapper" )
   5083 				.removeUniqueId()
   5084 				.removeAttr( "tabIndex role aria-haspopup" );
   5085 
   5086 		// Destroy (sub)menus
   5087 		this.element
   5088 			.removeAttr( "aria-activedescendant" )
   5089 			.find( ".ui-menu" ).addBack()
   5090 				.removeAttr( "role aria-labelledby aria-expanded aria-hidden aria-disabled " +
   5091 					"tabIndex" )
   5092 				.removeUniqueId()
   5093 				.show();
   5094 
   5095 		submenus.children().each( function() {
   5096 			var elem = $( this );
   5097 			if ( elem.data( "ui-menu-submenu-caret" ) ) {
   5098 				elem.remove();
   5099 			}
   5100 		} );
   5101 	},
   5102 
   5103 	_keydown: function( event ) {
   5104 		var match, prev, character, skip,
   5105 			preventDefault = true;
   5106 
   5107 		switch ( event.keyCode ) {
   5108 		case $.ui.keyCode.PAGE_UP:
   5109 			this.previousPage( event );
   5110 			break;
   5111 		case $.ui.keyCode.PAGE_DOWN:
   5112 			this.nextPage( event );
   5113 			break;
   5114 		case $.ui.keyCode.HOME:
   5115 			this._move( "first", "first", event );
   5116 			break;
   5117 		case $.ui.keyCode.END:
   5118 			this._move( "last", "last", event );
   5119 			break;
   5120 		case $.ui.keyCode.UP:
   5121 			this.previous( event );
   5122 			break;
   5123 		case $.ui.keyCode.DOWN:
   5124 			this.next( event );
   5125 			break;
   5126 		case $.ui.keyCode.LEFT:
   5127 			this.collapse( event );
   5128 			break;
   5129 		case $.ui.keyCode.RIGHT:
   5130 			if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
   5131 				this.expand( event );
   5132 			}
   5133 			break;
   5134 		case $.ui.keyCode.ENTER:
   5135 		case $.ui.keyCode.SPACE:
   5136 			this._activate( event );
   5137 			break;
   5138 		case $.ui.keyCode.ESCAPE:
   5139 			this.collapse( event );
   5140 			break;
   5141 		default:
   5142 			preventDefault = false;
   5143 			prev = this.previousFilter || "";
   5144 			skip = false;
   5145 
   5146 			// Support number pad values
   5147 			character = event.keyCode >= 96 && event.keyCode <= 105 ?
   5148 				( event.keyCode - 96 ).toString() : String.fromCharCode( event.keyCode );
   5149 
   5150 			clearTimeout( this.filterTimer );
   5151 
   5152 			if ( character === prev ) {
   5153 				skip = true;
   5154 			} else {
   5155 				character = prev + character;
   5156 			}
   5157 
   5158 			match = this._filterMenuItems( character );
   5159 			match = skip && match.index( this.active.next() ) !== -1 ?
   5160 				this.active.nextAll( ".ui-menu-item" ) :
   5161 				match;
   5162 
   5163 			// If no matches on the current filter, reset to the last character pressed
   5164 			// to move down the menu to the first item that starts with that character
   5165 			if ( !match.length ) {
   5166 				character = String.fromCharCode( event.keyCode );
   5167 				match = this._filterMenuItems( character );
   5168 			}
   5169 
   5170 			if ( match.length ) {
   5171 				this.focus( event, match );
   5172 				this.previousFilter = character;
   5173 				this.filterTimer = this._delay( function() {
   5174 					delete this.previousFilter;
   5175 				}, 1000 );
   5176 			} else {
   5177 				delete this.previousFilter;
   5178 			}
   5179 		}
   5180 
   5181 		if ( preventDefault ) {
   5182 			event.preventDefault();
   5183 		}
   5184 	},
   5185 
   5186 	_activate: function( event ) {
   5187 		if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
   5188 			if ( this.active.children( "[aria-haspopup='true']" ).length ) {
   5189 				this.expand( event );
   5190 			} else {
   5191 				this.select( event );
   5192 			}
   5193 		}
   5194 	},
   5195 
   5196 	refresh: function() {
   5197 		var menus, items, newSubmenus, newItems, newWrappers,
   5198 			that = this,
   5199 			icon = this.options.icons.submenu,
   5200 			submenus = this.element.find( this.options.menus );
   5201 
   5202 		this._toggleClass( "ui-menu-icons", null, !!this.element.find( ".ui-icon" ).length );
   5203 
   5204 		// Initialize nested menus
   5205 		newSubmenus = submenus.filter( ":not(.ui-menu)" )
   5206 			.hide()
   5207 			.attr( {
   5208 				role: this.options.role,
   5209 				"aria-hidden": "true",
   5210 				"aria-expanded": "false"
   5211 			} )
   5212 			.each( function() {
   5213 				var menu = $( this ),
   5214 					item = menu.prev(),
   5215 					submenuCaret = $( "<span>" ).data( "ui-menu-submenu-caret", true );
   5216 
   5217 				that._addClass( submenuCaret, "ui-menu-icon", "ui-icon " + icon );
   5218 				item
   5219 					.attr( "aria-haspopup", "true" )
   5220 					.prepend( submenuCaret );
   5221 				menu.attr( "aria-labelledby", item.attr( "id" ) );
   5222 			} );
   5223 
   5224 		this._addClass( newSubmenus, "ui-menu", "ui-widget ui-widget-content ui-front" );
   5225 
   5226 		menus = submenus.add( this.element );
   5227 		items = menus.find( this.options.items );
   5228 
   5229 		// Initialize menu-items containing spaces and/or dashes only as dividers
   5230 		items.not( ".ui-menu-item" ).each( function() {
   5231 			var item = $( this );
   5232 			if ( that._isDivider( item ) ) {
   5233 				that._addClass( item, "ui-menu-divider", "ui-widget-content" );
   5234 			}
   5235 		} );
   5236 
   5237 		// Don't refresh list items that are already adapted
   5238 		newItems = items.not( ".ui-menu-item, .ui-menu-divider" );
   5239 		newWrappers = newItems.children()
   5240 			.not( ".ui-menu" )
   5241 				.uniqueId()
   5242 				.attr( {
   5243 					tabIndex: -1,
   5244 					role: this._itemRole()
   5245 				} );
   5246 		this._addClass( newItems, "ui-menu-item" )
   5247 			._addClass( newWrappers, "ui-menu-item-wrapper" );
   5248 
   5249 		// Add aria-disabled attribute to any disabled menu item
   5250 		items.filter( ".ui-state-disabled" ).attr( "aria-disabled", "true" );
   5251 
   5252 		// If the active item has been removed, blur the menu
   5253 		if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
   5254 			this.blur();
   5255 		}
   5256 	},
   5257 
   5258 	_itemRole: function() {
   5259 		return {
   5260 			menu: "menuitem",
   5261 			listbox: "option"
   5262 		}[ this.options.role ];
   5263 	},
   5264 
   5265 	_setOption: function( key, value ) {
   5266 		if ( key === "icons" ) {
   5267 			var icons = this.element.find( ".ui-menu-icon" );
   5268 			this._removeClass( icons, null, this.options.icons.submenu )
   5269 				._addClass( icons, null, value.submenu );
   5270 		}
   5271 		this._super( key, value );
   5272 	},
   5273 
   5274 	_setOptionDisabled: function( value ) {
   5275 		this._super( value );
   5276 
   5277 		this.element.attr( "aria-disabled", String( value ) );
   5278 		this._toggleClass( null, "ui-state-disabled", !!value );
   5279 	},
   5280 
   5281 	focus: function( event, item ) {
   5282 		var nested, focused, activeParent;
   5283 		this.blur( event, event && event.type === "focus" );
   5284 
   5285 		this._scrollIntoView( item );
   5286 
   5287 		this.active = item.first();
   5288 
   5289 		focused = this.active.children( ".ui-menu-item-wrapper" );
   5290 		this._addClass( focused, null, "ui-state-active" );
   5291 
   5292 		// Only update aria-activedescendant if there's a role
   5293 		// otherwise we assume focus is managed elsewhere
   5294 		if ( this.options.role ) {
   5295 			this.element.attr( "aria-activedescendant", focused.attr( "id" ) );
   5296 		}
   5297 
   5298 		// Highlight active parent menu item, if any
   5299 		activeParent = this.active
   5300 			.parent()
   5301 				.closest( ".ui-menu-item" )
   5302 					.children( ".ui-menu-item-wrapper" );
   5303 		this._addClass( activeParent, null, "ui-state-active" );
   5304 
   5305 		if ( event && event.type === "keydown" ) {
   5306 			this._close();
   5307 		} else {
   5308 			this.timer = this._delay( function() {
   5309 				this._close();
   5310 			}, this.delay );
   5311 		}
   5312 
   5313 		nested = item.children( ".ui-menu" );
   5314 		if ( nested.length && event && ( /^mouse/.test( event.type ) ) ) {
   5315 			this._startOpening( nested );
   5316 		}
   5317 		this.activeMenu = item.parent();
   5318 
   5319 		this._trigger( "focus", event, { item: item } );
   5320 	},
   5321 
   5322 	_scrollIntoView: function( item ) {
   5323 		var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight;
   5324 		if ( this._hasScroll() ) {
   5325 			borderTop = parseFloat( $.css( this.activeMenu[ 0 ], "borderTopWidth" ) ) || 0;
   5326 			paddingTop = parseFloat( $.css( this.activeMenu[ 0 ], "paddingTop" ) ) || 0;
   5327 			offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop;
   5328 			scroll = this.activeMenu.scrollTop();
   5329 			elementHeight = this.activeMenu.height();
   5330 			itemHeight = item.outerHeight();
   5331 
   5332 			if ( offset < 0 ) {
   5333 				this.activeMenu.scrollTop( scroll + offset );
   5334 			} else if ( offset + itemHeight > elementHeight ) {
   5335 				this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight );
   5336 			}
   5337 		}
   5338 	},
   5339 
   5340 	blur: function( event, fromFocus ) {
   5341 		if ( !fromFocus ) {
   5342 			clearTimeout( this.timer );
   5343 		}
   5344 
   5345 		if ( !this.active ) {
   5346 			return;
   5347 		}
   5348 
   5349 		this._removeClass( this.active.children( ".ui-menu-item-wrapper" ),
   5350 			null, "ui-state-active" );
   5351 
   5352 		this._trigger( "blur", event, { item: this.active } );
   5353 		this.active = null;
   5354 	},
   5355 
   5356 	_startOpening: function( submenu ) {
   5357 		clearTimeout( this.timer );
   5358 
   5359 		// Don't open if already open fixes a Firefox bug that caused a .5 pixel
   5360 		// shift in the submenu position when mousing over the caret icon
   5361 		if ( submenu.attr( "aria-hidden" ) !== "true" ) {
   5362 			return;
   5363 		}
   5364 
   5365 		this.timer = this._delay( function() {
   5366 			this._close();
   5367 			this._open( submenu );
   5368 		}, this.delay );
   5369 	},
   5370 
   5371 	_open: function( submenu ) {
   5372 		var position = $.extend( {
   5373 			of: this.active
   5374 		}, this.options.position );
   5375 
   5376 		clearTimeout( this.timer );
   5377 		this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) )
   5378 			.hide()
   5379 			.attr( "aria-hidden", "true" );
   5380 
   5381 		submenu
   5382 			.show()
   5383 			.removeAttr( "aria-hidden" )
   5384 			.attr( "aria-expanded", "true" )
   5385 			.position( position );
   5386 	},
   5387 
   5388 	collapseAll: function( event, all ) {
   5389 		clearTimeout( this.timer );
   5390 		this.timer = this._delay( function() {
   5391 
   5392 			// If we were passed an event, look for the submenu that contains the event
   5393 			var currentMenu = all ? this.element :
   5394 				$( event && event.target ).closest( this.element.find( ".ui-menu" ) );
   5395 
   5396 			// If we found no valid submenu ancestor, use the main menu to close all
   5397 			// sub menus anyway
   5398 			if ( !currentMenu.length ) {
   5399 				currentMenu = this.element;
   5400 			}
   5401 
   5402 			this._close( currentMenu );
   5403 
   5404 			this.blur( event );
   5405 
   5406 			// Work around active item staying active after menu is blurred
   5407 			this._removeClass( currentMenu.find( ".ui-state-active" ), null, "ui-state-active" );
   5408 
   5409 			this.activeMenu = currentMenu;
   5410 		}, this.delay );
   5411 	},
   5412 
   5413 	// With no arguments, closes the currently active menu - if nothing is active
   5414 	// it closes all menus.  If passed an argument, it will search for menus BELOW
   5415 	_close: function( startMenu ) {
   5416 		if ( !startMenu ) {
   5417 			startMenu = this.active ? this.active.parent() : this.element;
   5418 		}
   5419 
   5420 		startMenu.find( ".ui-menu" )
   5421 			.hide()
   5422 			.attr( "aria-hidden", "true" )
   5423 			.attr( "aria-expanded", "false" );
   5424 	},
   5425 
   5426 	_closeOnDocumentClick: function( event ) {
   5427 		return !$( event.target ).closest( ".ui-menu" ).length;
   5428 	},
   5429 
   5430 	_isDivider: function( item ) {
   5431 
   5432 		// Match hyphen, em dash, en dash
   5433 		return !/[^\-\u2014\u2013\s]/.test( item.text() );
   5434 	},
   5435 
   5436 	collapse: function( event ) {
   5437 		var newItem = this.active &&
   5438 			this.active.parent().closest( ".ui-menu-item", this.element );
   5439 		if ( newItem && newItem.length ) {
   5440 			this._close();
   5441 			this.focus( event, newItem );
   5442 		}
   5443 	},
   5444 
   5445 	expand: function( event ) {
   5446 		var newItem = this.active &&
   5447 			this.active
   5448 				.children( ".ui-menu " )
   5449 					.find( this.options.items )
   5450 						.first();
   5451 
   5452 		if ( newItem && newItem.length ) {
   5453 			this._open( newItem.parent() );
   5454 
   5455 			// Delay so Firefox will not hide activedescendant change in expanding submenu from AT
   5456 			this._delay( function() {
   5457 				this.focus( event, newItem );
   5458 			} );
   5459 		}
   5460 	},
   5461 
   5462 	next: function( event ) {
   5463 		this._move( "next", "first", event );
   5464 	},
   5465 
   5466 	previous: function( event ) {
   5467 		this._move( "prev", "last", event );
   5468 	},
   5469 
   5470 	isFirstItem: function() {
   5471 		return this.active && !this.active.prevAll( ".ui-menu-item" ).length;
   5472 	},
   5473 
   5474 	isLastItem: function() {
   5475 		return this.active && !this.active.nextAll( ".ui-menu-item" ).length;
   5476 	},
   5477 
   5478 	_move: function( direction, filter, event ) {
   5479 		var next;
   5480 		if ( this.active ) {
   5481 			if ( direction === "first" || direction === "last" ) {
   5482 				next = this.active
   5483 					[ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" )
   5484 					.eq( -1 );
   5485 			} else {
   5486 				next = this.active
   5487 					[ direction + "All" ]( ".ui-menu-item" )
   5488 					.eq( 0 );
   5489 			}
   5490 		}
   5491 		if ( !next || !next.length || !this.active ) {
   5492 			next = this.activeMenu.find( this.options.items )[ filter ]();
   5493 		}
   5494 
   5495 		this.focus( event, next );
   5496 	},
   5497 
   5498 	nextPage: function( event ) {
   5499 		var item, base, height;
   5500 
   5501 		if ( !this.active ) {
   5502 			this.next( event );
   5503 			return;
   5504 		}
   5505 		if ( this.isLastItem() ) {
   5506 			return;
   5507 		}
   5508 		if ( this._hasScroll() ) {
   5509 			base = this.active.offset().top;
   5510 			height = this.element.height();
   5511 			this.active.nextAll( ".ui-menu-item" ).each( function() {
   5512 				item = $( this );
   5513 				return item.offset().top - base - height < 0;
   5514 			} );
   5515 
   5516 			this.focus( event, item );
   5517 		} else {
   5518 			this.focus( event, this.activeMenu.find( this.options.items )
   5519 				[ !this.active ? "first" : "last" ]() );
   5520 		}
   5521 	},
   5522 
   5523 	previousPage: function( event ) {
   5524 		var item, base, height;
   5525 		if ( !this.active ) {
   5526 			this.next( event );
   5527 			return;
   5528 		}
   5529 		if ( this.isFirstItem() ) {
   5530 			return;
   5531 		}
   5532 		if ( this._hasScroll() ) {
   5533 			base = this.active.offset().top;
   5534 			height = this.element.height();
   5535 			this.active.prevAll( ".ui-menu-item" ).each( function() {
   5536 				item = $( this );
   5537 				return item.offset().top - base + height > 0;
   5538 			} );
   5539 
   5540 			this.focus( event, item );
   5541 		} else {
   5542 			this.focus( event, this.activeMenu.find( this.options.items ).first() );
   5543 		}
   5544 	},
   5545 
   5546 	_hasScroll: function() {
   5547 		return this.element.outerHeight() < this.element.prop( "scrollHeight" );
   5548 	},
   5549 
   5550 	select: function( event ) {
   5551 
   5552 		// TODO: It should never be possible to not have an active item at this
   5553 		// point, but the tests don't trigger mouseenter before click.
   5554 		this.active = this.active || $( event.target ).closest( ".ui-menu-item" );
   5555 		var ui = { item: this.active };
   5556 		if ( !this.active.has( ".ui-menu" ).length ) {
   5557 			this.collapseAll( event, true );
   5558 		}
   5559 		this._trigger( "select", event, ui );
   5560 	},
   5561 
   5562 	_filterMenuItems: function( character ) {
   5563 		var escapedCharacter = character.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ),
   5564 			regex = new RegExp( "^" + escapedCharacter, "i" );
   5565 
   5566 		return this.activeMenu
   5567 			.find( this.options.items )
   5568 
   5569 				// Only match on items, not dividers or other content (#10571)
   5570 				.filter( ".ui-menu-item" )
   5571 					.filter( function() {
   5572 						return regex.test(
   5573 							$.trim( $( this ).children( ".ui-menu-item-wrapper" ).text() ) );
   5574 					} );
   5575 	}
   5576 } );
   5577 
   5578 
   5579 /*!
   5580  * jQuery UI Autocomplete 1.12.1
   5581  * http://jqueryui.com
   5582  *
   5583  * Copyright jQuery Foundation and other contributors
   5584  * Released under the MIT license.
   5585  * http://jquery.org/license
   5586  */
   5587 
   5588 //>>label: Autocomplete
   5589 //>>group: Widgets
   5590 //>>description: Lists suggested words as the user is typing.
   5591 //>>docs: http://api.jqueryui.com/autocomplete/
   5592 //>>demos: http://jqueryui.com/autocomplete/
   5593 //>>css.structure: ../../themes/base/core.css
   5594 //>>css.structure: ../../themes/base/autocomplete.css
   5595 //>>css.theme: ../../themes/base/theme.css
   5596 
   5597 
   5598 
   5599 $.widget( "ui.autocomplete", {
   5600 	version: "1.12.1",
   5601 	defaultElement: "<input>",
   5602 	options: {
   5603 		appendTo: null,
   5604 		autoFocus: false,
   5605 		delay: 300,
   5606 		minLength: 1,
   5607 		position: {
   5608 			my: "left top",
   5609 			at: "left bottom",
   5610 			collision: "none"
   5611 		},
   5612 		source: null,
   5613 
   5614 		// Callbacks
   5615 		change: null,
   5616 		close: null,
   5617 		focus: null,
   5618 		open: null,
   5619 		response: null,
   5620 		search: null,
   5621 		select: null
   5622 	},
   5623 
   5624 	requestIndex: 0,
   5625 	pending: 0,
   5626 
   5627 	_create: function() {
   5628 
   5629 		// Some browsers only repeat keydown events, not keypress events,
   5630 		// so we use the suppressKeyPress flag to determine if we've already
   5631 		// handled the keydown event. #7269
   5632 		// Unfortunately the code for & in keypress is the same as the up arrow,
   5633 		// so we use the suppressKeyPressRepeat flag to avoid handling keypress
   5634 		// events when we know the keydown event was used to modify the
   5635 		// search term. #7799
   5636 		var suppressKeyPress, suppressKeyPressRepeat, suppressInput,
   5637 			nodeName = this.element[ 0 ].nodeName.toLowerCase(),
   5638 			isTextarea = nodeName === "textarea",
   5639 			isInput = nodeName === "input";
   5640 
   5641 		// Textareas are always multi-line
   5642 		// Inputs are always single-line, even if inside a contentEditable element
   5643 		// IE also treats inputs as contentEditable
   5644 		// All other element types are determined by whether or not they're contentEditable
   5645 		this.isMultiLine = isTextarea || !isInput && this._isContentEditable( this.element );
   5646 
   5647 		this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ];
   5648 		this.isNewMenu = true;
   5649 
   5650 		this._addClass( "ui-autocomplete-input" );
   5651 		this.element.attr( "autocomplete", "off" );
   5652 
   5653 		this._on( this.element, {
   5654 			keydown: function( event ) {
   5655 				if ( this.element.prop( "readOnly" ) ) {
   5656 					suppressKeyPress = true;
   5657 					suppressInput = true;
   5658 					suppressKeyPressRepeat = true;
   5659 					return;
   5660 				}
   5661 
   5662 				suppressKeyPress = false;
   5663 				suppressInput = false;
   5664 				suppressKeyPressRepeat = false;
   5665 				var keyCode = $.ui.keyCode;
   5666 				switch ( event.keyCode ) {
   5667 				case keyCode.PAGE_UP:
   5668 					suppressKeyPress = true;
   5669 					this._move( "previousPage", event );
   5670 					break;
   5671 				case keyCode.PAGE_DOWN:
   5672 					suppressKeyPress = true;
   5673 					this._move( "nextPage", event );
   5674 					break;
   5675 				case keyCode.UP:
   5676 					suppressKeyPress = true;
   5677 					this._keyEvent( "previous", event );
   5678 					break;
   5679 				case keyCode.DOWN:
   5680 					suppressKeyPress = true;
   5681 					this._keyEvent( "next", event );
   5682 					break;
   5683 				case keyCode.ENTER:
   5684 
   5685 					// when menu is open and has focus
   5686 					if ( this.menu.active ) {
   5687 
   5688 						// #6055 - Opera still allows the keypress to occur
   5689 						// which causes forms to submit
   5690 						suppressKeyPress = true;
   5691 						event.preventDefault();
   5692 						this.menu.select( event );
   5693 					}
   5694 					break;
   5695 				case keyCode.TAB:
   5696 					if ( this.menu.active ) {
   5697 						this.menu.select( event );
   5698 					}
   5699 					break;
   5700 				case keyCode.ESCAPE:
   5701 					if ( this.menu.element.is( ":visible" ) ) {
   5702 						if ( !this.isMultiLine ) {
   5703 							this._value( this.term );
   5704 						}
   5705 						this.close( event );
   5706 
   5707 						// Different browsers have different default behavior for escape
   5708 						// Single press can mean undo or clear
   5709 						// Double press in IE means clear the whole form
   5710 						event.preventDefault();
   5711 					}
   5712 					break;
   5713 				default:
   5714 					suppressKeyPressRepeat = true;
   5715 
   5716 					// search timeout should be triggered before the input value is changed
   5717 					this._searchTimeout( event );
   5718 					break;
   5719 				}
   5720 			},
   5721 			keypress: function( event ) {
   5722 				if ( suppressKeyPress ) {
   5723 					suppressKeyPress = false;
   5724 					if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
   5725 						event.preventDefault();
   5726 					}
   5727 					return;
   5728 				}
   5729 				if ( suppressKeyPressRepeat ) {
   5730 					return;
   5731 				}
   5732 
   5733 				// Replicate some key handlers to allow them to repeat in Firefox and Opera
   5734 				var keyCode = $.ui.keyCode;
   5735 				switch ( event.keyCode ) {
   5736 				case keyCode.PAGE_UP:
   5737 					this._move( "previousPage", event );
   5738 					break;
   5739 				case keyCode.PAGE_DOWN:
   5740 					this._move( "nextPage", event );
   5741 					break;
   5742 				case keyCode.UP:
   5743 					this._keyEvent( "previous", event );
   5744 					break;
   5745 				case keyCode.DOWN:
   5746 					this._keyEvent( "next", event );
   5747 					break;
   5748 				}
   5749 			},
   5750 			input: function( event ) {
   5751 				if ( suppressInput ) {
   5752 					suppressInput = false;
   5753 					event.preventDefault();
   5754 					return;
   5755 				}
   5756 				this._searchTimeout( event );
   5757 			},
   5758 			focus: function() {
   5759 				this.selectedItem = null;
   5760 				this.previous = this._value();
   5761 			},
   5762 			blur: function( event ) {
   5763 				if ( this.cancelBlur ) {
   5764 					delete this.cancelBlur;
   5765 					return;
   5766 				}
   5767 
   5768 				clearTimeout( this.searching );
   5769 				this.close( event );
   5770 				this._change( event );
   5771 			}
   5772 		} );
   5773 
   5774 		this._initSource();
   5775 		this.menu = $( "<ul>" )
   5776 			.appendTo( this._appendTo() )
   5777 			.menu( {
   5778 
   5779 				// disable ARIA support, the live region takes care of that
   5780 				role: null
   5781 			} )
   5782 			.hide()
   5783 			.menu( "instance" );
   5784 
   5785 		this._addClass( this.menu.element, "ui-autocomplete", "ui-front" );
   5786 		this._on( this.menu.element, {
   5787 			mousedown: function( event ) {
   5788 
   5789 				// prevent moving focus out of the text field
   5790 				event.preventDefault();
   5791 
   5792 				// IE doesn't prevent moving focus even with event.preventDefault()
   5793 				// so we set a flag to know when we should ignore the blur event
   5794 				this.cancelBlur = true;
   5795 				this._delay( function() {
   5796 					delete this.cancelBlur;
   5797 
   5798 					// Support: IE 8 only
   5799 					// Right clicking a menu item or selecting text from the menu items will
   5800 					// result in focus moving out of the input. However, we've already received
   5801 					// and ignored the blur event because of the cancelBlur flag set above. So
   5802 					// we restore focus to ensure that the menu closes properly based on the user's
   5803 					// next actions.
   5804 					if ( this.element[ 0 ] !== $.ui.safeActiveElement( this.document[ 0 ] ) ) {
   5805 						this.element.trigger( "focus" );
   5806 					}
   5807 				} );
   5808 			},
   5809 			menufocus: function( event, ui ) {
   5810 				var label, item;
   5811 
   5812 				// support: Firefox
   5813 				// Prevent accidental activation of menu items in Firefox (#7024 #9118)
   5814 				if ( this.isNewMenu ) {
   5815 					this.isNewMenu = false;
   5816 					if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) {
   5817 						this.menu.blur();
   5818 
   5819 						this.document.one( "mousemove", function() {
   5820 							$( event.target ).trigger( event.originalEvent );
   5821 						} );
   5822 
   5823 						return;
   5824 					}
   5825 				}
   5826 
   5827 				item = ui.item.data( "ui-autocomplete-item" );
   5828 				if ( false !== this._trigger( "focus", event, { item: item } ) ) {
   5829 
   5830 					// use value to match what will end up in the input, if it was a key event
   5831 					if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) {
   5832 						this._value( item.value );
   5833 					}
   5834 				}
   5835 
   5836 				// Announce the value in the liveRegion
   5837 				label = ui.item.attr( "aria-label" ) || item.value;
   5838 				if ( label && $.trim( label ).length ) {
   5839 					this.liveRegion.children().hide();
   5840 					$( "<div>" ).text( label ).appendTo( this.liveRegion );
   5841 				}
   5842 			},
   5843 			menuselect: function( event, ui ) {
   5844 				var item = ui.item.data( "ui-autocomplete-item" ),
   5845 					previous = this.previous;
   5846 
   5847 				// Only trigger when focus was lost (click on menu)
   5848 				if ( this.element[ 0 ] !== $.ui.safeActiveElement( this.document[ 0 ] ) ) {
   5849 					this.element.trigger( "focus" );
   5850 					this.previous = previous;
   5851 
   5852 					// #6109 - IE triggers two focus events and the second
   5853 					// is asynchronous, so we need to reset the previous
   5854 					// term synchronously and asynchronously :-(
   5855 					this._delay( function() {
   5856 						this.previous = previous;
   5857 						this.selectedItem = item;
   5858 					} );
   5859 				}
   5860 
   5861 				if ( false !== this._trigger( "select", event, { item: item } ) ) {
   5862 					this._value( item.value );
   5863 				}
   5864 
   5865 				// reset the term after the select event
   5866 				// this allows custom select handling to work properly
   5867 				this.term = this._value();
   5868 
   5869 				this.close( event );
   5870 				this.selectedItem = item;
   5871 			}
   5872 		} );
   5873 
   5874 		this.liveRegion = $( "<div>", {
   5875 			role: "status",
   5876 			"aria-live": "assertive",
   5877 			"aria-relevant": "additions"
   5878 		} )
   5879 			.appendTo( this.document[ 0 ].body );
   5880 
   5881 		this._addClass( this.liveRegion, null, "ui-helper-hidden-accessible" );
   5882 
   5883 		// Turning off autocomplete prevents the browser from remembering the
   5884 		// value when navigating through history, so we re-enable autocomplete
   5885 		// if the page is unloaded before the widget is destroyed. #7790
   5886 		this._on( this.window, {
   5887 			beforeunload: function() {
   5888 				this.element.removeAttr( "autocomplete" );
   5889 			}
   5890 		} );
   5891 	},
   5892 
   5893 	_destroy: function() {
   5894 		clearTimeout( this.searching );
   5895 		this.element.removeAttr( "autocomplete" );
   5896 		this.menu.element.remove();
   5897 		this.liveRegion.remove();
   5898 	},
   5899 
   5900 	_setOption: function( key, value ) {
   5901 		this._super( key, value );
   5902 		if ( key === "source" ) {
   5903 			this._initSource();
   5904 		}
   5905 		if ( key === "appendTo" ) {
   5906 			this.menu.element.appendTo( this._appendTo() );
   5907 		}
   5908 		if ( key === "disabled" && value && this.xhr ) {
   5909 			this.xhr.abort();
   5910 		}
   5911 	},
   5912 
   5913 	_isEventTargetInWidget: function( event ) {
   5914 		var menuElement = this.menu.element[ 0 ];
   5915 
   5916 		return event.target === this.element[ 0 ] ||
   5917 			event.target === menuElement ||
   5918 			$.contains( menuElement, event.target );
   5919 	},
   5920 
   5921 	_closeOnClickOutside: function( event ) {
   5922 		if ( !this._isEventTargetInWidget( event ) ) {
   5923 			this.close();
   5924 		}
   5925 	},
   5926 
   5927 	_appendTo: function() {
   5928 		var element = this.options.appendTo;
   5929 
   5930 		if ( element ) {
   5931 			element = element.jquery || element.nodeType ?
   5932 				$( element ) :
   5933 				this.document.find( element ).eq( 0 );
   5934 		}
   5935 
   5936 		if ( !element || !element[ 0 ] ) {
   5937 			element = this.element.closest( ".ui-front, dialog" );
   5938 		}
   5939 
   5940 		if ( !element.length ) {
   5941 			element = this.document[ 0 ].body;
   5942 		}
   5943 
   5944 		return element;
   5945 	},
   5946 
   5947 	_initSource: function() {
   5948 		var array, url,
   5949 			that = this;
   5950 		if ( $.isArray( this.options.source ) ) {
   5951 			array = this.options.source;
   5952 			this.source = function( request, response ) {
   5953 				response( $.ui.autocomplete.filter( array, request.term ) );
   5954 			};
   5955 		} else if ( typeof this.options.source === "string" ) {
   5956 			url = this.options.source;
   5957 			this.source = function( request, response ) {
   5958 				if ( that.xhr ) {
   5959 					that.xhr.abort();
   5960 				}
   5961 				that.xhr = $.ajax( {
   5962 					url: url,
   5963 					data: request,
   5964 					dataType: "json",
   5965 					success: function( data ) {
   5966 						response( data );
   5967 					},
   5968 					error: function() {
   5969 						response( [] );
   5970 					}
   5971 				} );
   5972 			};
   5973 		} else {
   5974 			this.source = this.options.source;
   5975 		}
   5976 	},
   5977 
   5978 	_searchTimeout: function( event ) {
   5979 		clearTimeout( this.searching );
   5980 		this.searching = this._delay( function() {
   5981 
   5982 			// Search if the value has changed, or if the user retypes the same value (see #7434)
   5983 			var equalValues = this.term === this._value(),
   5984 				menuVisible = this.menu.element.is( ":visible" ),
   5985 				modifierKey = event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;
   5986 
   5987 			if ( !equalValues || ( equalValues && !menuVisible && !modifierKey ) ) {
   5988 				this.selectedItem = null;
   5989 				this.search( null, event );
   5990 			}
   5991 		}, this.options.delay );
   5992 	},
   5993 
   5994 	search: function( value, event ) {
   5995 		value = value != null ? value : this._value();
   5996 
   5997 		// Always save the actual value, not the one passed as an argument
   5998 		this.term = this._value();
   5999 
   6000 		if ( value.length < this.options.minLength ) {
   6001 			return this.close( event );
   6002 		}
   6003 
   6004 		if ( this._trigger( "search", event ) === false ) {
   6005 			return;
   6006 		}
   6007 
   6008 		return this._search( value );
   6009 	},
   6010 
   6011 	_search: function( value ) {
   6012 		this.pending++;
   6013 		this._addClass( "ui-autocomplete-loading" );
   6014 		this.cancelSearch = false;
   6015 
   6016 		this.source( { term: value }, this._response() );
   6017 	},
   6018 
   6019 	_response: function() {
   6020 		var index = ++this.requestIndex;
   6021 
   6022 		return $.proxy( function( content ) {
   6023 			if ( index === this.requestIndex ) {
   6024 				this.__response( content );
   6025 			}
   6026 
   6027 			this.pending--;
   6028 			if ( !this.pending ) {
   6029 				this._removeClass( "ui-autocomplete-loading" );
   6030 			}
   6031 		}, this );
   6032 	},
   6033 
   6034 	__response: function( content ) {
   6035 		if ( content ) {
   6036 			content = this._normalize( content );
   6037 		}
   6038 		this._trigger( "response", null, { content: content } );
   6039 		if ( !this.options.disabled && content && content.length && !this.cancelSearch ) {
   6040 			this._suggest( content );
   6041 			this._trigger( "open" );
   6042 		} else {
   6043 
   6044 			// use ._close() instead of .close() so we don't cancel future searches
   6045 			this._close();
   6046 		}
   6047 	},
   6048 
   6049 	close: function( event ) {
   6050 		this.cancelSearch = true;
   6051 		this._close( event );
   6052 	},
   6053 
   6054 	_close: function( event ) {
   6055 
   6056 		// Remove the handler that closes the menu on outside clicks
   6057 		this._off( this.document, "mousedown" );
   6058 
   6059 		if ( this.menu.element.is( ":visible" ) ) {
   6060 			this.menu.element.hide();
   6061 			this.menu.blur();
   6062 			this.isNewMenu = true;
   6063 			this._trigger( "close", event );
   6064 		}
   6065 	},
   6066 
   6067 	_change: function( event ) {
   6068 		if ( this.previous !== this._value() ) {
   6069 			this._trigger( "change", event, { item: this.selectedItem } );
   6070 		}
   6071 	},
   6072 
   6073 	_normalize: function( items ) {
   6074 
   6075 		// assume all items have the right format when the first item is complete
   6076 		if ( items.length && items[ 0 ].label && items[ 0 ].value ) {
   6077 			return items;
   6078 		}
   6079 		return $.map( items, function( item ) {
   6080 			if ( typeof item === "string" ) {
   6081 				return {
   6082 					label: item,
   6083 					value: item
   6084 				};
   6085 			}
   6086 			return $.extend( {}, item, {
   6087 				label: item.label || item.value,
   6088 				value: item.value || item.label
   6089 			} );
   6090 		} );
   6091 	},
   6092 
   6093 	_suggest: function( items ) {
   6094 		var ul = this.menu.element.empty();
   6095 		this._renderMenu( ul, items );
   6096 		this.isNewMenu = true;
   6097 		this.menu.refresh();
   6098 
   6099 		// Size and position menu
   6100 		ul.show();
   6101 		this._resizeMenu();
   6102 		ul.position( $.extend( {
   6103 			of: this.element
   6104 		}, this.options.position ) );
   6105 
   6106 		if ( this.options.autoFocus ) {
   6107 			this.menu.next();
   6108 		}
   6109 
   6110 		// Listen for interactions outside of the widget (#6642)
   6111 		this._on( this.document, {
   6112 			mousedown: "_closeOnClickOutside"
   6113 		} );
   6114 	},
   6115 
   6116 	_resizeMenu: function() {
   6117 		var ul = this.menu.element;
   6118 		ul.outerWidth( Math.max(
   6119 
   6120 			// Firefox wraps long text (possibly a rounding bug)
   6121 			// so we add 1px to avoid the wrapping (#7513)
   6122 			ul.width( "" ).outerWidth() + 1,
   6123 			this.element.outerWidth()
   6124 		) );
   6125 	},
   6126 
   6127 	_renderMenu: function( ul, items ) {
   6128 		var that = this;
   6129 		$.each( items, function( index, item ) {
   6130 			that._renderItemData( ul, item );
   6131 		} );
   6132 	},
   6133 
   6134 	_renderItemData: function( ul, item ) {
   6135 		return this._renderItem( ul, item ).data( "ui-autocomplete-item", item );
   6136 	},
   6137 
   6138 	_renderItem: function( ul, item ) {
   6139 		return $( "<li>" )
   6140 			.append( $( "<div>" ).text( item.label ) )
   6141 			.appendTo( ul );
   6142 	},
   6143 
   6144 	_move: function( direction, event ) {
   6145 		if ( !this.menu.element.is( ":visible" ) ) {
   6146 			this.search( null, event );
   6147 			return;
   6148 		}
   6149 		if ( this.menu.isFirstItem() && /^previous/.test( direction ) ||
   6150 				this.menu.isLastItem() && /^next/.test( direction ) ) {
   6151 
   6152 			if ( !this.isMultiLine ) {
   6153 				this._value( this.term );
   6154 			}
   6155 
   6156 			this.menu.blur();
   6157 			return;
   6158 		}
   6159 		this.menu[ direction ]( event );
   6160 	},
   6161 
   6162 	widget: function() {
   6163 		return this.menu.element;
   6164 	},
   6165 
   6166 	_value: function() {
   6167 		return this.valueMethod.apply( this.element, arguments );
   6168 	},
   6169 
   6170 	_keyEvent: function( keyEvent, event ) {
   6171 		if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
   6172 			this._move( keyEvent, event );
   6173 
   6174 			// Prevents moving cursor to beginning/end of the text field in some browsers
   6175 			event.preventDefault();
   6176 		}
   6177 	},
   6178 
   6179 	// Support: Chrome <=50
   6180 	// We should be able to just use this.element.prop( "isContentEditable" )
   6181 	// but hidden elements always report false in Chrome.
   6182 	// https://code.google.com/p/chromium/issues/detail?id=313082
   6183 	_isContentEditable: function( element ) {
   6184 		if ( !element.length ) {
   6185 			return false;
   6186 		}
   6187 
   6188 		var editable = element.prop( "contentEditable" );
   6189 
   6190 		if ( editable === "inherit" ) {
   6191 		  return this._isContentEditable( element.parent() );
   6192 		}
   6193 
   6194 		return editable === "true";
   6195 	}
   6196 } );
   6197 
   6198 $.extend( $.ui.autocomplete, {
   6199 	escapeRegex: function( value ) {
   6200 		return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" );
   6201 	},
   6202 	filter: function( array, term ) {
   6203 		var matcher = new RegExp( $.ui.autocomplete.escapeRegex( term ), "i" );
   6204 		return $.grep( array, function( value ) {
   6205 			return matcher.test( value.label || value.value || value );
   6206 		} );
   6207 	}
   6208 } );
   6209 
   6210 // Live region extension, adding a `messages` option
   6211 // NOTE: This is an experimental API. We are still investigating
   6212 // a full solution for string manipulation and internationalization.
   6213 $.widget( "ui.autocomplete", $.ui.autocomplete, {
   6214 	options: {
   6215 		messages: {
   6216 			noResults: "No search results.",
   6217 			results: function( amount ) {
   6218 				return amount + ( amount > 1 ? " results are" : " result is" ) +
   6219 					" available, use up and down arrow keys to navigate.";
   6220 			}
   6221 		}
   6222 	},
   6223 
   6224 	__response: function( content ) {
   6225 		var message;
   6226 		this._superApply( arguments );
   6227 		if ( this.options.disabled || this.cancelSearch ) {
   6228 			return;
   6229 		}
   6230 		if ( content && content.length ) {
   6231 			message = this.options.messages.results( content.length );
   6232 		} else {
   6233 			message = this.options.messages.noResults;
   6234 		}
   6235 		this.liveRegion.children().hide();
   6236 		$( "<div>" ).text( message ).appendTo( this.liveRegion );
   6237 	}
   6238 } );
   6239 
   6240 var widgetsAutocomplete = $.ui.autocomplete;
   6241 
   6242 
   6243 /*!
   6244  * jQuery UI Controlgroup 1.12.1
   6245  * http://jqueryui.com
   6246  *
   6247  * Copyright jQuery Foundation and other contributors
   6248  * Released under the MIT license.
   6249  * http://jquery.org/license
   6250  */
   6251 
   6252 //>>label: Controlgroup
   6253 //>>group: Widgets
   6254 //>>description: Visually groups form control widgets
   6255 //>>docs: http://api.jqueryui.com/controlgroup/
   6256 //>>demos: http://jqueryui.com/controlgroup/
   6257 //>>css.structure: ../../themes/base/core.css
   6258 //>>css.structure: ../../themes/base/controlgroup.css
   6259 //>>css.theme: ../../themes/base/theme.css
   6260 
   6261 
   6262 var controlgroupCornerRegex = /ui-corner-([a-z]){2,6}/g;
   6263 
   6264 var widgetsControlgroup = $.widget( "ui.controlgroup", {
   6265 	version: "1.12.1",
   6266 	defaultElement: "<div>",
   6267 	options: {
   6268 		direction: "horizontal",
   6269 		disabled: null,
   6270 		onlyVisible: true,
   6271 		items: {
   6272 			"button": "input[type=button], input[type=submit], input[type=reset], button, a",
   6273 			"controlgroupLabel": ".ui-controlgroup-label",
   6274 			"checkboxradio": "input[type='checkbox'], input[type='radio']",
   6275 			"selectmenu": "select",
   6276 			"spinner": ".ui-spinner-input"
   6277 		}
   6278 	},
   6279 
   6280 	_create: function() {
   6281 		this._enhance();
   6282 	},
   6283 
   6284 	// To support the enhanced option in jQuery Mobile, we isolate DOM manipulation
   6285 	_enhance: function() {
   6286 		this.element.attr( "role", "toolbar" );
   6287 		this.refresh();
   6288 	},
   6289 
   6290 	_destroy: function() {
   6291 		this._callChildMethod( "destroy" );
   6292 		this.childWidgets.removeData( "ui-controlgroup-data" );
   6293 		this.element.removeAttr( "role" );
   6294 		if ( this.options.items.controlgroupLabel ) {
   6295 			this.element
   6296 				.find( this.options.items.controlgroupLabel )
   6297 				.find( ".ui-controlgroup-label-contents" )
   6298 				.contents().unwrap();
   6299 		}
   6300 	},
   6301 
   6302 	_initWidgets: function() {
   6303 		var that = this,
   6304 			childWidgets = [];
   6305 
   6306 		// First we iterate over each of the items options
   6307 		$.each( this.options.items, function( widget, selector ) {
   6308 			var labels;
   6309 			var options = {};
   6310 
   6311 			// Make sure the widget has a selector set
   6312 			if ( !selector ) {
   6313 				return;
   6314 			}
   6315 
   6316 			if ( widget === "controlgroupLabel" ) {
   6317 				labels = that.element.find( selector );
   6318 				labels.each( function() {
   6319 					var element = $( this );
   6320 
   6321 					if ( element.children( ".ui-controlgroup-label-contents" ).length ) {
   6322 						return;
   6323 					}
   6324 					element.contents()
   6325 						.wrapAll( "<span class='ui-controlgroup-label-contents'></span>" );
   6326 				} );
   6327 				that._addClass( labels, null, "ui-widget ui-widget-content ui-state-default" );
   6328 				childWidgets = childWidgets.concat( labels.get() );
   6329 				return;
   6330 			}
   6331 
   6332 			// Make sure the widget actually exists
   6333 			if ( !$.fn[ widget ] ) {
   6334 				return;
   6335 			}
   6336 
   6337 			// We assume everything is in the middle to start because we can't determine
   6338 			// first / last elements until all enhancments are done.
   6339 			if ( that[ "_" + widget + "Options" ] ) {
   6340 				options = that[ "_" + widget + "Options" ]( "middle" );
   6341 			} else {
   6342 				options = { classes: {} };
   6343 			}
   6344 
   6345 			// Find instances of this widget inside controlgroup and init them
   6346 			that.element
   6347 				.find( selector )
   6348 				.each( function() {
   6349 					var element = $( this );
   6350 					var instance = element[ widget ]( "instance" );
   6351 
   6352 					// We need to clone the default options for this type of widget to avoid
   6353 					// polluting the variable options which has a wider scope than a single widget.
   6354 					var instanceOptions = $.widget.extend( {}, options );
   6355 
   6356 					// If the button is the child of a spinner ignore it
   6357 					// TODO: Find a more generic solution
   6358 					if ( widget === "button" && element.parent( ".ui-spinner" ).length ) {
   6359 						return;
   6360 					}
   6361 
   6362 					// Create the widget if it doesn't exist
   6363 					if ( !instance ) {
   6364 						instance = element[ widget ]()[ widget ]( "instance" );
   6365 					}
   6366 					if ( instance ) {
   6367 						instanceOptions.classes =
   6368 							that._resolveClassesValues( instanceOptions.classes, instance );
   6369 					}
   6370 					element[ widget ]( instanceOptions );
   6371 
   6372 					// Store an instance of the controlgroup to be able to reference
   6373 					// from the outermost element for changing options and refresh
   6374 					var widgetElement = element[ widget ]( "widget" );
   6375 					$.data( widgetElement[ 0 ], "ui-controlgroup-data",
   6376 						instance ? instance : element[ widget ]( "instance" ) );
   6377 
   6378 					childWidgets.push( widgetElement[ 0 ] );
   6379 				} );
   6380 		} );
   6381 
   6382 		this.childWidgets = $( $.unique( childWidgets ) );
   6383 		this._addClass( this.childWidgets, "ui-controlgroup-item" );
   6384 	},
   6385 
   6386 	_callChildMethod: function( method ) {
   6387 		this.childWidgets.each( function() {
   6388 			var element = $( this ),
   6389 				data = element.data( "ui-controlgroup-data" );
   6390 			if ( data && data[ method ] ) {
   6391 				data[ method ]();
   6392 			}
   6393 		} );
   6394 	},
   6395 
   6396 	_updateCornerClass: function( element, position ) {
   6397 		var remove = "ui-corner-top ui-corner-bottom ui-corner-left ui-corner-right ui-corner-all";
   6398 		var add = this._buildSimpleOptions( position, "label" ).classes.label;
   6399 
   6400 		this._removeClass( element, null, remove );
   6401 		this._addClass( element, null, add );
   6402 	},
   6403 
   6404 	_buildSimpleOptions: function( position, key ) {
   6405 		var direction = this.options.direction === "vertical";
   6406 		var result = {
   6407 			classes: {}
   6408 		};
   6409 		result.classes[ key ] = {
   6410 			"middle": "",
   6411 			"first": "ui-corner-" + ( direction ? "top" : "left" ),
   6412 			"last": "ui-corner-" + ( direction ? "bottom" : "right" ),
   6413 			"only": "ui-corner-all"
   6414 		}[ position ];
   6415 
   6416 		return result;
   6417 	},
   6418 
   6419 	_spinnerOptions: function( position ) {
   6420 		var options = this._buildSimpleOptions( position, "ui-spinner" );
   6421 
   6422 		options.classes[ "ui-spinner-up" ] = "";
   6423 		options.classes[ "ui-spinner-down" ] = "";
   6424 
   6425 		return options;
   6426 	},
   6427 
   6428 	_buttonOptions: function( position ) {
   6429 		return this._buildSimpleOptions( position, "ui-button" );
   6430 	},
   6431 
   6432 	_checkboxradioOptions: function( position ) {
   6433 		return this._buildSimpleOptions( position, "ui-checkboxradio-label" );
   6434 	},
   6435 
   6436 	_selectmenuOptions: function( position ) {
   6437 		var direction = this.options.direction === "vertical";
   6438 		return {
   6439 			width: direction ? "auto" : false,
   6440 			classes: {
   6441 				middle: {
   6442 					"ui-selectmenu-button-open": "",
   6443 					"ui-selectmenu-button-closed": ""
   6444 				},
   6445 				first: {
   6446 					"ui-selectmenu-button-open": "ui-corner-" + ( direction ? "top" : "tl" ),
   6447 					"ui-selectmenu-button-closed": "ui-corner-" + ( direction ? "top" : "left" )
   6448 				},
   6449 				last: {
   6450 					"ui-selectmenu-button-open": direction ? "" : "ui-corner-tr",
   6451 					"ui-selectmenu-button-closed": "ui-corner-" + ( direction ? "bottom" : "right" )
   6452 				},
   6453 				only: {
   6454 					"ui-selectmenu-button-open": "ui-corner-top",
   6455 					"ui-selectmenu-button-closed": "ui-corner-all"
   6456 				}
   6457 
   6458 			}[ position ]
   6459 		};
   6460 	},
   6461 
   6462 	_resolveClassesValues: function( classes, instance ) {
   6463 		var result = {};
   6464 		$.each( classes, function( key ) {
   6465 			var current = instance.options.classes[ key ] || "";
   6466 			current = $.trim( current.replace( controlgroupCornerRegex, "" ) );
   6467 			result[ key ] = ( current + " " + classes[ key ] ).replace( /\s+/g, " " );
   6468 		} );
   6469 		return result;
   6470 	},
   6471 
   6472 	_setOption: function( key, value ) {
   6473 		if ( key === "direction" ) {
   6474 			this._removeClass( "ui-controlgroup-" + this.options.direction );
   6475 		}
   6476 
   6477 		this._super( key, value );
   6478 		if ( key === "disabled" ) {
   6479 			this._callChildMethod( value ? "disable" : "enable" );
   6480 			return;
   6481 		}
   6482 
   6483 		this.refresh();
   6484 	},
   6485 
   6486 	refresh: function() {
   6487 		var children,
   6488 			that = this;
   6489 
   6490 		this._addClass( "ui-controlgroup ui-controlgroup-" + this.options.direction );
   6491 
   6492 		if ( this.options.direction === "horizontal" ) {
   6493 			this._addClass( null, "ui-helper-clearfix" );
   6494 		}
   6495 		this._initWidgets();
   6496 
   6497 		children = this.childWidgets;
   6498 
   6499 		// We filter here because we need to track all childWidgets not just the visible ones
   6500 		if ( this.options.onlyVisible ) {
   6501 			children = children.filter( ":visible" );
   6502 		}
   6503 
   6504 		if ( children.length ) {
   6505 
   6506 			// We do this last because we need to make sure all enhancment is done
   6507 			// before determining first and last
   6508 			$.each( [ "first", "last" ], function( index, value ) {
   6509 				var instance = children[ value ]().data( "ui-controlgroup-data" );
   6510 
   6511 				if ( instance && that[ "_" + instance.widgetName + "Options" ] ) {
   6512 					var options = that[ "_" + instance.widgetName + "Options" ](
   6513 						children.length === 1 ? "only" : value
   6514 					);
   6515 					options.classes = that._resolveClassesValues( options.classes, instance );
   6516 					instance.element[ instance.widgetName ]( options );
   6517 				} else {
   6518 					that._updateCornerClass( children[ value ](), value );
   6519 				}
   6520 			} );
   6521 
   6522 			// Finally call the refresh method on each of the child widgets.
   6523 			this._callChildMethod( "refresh" );
   6524 		}
   6525 	}
   6526 } );
   6527 
   6528 /*!
   6529  * jQuery UI Checkboxradio 1.12.1
   6530  * http://jqueryui.com
   6531  *
   6532  * Copyright jQuery Foundation and other contributors
   6533  * Released under the MIT license.
   6534  * http://jquery.org/license
   6535  */
   6536 
   6537 //>>label: Checkboxradio
   6538 //>>group: Widgets
   6539 //>>description: Enhances a form with multiple themeable checkboxes or radio buttons.
   6540 //>>docs: http://api.jqueryui.com/checkboxradio/
   6541 //>>demos: http://jqueryui.com/checkboxradio/
   6542 //>>css.structure: ../../themes/base/core.css
   6543 //>>css.structure: ../../themes/base/button.css
   6544 //>>css.structure: ../../themes/base/checkboxradio.css
   6545 //>>css.theme: ../../themes/base/theme.css
   6546 
   6547 
   6548 
   6549 $.widget( "ui.checkboxradio", [ $.ui.formResetMixin, {
   6550 	version: "1.12.1",
   6551 	options: {
   6552 		disabled: null,
   6553 		label: null,
   6554 		icon: true,
   6555 		classes: {
   6556 			"ui-checkboxradio-label": "ui-corner-all",
   6557 			"ui-checkboxradio-icon": "ui-corner-all"
   6558 		}
   6559 	},
   6560 
   6561 	_getCreateOptions: function() {
   6562 		var disabled, labels;
   6563 		var that = this;
   6564 		var options = this._super() || {};
   6565 
   6566 		// We read the type here, because it makes more sense to throw a element type error first,
   6567 		// rather then the error for lack of a label. Often if its the wrong type, it
   6568 		// won't have a label (e.g. calling on a div, btn, etc)
   6569 		this._readType();
   6570 
   6571 		labels = this.element.labels();
   6572 
   6573 		// If there are multiple labels, use the last one
   6574 		this.label = $( labels[ labels.length - 1 ] );
   6575 		if ( !this.label.length ) {
   6576 			$.error( "No label found for checkboxradio widget" );
   6577 		}
   6578 
   6579 		this.originalLabel = "";
   6580 
   6581 		// We need to get the label text but this may also need to make sure it does not contain the
   6582 		// input itself.
   6583 		this.label.contents().not( this.element[ 0 ] ).each( function() {
   6584 
   6585 			// The label contents could be text, html, or a mix. We concat each element to get a
   6586 			// string representation of the label, without the input as part of it.
   6587 			that.originalLabel += this.nodeType === 3 ? $( this ).text() : this.outerHTML;
   6588 		} );
   6589 
   6590 		// Set the label option if we found label text
   6591 		if ( this.originalLabel ) {
   6592 			options.label = this.originalLabel;
   6593 		}
   6594 
   6595 		disabled = this.element[ 0 ].disabled;
   6596 		if ( disabled != null ) {
   6597 			options.disabled = disabled;
   6598 		}
   6599 		return options;
   6600 	},
   6601 
   6602 	_create: function() {
   6603 		var checked = this.element[ 0 ].checked;
   6604 
   6605 		this._bindFormResetHandler();
   6606 
   6607 		if ( this.options.disabled == null ) {
   6608 			this.options.disabled = this.element[ 0 ].disabled;
   6609 		}
   6610 
   6611 		this._setOption( "disabled", this.options.disabled );
   6612 		this._addClass( "ui-checkboxradio", "ui-helper-hidden-accessible" );
   6613 		this._addClass( this.label, "ui-checkboxradio-label", "ui-button ui-widget" );
   6614 
   6615 		if ( this.type === "radio" ) {
   6616 			this._addClass( this.label, "ui-checkboxradio-radio-label" );
   6617 		}
   6618 
   6619 		if ( this.options.label && this.options.label !== this.originalLabel ) {
   6620 			this._updateLabel();
   6621 		} else if ( this.originalLabel ) {
   6622 			this.options.label = this.originalLabel;
   6623 		}
   6624 
   6625 		this._enhance();
   6626 
   6627 		if ( checked ) {
   6628 			this._addClass( this.label, "ui-checkboxradio-checked", "ui-state-active" );
   6629 			if ( this.icon ) {
   6630 				this._addClass( this.icon, null, "ui-state-hover" );
   6631 			}
   6632 		}
   6633 
   6634 		this._on( {
   6635 			change: "_toggleClasses",
   6636 			focus: function() {
   6637 				this._addClass( this.label, null, "ui-state-focus ui-visual-focus" );
   6638 			},
   6639 			blur: function() {
   6640 				this._removeClass( this.label, null, "ui-state-focus ui-visual-focus" );
   6641 			}
   6642 		} );
   6643 	},
   6644 
   6645 	_readType: function() {
   6646 		var nodeName = this.element[ 0 ].nodeName.toLowerCase();
   6647 		this.type = this.element[ 0 ].type;
   6648 		if ( nodeName !== "input" || !/radio|checkbox/.test( this.type ) ) {
   6649 			$.error( "Can't create checkboxradio on element.nodeName=" + nodeName +
   6650 				" and element.type=" + this.type );
   6651 		}
   6652 	},
   6653 
   6654 	// Support jQuery Mobile enhanced option
   6655 	_enhance: function() {
   6656 		this._updateIcon( this.element[ 0 ].checked );
   6657 	},
   6658 
   6659 	widget: function() {
   6660 		return this.label;
   6661 	},
   6662 
   6663 	_getRadioGroup: function() {
   6664 		var group;
   6665 		var name = this.element[ 0 ].name;
   6666 		var nameSelector = "input[name='" + $.ui.escapeSelector( name ) + "']";
   6667 
   6668 		if ( !name ) {
   6669 			return $( [] );
   6670 		}
   6671 
   6672 		if ( this.form.length ) {
   6673 			group = $( this.form[ 0 ].elements ).filter( nameSelector );
   6674 		} else {
   6675 
   6676 			// Not inside a form, check all inputs that also are not inside a form
   6677 			group = $( nameSelector ).filter( function() {
   6678 				return $( this ).form().length === 0;
   6679 			} );
   6680 		}
   6681 
   6682 		return group.not( this.element );
   6683 	},
   6684 
   6685 	_toggleClasses: function() {
   6686 		var checked = this.element[ 0 ].checked;
   6687 		this._toggleClass( this.label, "ui-checkboxradio-checked", "ui-state-active", checked );
   6688 
   6689 		if ( this.options.icon && this.type === "checkbox" ) {
   6690 			this._toggleClass( this.icon, null, "ui-icon-check ui-state-checked", checked )
   6691 				._toggleClass( this.icon, null, "ui-icon-blank", !checked );
   6692 		}
   6693 
   6694 		if ( this.type === "radio" ) {
   6695 			this._getRadioGroup()
   6696 				.each( function() {
   6697 					var instance = $( this ).checkboxradio( "instance" );
   6698 
   6699 					if ( instance ) {
   6700 						instance._removeClass( instance.label,
   6701 							"ui-checkboxradio-checked", "ui-state-active" );
   6702 					}
   6703 				} );
   6704 		}
   6705 	},
   6706 
   6707 	_destroy: function() {
   6708 		this._unbindFormResetHandler();
   6709 
   6710 		if ( this.icon ) {
   6711 			this.icon.remove();
   6712 			this.iconSpace.remove();
   6713 		}
   6714 	},
   6715 
   6716 	_setOption: function( key, value ) {
   6717 
   6718 		// We don't allow the value to be set to nothing
   6719 		if ( key === "label" && !value ) {
   6720 			return;
   6721 		}
   6722 
   6723 		this._super( key, value );
   6724 
   6725 		if ( key === "disabled" ) {
   6726 			this._toggleClass( this.label, null, "ui-state-disabled", value );
   6727 			this.element[ 0 ].disabled = value;
   6728 
   6729 			// Don't refresh when setting disabled
   6730 			return;
   6731 		}
   6732 		this.refresh();
   6733 	},
   6734 
   6735 	_updateIcon: function( checked ) {
   6736 		var toAdd = "ui-icon ui-icon-background ";
   6737 
   6738 		if ( this.options.icon ) {
   6739 			if ( !this.icon ) {
   6740 				this.icon = $( "<span>" );
   6741 				this.iconSpace = $( "<span> </span>" );
   6742 				this._addClass( this.iconSpace, "ui-checkboxradio-icon-space" );
   6743 			}
   6744 
   6745 			if ( this.type === "checkbox" ) {
   6746 				toAdd += checked ? "ui-icon-check ui-state-checked" : "ui-icon-blank";
   6747 				this._removeClass( this.icon, null, checked ? "ui-icon-blank" : "ui-icon-check" );
   6748 			} else {
   6749 				toAdd += "ui-icon-blank";
   6750 			}
   6751 			this._addClass( this.icon, "ui-checkboxradio-icon", toAdd );
   6752 			if ( !checked ) {
   6753 				this._removeClass( this.icon, null, "ui-icon-check ui-state-checked" );
   6754 			}
   6755 			this.icon.prependTo( this.label ).after( this.iconSpace );
   6756 		} else if ( this.icon !== undefined ) {
   6757 			this.icon.remove();
   6758 			this.iconSpace.remove();
   6759 			delete this.icon;
   6760 		}
   6761 	},
   6762 
   6763 	_updateLabel: function() {
   6764 
   6765 		// Remove the contents of the label ( minus the icon, icon space, and input )
   6766 		var contents = this.label.contents().not( this.element[ 0 ] );
   6767 		if ( this.icon ) {
   6768 			contents = contents.not( this.icon[ 0 ] );
   6769 		}
   6770 		if ( this.iconSpace ) {
   6771 			contents = contents.not( this.iconSpace[ 0 ] );
   6772 		}
   6773 		contents.remove();
   6774 
   6775 		this.label.append( this.options.label );
   6776 	},
   6777 
   6778 	refresh: function() {
   6779 		var checked = this.element[ 0 ].checked,
   6780 			isDisabled = this.element[ 0 ].disabled;
   6781 
   6782 		this._updateIcon( checked );
   6783 		this._toggleClass( this.label, "ui-checkboxradio-checked", "ui-state-active", checked );
   6784 		if ( this.options.label !== null ) {
   6785 			this._updateLabel();
   6786 		}
   6787 
   6788 		if ( isDisabled !== this.options.disabled ) {
   6789 			this._setOptions( { "disabled": isDisabled } );
   6790 		}
   6791 	}
   6792 
   6793 } ] );
   6794 
   6795 var widgetsCheckboxradio = $.ui.checkboxradio;
   6796 
   6797 
   6798 /*!
   6799  * jQuery UI Button 1.12.1
   6800  * http://jqueryui.com
   6801  *
   6802  * Copyright jQuery Foundation and other contributors
   6803  * Released under the MIT license.
   6804  * http://jquery.org/license
   6805  */
   6806 
   6807 //>>label: Button
   6808 //>>group: Widgets
   6809 //>>description: Enhances a form with themeable buttons.
   6810 //>>docs: http://api.jqueryui.com/button/
   6811 //>>demos: http://jqueryui.com/button/
   6812 //>>css.structure: ../../themes/base/core.css
   6813 //>>css.structure: ../../themes/base/button.css
   6814 //>>css.theme: ../../themes/base/theme.css
   6815 
   6816 
   6817 
   6818 $.widget( "ui.button", {
   6819 	version: "1.12.1",
   6820 	defaultElement: "<button>",
   6821 	options: {
   6822 		classes: {
   6823 			"ui-button": "ui-corner-all"
   6824 		},
   6825 		disabled: null,
   6826 		icon: null,
   6827 		iconPosition: "beginning",
   6828 		label: null,
   6829 		showLabel: true
   6830 	},
   6831 
   6832 	_getCreateOptions: function() {
   6833 		var disabled,
   6834 
   6835 			// This is to support cases like in jQuery Mobile where the base widget does have
   6836 			// an implementation of _getCreateOptions
   6837 			options = this._super() || {};
   6838 
   6839 		this.isInput = this.element.is( "input" );
   6840 
   6841 		disabled = this.element[ 0 ].disabled;
   6842 		if ( disabled != null ) {
   6843 			options.disabled = disabled;
   6844 		}
   6845 
   6846 		this.originalLabel = this.isInput ? this.element.val() : this.element.html();
   6847 		if ( this.originalLabel ) {
   6848 			options.label = this.originalLabel;
   6849 		}
   6850 
   6851 		return options;
   6852 	},
   6853 
   6854 	_create: function() {
   6855 		if ( !this.option.showLabel & !this.options.icon ) {
   6856 			this.options.showLabel = true;
   6857 		}
   6858 
   6859 		// We have to check the option again here even though we did in _getCreateOptions,
   6860 		// because null may have been passed on init which would override what was set in
   6861 		// _getCreateOptions
   6862 		if ( this.options.disabled == null ) {
   6863 			this.options.disabled = this.element[ 0 ].disabled || false;
   6864 		}
   6865 
   6866 		this.hasTitle = !!this.element.attr( "title" );
   6867 
   6868 		// Check to see if the label needs to be set or if its already correct
   6869 		if ( this.options.label && this.options.label !== this.originalLabel ) {
   6870 			if ( this.isInput ) {
   6871 				this.element.val( this.options.label );
   6872 			} else {
   6873 				this.element.html( this.options.label );
   6874 			}
   6875 		}
   6876 		this._addClass( "ui-button", "ui-widget" );
   6877 		this._setOption( "disabled", this.options.disabled );
   6878 		this._enhance();
   6879 
   6880 		if ( this.element.is( "a" ) ) {
   6881 			this._on( {
   6882 				"keyup": function( event ) {
   6883 					if ( event.keyCode === $.ui.keyCode.SPACE ) {
   6884 						event.preventDefault();
   6885 
   6886 						// Support: PhantomJS <= 1.9, IE 8 Only
   6887 						// If a native click is available use it so we actually cause navigation
   6888 						// otherwise just trigger a click event
   6889 						if ( this.element[ 0 ].click ) {
   6890 							this.element[ 0 ].click();
   6891 						} else {
   6892 							this.element.trigger( "click" );
   6893 						}
   6894 					}
   6895 				}
   6896 			} );
   6897 		}
   6898 	},
   6899 
   6900 	_enhance: function() {
   6901 		if ( !this.element.is( "button" ) ) {
   6902 			this.element.attr( "role", "button" );
   6903 		}
   6904 
   6905 		if ( this.options.icon ) {
   6906 			this._updateIcon( "icon", this.options.icon );
   6907 			this._updateTooltip();
   6908 		}
   6909 	},
   6910 
   6911 	_updateTooltip: function() {
   6912 		this.title = this.element.attr( "title" );
   6913 
   6914 		if ( !this.options.showLabel && !this.title ) {
   6915 			this.element.attr( "title", this.options.label );
   6916 		}
   6917 	},
   6918 
   6919 	_updateIcon: function( option, value ) {
   6920 		var icon = option !== "iconPosition",
   6921 			position = icon ? this.options.iconPosition : value,
   6922 			displayBlock = position === "top" || position === "bottom";
   6923 
   6924 		// Create icon
   6925 		if ( !this.icon ) {
   6926 			this.icon = $( "<span>" );
   6927 
   6928 			this._addClass( this.icon, "ui-button-icon", "ui-icon" );
   6929 
   6930 			if ( !this.options.showLabel ) {
   6931 				this._addClass( "ui-button-icon-only" );
   6932 			}
   6933 		} else if ( icon ) {
   6934 
   6935 			// If we are updating the icon remove the old icon class
   6936 			this._removeClass( this.icon, null, this.options.icon );
   6937 		}
   6938 
   6939 		// If we are updating the icon add the new icon class
   6940 		if ( icon ) {
   6941 			this._addClass( this.icon, null, value );
   6942 		}
   6943 
   6944 		this._attachIcon( position );
   6945 
   6946 		// If the icon is on top or bottom we need to add the ui-widget-icon-block class and remove
   6947 		// the iconSpace if there is one.
   6948 		if ( displayBlock ) {
   6949 			this._addClass( this.icon, null, "ui-widget-icon-block" );
   6950 			if ( this.iconSpace ) {
   6951 				this.iconSpace.remove();
   6952 			}
   6953 		} else {
   6954 
   6955 			// Position is beginning or end so remove the ui-widget-icon-block class and add the
   6956 			// space if it does not exist
   6957 			if ( !this.iconSpace ) {
   6958 				this.iconSpace = $( "<span> </span>" );
   6959 				this._addClass( this.iconSpace, "ui-button-icon-space" );
   6960 			}
   6961 			this._removeClass( this.icon, null, "ui-wiget-icon-block" );
   6962 			this._attachIconSpace( position );
   6963 		}
   6964 	},
   6965 
   6966 	_destroy: function() {
   6967 		this.element.removeAttr( "role" );
   6968 
   6969 		if ( this.icon ) {
   6970 			this.icon.remove();
   6971 		}
   6972 		if ( this.iconSpace ) {
   6973 			this.iconSpace.remove();
   6974 		}
   6975 		if ( !this.hasTitle ) {
   6976 			this.element.removeAttr( "title" );
   6977 		}
   6978 	},
   6979 
   6980 	_attachIconSpace: function( iconPosition ) {
   6981 		this.icon[ /^(?:end|bottom)/.test( iconPosition ) ? "before" : "after" ]( this.iconSpace );
   6982 	},
   6983 
   6984 	_attachIcon: function( iconPosition ) {
   6985 		this.element[ /^(?:end|bottom)/.test( iconPosition ) ? "append" : "prepend" ]( this.icon );
   6986 	},
   6987 
   6988 	_setOptions: function( options ) {
   6989 		var newShowLabel = options.showLabel === undefined ?
   6990 				this.options.showLabel :
   6991 				options.showLabel,
   6992 			newIcon = options.icon === undefined ? this.options.icon : options.icon;
   6993 
   6994 		if ( !newShowLabel && !newIcon ) {
   6995 			options.showLabel = true;
   6996 		}
   6997 		this._super( options );
   6998 	},
   6999 
   7000 	_setOption: function( key, value ) {
   7001 		if ( key === "icon" ) {
   7002 			if ( value ) {
   7003 				this._updateIcon( key, value );
   7004 			} else if ( this.icon ) {
   7005 				this.icon.remove();
   7006 				if ( this.iconSpace ) {
   7007 					this.iconSpace.remove();
   7008 				}
   7009 			}
   7010 		}
   7011 
   7012 		if ( key === "iconPosition" ) {
   7013 			this._updateIcon( key, value );
   7014 		}
   7015 
   7016 		// Make sure we can't end up with a button that has neither text nor icon
   7017 		if ( key === "showLabel" ) {
   7018 				this._toggleClass( "ui-button-icon-only", null, !value );
   7019 				this._updateTooltip();
   7020 		}
   7021 
   7022 		if ( key === "label" ) {
   7023 			if ( this.isInput ) {
   7024 				this.element.val( value );
   7025 			} else {
   7026 
   7027 				// If there is an icon, append it, else nothing then append the value
   7028 				// this avoids removal of the icon when setting label text
   7029 				this.element.html( value );
   7030 				if ( this.icon ) {
   7031 					this._attachIcon( this.options.iconPosition );
   7032 					this._attachIconSpace( this.options.iconPosition );
   7033 				}
   7034 			}
   7035 		}
   7036 
   7037 		this._super( key, value );
   7038 
   7039 		if ( key === "disabled" ) {
   7040 			this._toggleClass( null, "ui-state-disabled", value );
   7041 			this.element[ 0 ].disabled = value;
   7042 			if ( value ) {
   7043 				this.element.blur();
   7044 			}
   7045 		}
   7046 	},
   7047 
   7048 	refresh: function() {
   7049 
   7050 		// Make sure to only check disabled if its an element that supports this otherwise
   7051 		// check for the disabled class to determine state
   7052 		var isDisabled = this.element.is( "input, button" ) ?
   7053 			this.element[ 0 ].disabled : this.element.hasClass( "ui-button-disabled" );
   7054 
   7055 		if ( isDisabled !== this.options.disabled ) {
   7056 			this._setOptions( { disabled: isDisabled } );
   7057 		}
   7058 
   7059 		this._updateTooltip();
   7060 	}
   7061 } );
   7062 
   7063 // DEPRECATED
   7064 if ( $.uiBackCompat !== false ) {
   7065 
   7066 	// Text and Icons options
   7067 	$.widget( "ui.button", $.ui.button, {
   7068 		options: {
   7069 			text: true,
   7070 			icons: {
   7071 				primary: null,
   7072 				secondary: null
   7073 			}
   7074 		},
   7075 
   7076 		_create: function() {
   7077 			if ( this.options.showLabel && !this.options.text ) {
   7078 				this.options.showLabel = this.options.text;
   7079 			}
   7080 			if ( !this.options.showLabel && this.options.text ) {
   7081 				this.options.text = this.options.showLabel;
   7082 			}
   7083 			if ( !this.options.icon && ( this.options.icons.primary ||
   7084 					this.options.icons.secondary ) ) {
   7085 				if ( this.options.icons.primary ) {
   7086 					this.options.icon = this.options.icons.primary;
   7087 				} else {
   7088 					this.options.icon = this.options.icons.secondary;
   7089 					this.options.iconPosition = "end";
   7090 				}
   7091 			} else if ( this.options.icon ) {
   7092 				this.options.icons.primary = this.options.icon;
   7093 			}
   7094 			this._super();
   7095 		},
   7096 
   7097 		_setOption: function( key, value ) {
   7098 			if ( key === "text" ) {
   7099 				this._super( "showLabel", value );
   7100 				return;
   7101 			}
   7102 			if ( key === "showLabel" ) {
   7103 				this.options.text = value;
   7104 			}
   7105 			if ( key === "icon" ) {
   7106 				this.options.icons.primary = value;
   7107 			}
   7108 			if ( key === "icons" ) {
   7109 				if ( value.primary ) {
   7110 					this._super( "icon", value.primary );
   7111 					this._super( "iconPosition", "beginning" );
   7112 				} else if ( value.secondary ) {
   7113 					this._super( "icon", value.secondary );
   7114 					this._super( "iconPosition", "end" );
   7115 				}
   7116 			}
   7117 			this._superApply( arguments );
   7118 		}
   7119 	} );
   7120 
   7121 	$.fn.button = ( function( orig ) {
   7122 		return function() {
   7123 			if ( !this.length || ( this.length && this[ 0 ].tagName !== "INPUT" ) ||
   7124 					( this.length && this[ 0 ].tagName === "INPUT" && (
   7125 						this.attr( "type" ) !== "checkbox" && this.attr( "type" ) !== "radio"
   7126 					) ) ) {
   7127 				return orig.apply( this, arguments );
   7128 			}
   7129 			if ( !$.ui.checkboxradio ) {
   7130 				$.error( "Checkboxradio widget missing" );
   7131 			}
   7132 			if ( arguments.length === 0 ) {
   7133 				return this.checkboxradio( {
   7134 					"icon": false
   7135 				} );
   7136 			}
   7137 			return this.checkboxradio.apply( this, arguments );
   7138 		};
   7139 	} )( $.fn.button );
   7140 
   7141 	$.fn.buttonset = function() {
   7142 		if ( !$.ui.controlgroup ) {
   7143 			$.error( "Controlgroup widget missing" );
   7144 		}
   7145 		if ( arguments[ 0 ] === "option" && arguments[ 1 ] === "items" && arguments[ 2 ] ) {
   7146 			return this.controlgroup.apply( this,
   7147 				[ arguments[ 0 ], "items.button", arguments[ 2 ] ] );
   7148 		}
   7149 		if ( arguments[ 0 ] === "option" && arguments[ 1 ] === "items" ) {
   7150 			return this.controlgroup.apply( this, [ arguments[ 0 ], "items.button" ] );
   7151 		}
   7152 		if ( typeof arguments[ 0 ] === "object" && arguments[ 0 ].items ) {
   7153 			arguments[ 0 ].items = {
   7154 				button: arguments[ 0 ].items
   7155 			};
   7156 		}
   7157 		return this.controlgroup.apply( this, arguments );
   7158 	};
   7159 }
   7160 
   7161 var widgetsButton = $.ui.button;
   7162 
   7163 
   7164 // jscs:disable maximumLineLength
   7165 /* jscs:disable requireCamelCaseOrUpperCaseIdentifiers */
   7166 /*!
   7167  * jQuery UI Datepicker 1.12.1
   7168  * http://jqueryui.com
   7169  *
   7170  * Copyright jQuery Foundation and other contributors
   7171 
   7172  * Released under the MIT license.
   7173  * http://jquery.org/license
   7174  */
   7175 
   7176 //>>label: Datepicker
   7177 //>>group: Widgets
   7178 //>>description: Displays a calendar from an input or inline for selecting dates.
   7179 //>>docs: http://api.jqueryui.com/datepicker/
   7180 //>>demos: http://jqueryui.com/datepicker/
   7181 //>>css.structure: ../../themes/base/core.css
   7182 //>>css.structure: ../../themes/base/datepicker.css
   7183 //>>css.theme: ../../themes/base/theme.css
   7184 
   7185 
   7186 
   7187 $.extend( $.ui, { datepicker: { version: "1.12.1" } } );
   7188 
   7189 var datepicker_instActive;
   7190 
   7191 function datepicker_getZindex( elem ) {
   7192 	var position, value;
   7193 	while ( elem.length && elem[ 0 ] !== document ) {
   7194 
   7195 		// Ignore z-index if position is set to a value where z-index is ignored by the browser
   7196 		// This makes behavior of this function consistent across browsers
   7197 		// WebKit always returns auto if the element is positioned
   7198 		position = elem.css( "position" );
   7199 		if ( position === "absolute" || position === "relative" || position === "fixed" ) {
   7200 
   7201 			// IE returns 0 when zIndex is not specified
   7202 			// other browsers return a string
   7203 			// we ignore the case of nested elements with an explicit value of 0
   7204 			// <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
   7205 			value = parseInt( elem.css( "zIndex" ), 10 );
   7206 			if ( !isNaN( value ) && value !== 0 ) {
   7207 				return value;
   7208 			}
   7209 		}
   7210 		elem = elem.parent();
   7211 	}
   7212 
   7213 	return 0;
   7214 }
   7215 /* Date picker manager.
   7216    Use the singleton instance of this class, $.datepicker, to interact with the date picker.
   7217    Settings for (groups of) date pickers are maintained in an instance object,
   7218    allowing multiple different settings on the same page. */
   7219 
   7220 function Datepicker() {
   7221 	this._curInst = null; // The current instance in use
   7222 	this._keyEvent = false; // If the last event was a key event
   7223 	this._disabledInputs = []; // List of date picker inputs that have been disabled
   7224 	this._datepickerShowing = false; // True if the popup picker is showing , false if not
   7225 	this._inDialog = false; // True if showing within a "dialog", false if not
   7226 	this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division
   7227 	this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class
   7228 	this._appendClass = "ui-datepicker-append"; // The name of the append marker class
   7229 	this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class
   7230 	this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class
   7231 	this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class
   7232 	this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class
   7233 	this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class
   7234 	this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class
   7235 	this.regional = []; // Available regional settings, indexed by language code
   7236 	this.regional[ "" ] = { // Default regional settings
   7237 		closeText: "Done", // Display text for close link
   7238 		prevText: "Prev", // Display text for previous month link
   7239 		nextText: "Next", // Display text for next month link
   7240 		currentText: "Today", // Display text for current month link
   7241 		monthNames: [ "January","February","March","April","May","June",
   7242 			"July","August","September","October","November","December" ], // Names of months for drop-down and formatting
   7243 		monthNamesShort: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ], // For formatting
   7244 		dayNames: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ], // For formatting
   7245 		dayNamesShort: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ], // For formatting
   7246 		dayNamesMin: [ "Su","Mo","Tu","We","Th","Fr","Sa" ], // Column headings for days starting at Sunday
   7247 		weekHeader: "Wk", // Column header for week of the year
   7248 		dateFormat: "mm/dd/yy", // See format options on parseDate
   7249 		firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
   7250 		isRTL: false, // True if right-to-left language, false if left-to-right
   7251 		showMonthAfterYear: false, // True if the year select precedes month, false for month then year
   7252 		yearSuffix: "" // Additional text to append to the year in the month headers
   7253 	};
   7254 	this._defaults = { // Global defaults for all the date picker instances
   7255 		showOn: "focus", // "focus" for popup on focus,
   7256 			// "button" for trigger button, or "both" for either
   7257 		showAnim: "fadeIn", // Name of jQuery animation for popup
   7258 		showOptions: {}, // Options for enhanced animations
   7259 		defaultDate: null, // Used when field is blank: actual date,
   7260 			// +/-number for offset from today, null for today
   7261 		appendText: "", // Display text following the input box, e.g. showing the format
   7262 		buttonText: "...", // Text for trigger button
   7263 		buttonImage: "", // URL for trigger button image
   7264 		buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
   7265 		hideIfNoPrevNext: false, // True to hide next/previous month links
   7266 			// if not applicable, false to just disable them
   7267 		navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
   7268 		gotoCurrent: false, // True if today link goes back to current selection instead
   7269 		changeMonth: false, // True if month can be selected directly, false if only prev/next
   7270 		changeYear: false, // True if year can be selected directly, false if only prev/next
   7271 		yearRange: "c-10:c+10", // Range of years to display in drop-down,
   7272 			// either relative to today's year (-nn:+nn), relative to currently displayed year
   7273 			// (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
   7274 		showOtherMonths: false, // True to show dates in other months, false to leave blank
   7275 		selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
   7276 		showWeek: false, // True to show week of the year, false to not show it
   7277 		calculateWeek: this.iso8601Week, // How to calculate the week of the year,
   7278 			// takes a Date and returns the number of the week for it
   7279 		shortYearCutoff: "+10", // Short year values < this are in the current century,
   7280 			// > this are in the previous century,
   7281 			// string value starting with "+" for current year + value
   7282 		minDate: null, // The earliest selectable date, or null for no limit
   7283 		maxDate: null, // The latest selectable date, or null for no limit
   7284 		duration: "fast", // Duration of display/closure
   7285 		beforeShowDay: null, // Function that takes a date and returns an array with
   7286 			// [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "",
   7287 			// [2] = cell title (optional), e.g. $.datepicker.noWeekends
   7288 		beforeShow: null, // Function that takes an input field and
   7289 			// returns a set of custom settings for the date picker
   7290 		onSelect: null, // Define a callback function when a date is selected
   7291 		onChangeMonthYear: null, // Define a callback function when the month or year is changed
   7292 		onClose: null, // Define a callback function when the datepicker is closed
   7293 		numberOfMonths: 1, // Number of months to show at a time
   7294 		showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
   7295 		stepMonths: 1, // Number of months to step back/forward
   7296 		stepBigMonths: 12, // Number of months to step back/forward for the big links
   7297 		altField: "", // Selector for an alternate field to store selected dates into
   7298 		altFormat: "", // The date format to use for the alternate field
   7299 		constrainInput: true, // The input is constrained by the current date format
   7300 		showButtonPanel: false, // True to show button panel, false to not show it
   7301 		autoSize: false, // True to size the input for the date format, false to leave as is
   7302 		disabled: false // The initial disabled state
   7303 	};
   7304 	$.extend( this._defaults, this.regional[ "" ] );
   7305 	this.regional.en = $.extend( true, {}, this.regional[ "" ] );
   7306 	this.regional[ "en-US" ] = $.extend( true, {}, this.regional.en );
   7307 	this.dpDiv = datepicker_bindHover( $( "<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>" ) );
   7308 }
   7309 
   7310 $.extend( Datepicker.prototype, {
   7311 	/* Class name added to elements to indicate already configured with a date picker. */
   7312 	markerClassName: "hasDatepicker",
   7313 
   7314 	//Keep track of the maximum number of rows displayed (see #7043)
   7315 	maxRows: 4,
   7316 
   7317 	// TODO rename to "widget" when switching to widget factory
   7318 	_widgetDatepicker: function() {
   7319 		return this.dpDiv;
   7320 	},
   7321 
   7322 	/* Override the default settings for all instances of the date picker.
   7323 	 * @param  settings  object - the new settings to use as defaults (anonymous object)
   7324 	 * @return the manager object
   7325 	 */
   7326 	setDefaults: function( settings ) {
   7327 		datepicker_extendRemove( this._defaults, settings || {} );
   7328 		return this;
   7329 	},
   7330 
   7331 	/* Attach the date picker to a jQuery selection.
   7332 	 * @param  target	element - the target input field or division or span
   7333 	 * @param  settings  object - the new settings to use for this date picker instance (anonymous)
   7334 	 */
   7335 	_attachDatepicker: function( target, settings ) {
   7336 		var nodeName, inline, inst;
   7337 		nodeName = target.nodeName.toLowerCase();
   7338 		inline = ( nodeName === "div" || nodeName === "span" );
   7339 		if ( !target.id ) {
   7340 			this.uuid += 1;
   7341 			target.id = "dp" + this.uuid;
   7342 		}
   7343 		inst = this._newInst( $( target ), inline );
   7344 		inst.settings = $.extend( {}, settings || {} );
   7345 		if ( nodeName === "input" ) {
   7346 			this._connectDatepicker( target, inst );
   7347 		} else if ( inline ) {
   7348 			this._inlineDatepicker( target, inst );
   7349 		}
   7350 	},
   7351 
   7352 	/* Create a new instance object. */
   7353 	_newInst: function( target, inline ) {
   7354 		var id = target[ 0 ].id.replace( /([^A-Za-z0-9_\-])/g, "\\\\$1" ); // escape jQuery meta chars
   7355 		return { id: id, input: target, // associated target
   7356 			selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
   7357 			drawMonth: 0, drawYear: 0, // month being drawn
   7358 			inline: inline, // is datepicker inline or not
   7359 			dpDiv: ( !inline ? this.dpDiv : // presentation div
   7360 			datepicker_bindHover( $( "<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>" ) ) ) };
   7361 	},
   7362 
   7363 	/* Attach the date picker to an input field. */
   7364 	_connectDatepicker: function( target, inst ) {
   7365 		var input = $( target );
   7366 		inst.append = $( [] );
   7367 		inst.trigger = $( [] );
   7368 		if ( input.hasClass( this.markerClassName ) ) {
   7369 			return;
   7370 		}
   7371 		this._attachments( input, inst );
   7372 		input.addClass( this.markerClassName ).on( "keydown", this._doKeyDown ).
   7373 			on( "keypress", this._doKeyPress ).on( "keyup", this._doKeyUp );
   7374 		this._autoSize( inst );
   7375 		$.data( target, "datepicker", inst );
   7376 
   7377 		//If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
   7378 		if ( inst.settings.disabled ) {
   7379 			this._disableDatepicker( target );
   7380 		}
   7381 	},
   7382 
   7383 	/* Make attachments based on settings. */
   7384 	_attachments: function( input, inst ) {
   7385 		var showOn, buttonText, buttonImage,
   7386 			appendText = this._get( inst, "appendText" ),
   7387 			isRTL = this._get( inst, "isRTL" );
   7388 
   7389 		if ( inst.append ) {
   7390 			inst.append.remove();
   7391 		}
   7392 		if ( appendText ) {
   7393 			inst.append = $( "<span class='" + this._appendClass + "'>" + appendText + "</span>" );
   7394 			input[ isRTL ? "before" : "after" ]( inst.append );
   7395 		}
   7396 
   7397 		input.off( "focus", this._showDatepicker );
   7398 
   7399 		if ( inst.trigger ) {
   7400 			inst.trigger.remove();
   7401 		}
   7402 
   7403 		showOn = this._get( inst, "showOn" );
   7404 		if ( showOn === "focus" || showOn === "both" ) { // pop-up date picker when in the marked field
   7405 			input.on( "focus", this._showDatepicker );
   7406 		}
   7407 		if ( showOn === "button" || showOn === "both" ) { // pop-up date picker when button clicked
   7408 			buttonText = this._get( inst, "buttonText" );
   7409 			buttonImage = this._get( inst, "buttonImage" );
   7410 			inst.trigger = $( this._get( inst, "buttonImageOnly" ) ?
   7411 				$( "<img/>" ).addClass( this._triggerClass ).
   7412 					attr( { src: buttonImage, alt: buttonText, title: buttonText } ) :
   7413 				$( "<button type='button'></button>" ).addClass( this._triggerClass ).
   7414 					html( !buttonImage ? buttonText : $( "<img/>" ).attr(
   7415 					{ src:buttonImage, alt:buttonText, title:buttonText } ) ) );
   7416 			input[ isRTL ? "before" : "after" ]( inst.trigger );
   7417 			inst.trigger.on( "click", function() {
   7418 				if ( $.datepicker._datepickerShowing && $.datepicker._lastInput === input[ 0 ] ) {
   7419 					$.datepicker._hideDatepicker();
   7420 				} else if ( $.datepicker._datepickerShowing && $.datepicker._lastInput !== input[ 0 ] ) {
   7421 					$.datepicker._hideDatepicker();
   7422 					$.datepicker._showDatepicker( input[ 0 ] );
   7423 				} else {
   7424 					$.datepicker._showDatepicker( input[ 0 ] );
   7425 				}
   7426 				return false;
   7427 			} );
   7428 		}
   7429 	},
   7430 
   7431 	/* Apply the maximum length for the date format. */
   7432 	_autoSize: function( inst ) {
   7433 		if ( this._get( inst, "autoSize" ) && !inst.inline ) {
   7434 			var findMax, max, maxI, i,
   7435 				date = new Date( 2009, 12 - 1, 20 ), // Ensure double digits
   7436 				dateFormat = this._get( inst, "dateFormat" );
   7437 
   7438 			if ( dateFormat.match( /[DM]/ ) ) {
   7439 				findMax = function( names ) {
   7440 					max = 0;
   7441 					maxI = 0;
   7442 					for ( i = 0; i < names.length; i++ ) {
   7443 						if ( names[ i ].length > max ) {
   7444 							max = names[ i ].length;
   7445 							maxI = i;
   7446 						}
   7447 					}
   7448 					return maxI;
   7449 				};
   7450 				date.setMonth( findMax( this._get( inst, ( dateFormat.match( /MM/ ) ?
   7451 					"monthNames" : "monthNamesShort" ) ) ) );
   7452 				date.setDate( findMax( this._get( inst, ( dateFormat.match( /DD/ ) ?
   7453 					"dayNames" : "dayNamesShort" ) ) ) + 20 - date.getDay() );
   7454 			}
   7455 			inst.input.attr( "size", this._formatDate( inst, date ).length );
   7456 		}
   7457 	},
   7458 
   7459 	/* Attach an inline date picker to a div. */
   7460 	_inlineDatepicker: function( target, inst ) {
   7461 		var divSpan = $( target );
   7462 		if ( divSpan.hasClass( this.markerClassName ) ) {
   7463 			return;
   7464 		}
   7465 		divSpan.addClass( this.markerClassName ).append( inst.dpDiv );
   7466 		$.data( target, "datepicker", inst );
   7467 		this._setDate( inst, this._getDefaultDate( inst ), true );
   7468 		this._updateDatepicker( inst );
   7469 		this._updateAlternate( inst );
   7470 
   7471 		//If disabled option is true, disable the datepicker before showing it (see ticket #5665)
   7472 		if ( inst.settings.disabled ) {
   7473 			this._disableDatepicker( target );
   7474 		}
   7475 
   7476 		// Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
   7477 		// http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
   7478 		inst.dpDiv.css( "display", "block" );
   7479 	},
   7480 
   7481 	/* Pop-up the date picker in a "dialog" box.
   7482 	 * @param  input element - ignored
   7483 	 * @param  date	string or Date - the initial date to display
   7484 	 * @param  onSelect  function - the function to call when a date is selected
   7485 	 * @param  settings  object - update the dialog date picker instance's settings (anonymous object)
   7486 	 * @param  pos int[2] - coordinates for the dialog's position within the screen or
   7487 	 *					event - with x/y coordinates or
   7488 	 *					leave empty for default (screen centre)
   7489 	 * @return the manager object
   7490 	 */
   7491 	_dialogDatepicker: function( input, date, onSelect, settings, pos ) {
   7492 		var id, browserWidth, browserHeight, scrollX, scrollY,
   7493 			inst = this._dialogInst; // internal instance
   7494 
   7495 		if ( !inst ) {
   7496 			this.uuid += 1;
   7497 			id = "dp" + this.uuid;
   7498 			this._dialogInput = $( "<input type='text' id='" + id +
   7499 				"' style='position: absolute; top: -100px; width: 0px;'/>" );
   7500 			this._dialogInput.on( "keydown", this._doKeyDown );
   7501 			$( "body" ).append( this._dialogInput );
   7502 			inst = this._dialogInst = this._newInst( this._dialogInput, false );
   7503 			inst.settings = {};
   7504 			$.data( this._dialogInput[ 0 ], "datepicker", inst );
   7505 		}
   7506 		datepicker_extendRemove( inst.settings, settings || {} );
   7507 		date = ( date && date.constructor === Date ? this._formatDate( inst, date ) : date );
   7508 		this._dialogInput.val( date );
   7509 
   7510 		this._pos = ( pos ? ( pos.length ? pos : [ pos.pageX, pos.pageY ] ) : null );
   7511 		if ( !this._pos ) {
   7512 			browserWidth = document.documentElement.clientWidth;
   7513 			browserHeight = document.documentElement.clientHeight;
   7514 			scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
   7515 			scrollY = document.documentElement.scrollTop || document.body.scrollTop;
   7516 			this._pos = // should use actual width/height below
   7517 				[ ( browserWidth / 2 ) - 100 + scrollX, ( browserHeight / 2 ) - 150 + scrollY ];
   7518 		}
   7519 
   7520 		// Move input on screen for focus, but hidden behind dialog
   7521 		this._dialogInput.css( "left", ( this._pos[ 0 ] + 20 ) + "px" ).css( "top", this._pos[ 1 ] + "px" );
   7522 		inst.settings.onSelect = onSelect;
   7523 		this._inDialog = true;
   7524 		this.dpDiv.addClass( this._dialogClass );
   7525 		this._showDatepicker( this._dialogInput[ 0 ] );
   7526 		if ( $.blockUI ) {
   7527 			$.blockUI( this.dpDiv );
   7528 		}
   7529 		$.data( this._dialogInput[ 0 ], "datepicker", inst );
   7530 		return this;
   7531 	},
   7532 
   7533 	/* Detach a datepicker from its control.
   7534 	 * @param  target	element - the target input field or division or span
   7535 	 */
   7536 	_destroyDatepicker: function( target ) {
   7537 		var nodeName,
   7538 			$target = $( target ),
   7539 			inst = $.data( target, "datepicker" );
   7540 
   7541 		if ( !$target.hasClass( this.markerClassName ) ) {
   7542 			return;
   7543 		}
   7544 
   7545 		nodeName = target.nodeName.toLowerCase();
   7546 		$.removeData( target, "datepicker" );
   7547 		if ( nodeName === "input" ) {
   7548 			inst.append.remove();
   7549 			inst.trigger.remove();
   7550 			$target.removeClass( this.markerClassName ).
   7551 				off( "focus", this._showDatepicker ).
   7552 				off( "keydown", this._doKeyDown ).
   7553 				off( "keypress", this._doKeyPress ).
   7554 				off( "keyup", this._doKeyUp );
   7555 		} else if ( nodeName === "div" || nodeName === "span" ) {
   7556 			$target.removeClass( this.markerClassName ).empty();
   7557 		}
   7558 
   7559 		if ( datepicker_instActive === inst ) {
   7560 			datepicker_instActive = null;
   7561 		}
   7562 	},
   7563 
   7564 	/* Enable the date picker to a jQuery selection.
   7565 	 * @param  target	element - the target input field or division or span
   7566 	 */
   7567 	_enableDatepicker: function( target ) {
   7568 		var nodeName, inline,
   7569 			$target = $( target ),
   7570 			inst = $.data( target, "datepicker" );
   7571 
   7572 		if ( !$target.hasClass( this.markerClassName ) ) {
   7573 			return;
   7574 		}
   7575 
   7576 		nodeName = target.nodeName.toLowerCase();
   7577 		if ( nodeName === "input" ) {
   7578 			target.disabled = false;
   7579 			inst.trigger.filter( "button" ).
   7580 				each( function() { this.disabled = false; } ).end().
   7581 				filter( "img" ).css( { opacity: "1.0", cursor: "" } );
   7582 		} else if ( nodeName === "div" || nodeName === "span" ) {
   7583 			inline = $target.children( "." + this._inlineClass );
   7584 			inline.children().removeClass( "ui-state-disabled" );
   7585 			inline.find( "select.ui-datepicker-month, select.ui-datepicker-year" ).
   7586 				prop( "disabled", false );
   7587 		}
   7588 		this._disabledInputs = $.map( this._disabledInputs,
   7589 			function( value ) { return ( value === target ? null : value ); } ); // delete entry
   7590 	},
   7591 
   7592 	/* Disable the date picker to a jQuery selection.
   7593 	 * @param  target	element - the target input field or division or span
   7594 	 */
   7595 	_disableDatepicker: function( target ) {
   7596 		var nodeName, inline,
   7597 			$target = $( target ),
   7598 			inst = $.data( target, "datepicker" );
   7599 
   7600 		if ( !$target.hasClass( this.markerClassName ) ) {
   7601 			return;
   7602 		}
   7603 
   7604 		nodeName = target.nodeName.toLowerCase();
   7605 		if ( nodeName === "input" ) {
   7606 			target.disabled = true;
   7607 			inst.trigger.filter( "button" ).
   7608 				each( function() { this.disabled = true; } ).end().
   7609 				filter( "img" ).css( { opacity: "0.5", cursor: "default" } );
   7610 		} else if ( nodeName === "div" || nodeName === "span" ) {
   7611 			inline = $target.children( "." + this._inlineClass );
   7612 			inline.children().addClass( "ui-state-disabled" );
   7613 			inline.find( "select.ui-datepicker-month, select.ui-datepicker-year" ).
   7614 				prop( "disabled", true );
   7615 		}
   7616 		this._disabledInputs = $.map( this._disabledInputs,
   7617 			function( value ) { return ( value === target ? null : value ); } ); // delete entry
   7618 		this._disabledInputs[ this._disabledInputs.length ] = target;
   7619 	},
   7620 
   7621 	/* Is the first field in a jQuery collection disabled as a datepicker?
   7622 	 * @param  target	element - the target input field or division or span
   7623 	 * @return boolean - true if disabled, false if enabled
   7624 	 */
   7625 	_isDisabledDatepicker: function( target ) {
   7626 		if ( !target ) {
   7627 			return false;
   7628 		}
   7629 		for ( var i = 0; i < this._disabledInputs.length; i++ ) {
   7630 			if ( this._disabledInputs[ i ] === target ) {
   7631 				return true;
   7632 			}
   7633 		}
   7634 		return false;
   7635 	},
   7636 
   7637 	/* Retrieve the instance data for the target control.
   7638 	 * @param  target  element - the target input field or division or span
   7639 	 * @return  object - the associated instance data
   7640 	 * @throws  error if a jQuery problem getting data
   7641 	 */
   7642 	_getInst: function( target ) {
   7643 		try {
   7644 			return $.data( target, "datepicker" );
   7645 		}
   7646 		catch ( err ) {
   7647 			throw "Missing instance data for this datepicker";
   7648 		}
   7649 	},
   7650 
   7651 	/* Update or retrieve the settings for a date picker attached to an input field or division.
   7652 	 * @param  target  element - the target input field or division or span
   7653 	 * @param  name	object - the new settings to update or
   7654 	 *				string - the name of the setting to change or retrieve,
   7655 	 *				when retrieving also "all" for all instance settings or
   7656 	 *				"defaults" for all global defaults
   7657 	 * @param  value   any - the new value for the setting
   7658 	 *				(omit if above is an object or to retrieve a value)
   7659 	 */
   7660 	_optionDatepicker: function( target, name, value ) {
   7661 		var settings, date, minDate, maxDate,
   7662 			inst = this._getInst( target );
   7663 
   7664 		if ( arguments.length === 2 && typeof name === "string" ) {
   7665 			return ( name === "defaults" ? $.extend( {}, $.datepicker._defaults ) :
   7666 				( inst ? ( name === "all" ? $.extend( {}, inst.settings ) :
   7667 				this._get( inst, name ) ) : null ) );
   7668 		}
   7669 
   7670 		settings = name || {};
   7671 		if ( typeof name === "string" ) {
   7672 			settings = {};
   7673 			settings[ name ] = value;
   7674 		}
   7675 
   7676 		if ( inst ) {
   7677 			if ( this._curInst === inst ) {
   7678 				this._hideDatepicker();
   7679 			}
   7680 
   7681 			date = this._getDateDatepicker( target, true );
   7682 			minDate = this._getMinMaxDate( inst, "min" );
   7683 			maxDate = this._getMinMaxDate( inst, "max" );
   7684 			datepicker_extendRemove( inst.settings, settings );
   7685 
   7686 			// reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
   7687 			if ( minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined ) {
   7688 				inst.settings.minDate = this._formatDate( inst, minDate );
   7689 			}
   7690 			if ( maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined ) {
   7691 				inst.settings.maxDate = this._formatDate( inst, maxDate );
   7692 			}
   7693 			if ( "disabled" in settings ) {
   7694 				if ( settings.disabled ) {
   7695 					this._disableDatepicker( target );
   7696 				} else {
   7697 					this._enableDatepicker( target );
   7698 				}
   7699 			}
   7700 			this._attachments( $( target ), inst );
   7701 			this._autoSize( inst );
   7702 			this._setDate( inst, date );
   7703 			this._updateAlternate( inst );
   7704 			this._updateDatepicker( inst );
   7705 		}
   7706 	},
   7707 
   7708 	// Change method deprecated
   7709 	_changeDatepicker: function( target, name, value ) {
   7710 		this._optionDatepicker( target, name, value );
   7711 	},
   7712 
   7713 	/* Redraw the date picker attached to an input field or division.
   7714 	 * @param  target  element - the target input field or division or span
   7715 	 */
   7716 	_refreshDatepicker: function( target ) {
   7717 		var inst = this._getInst( target );
   7718 		if ( inst ) {
   7719 			this._updateDatepicker( inst );
   7720 		}
   7721 	},
   7722 
   7723 	/* Set the dates for a jQuery selection.
   7724 	 * @param  target element - the target input field or division or span
   7725 	 * @param  date	Date - the new date
   7726 	 */
   7727 	_setDateDatepicker: function( target, date ) {
   7728 		var inst = this._getInst( target );
   7729 		if ( inst ) {
   7730 			this._setDate( inst, date );
   7731 			this._updateDatepicker( inst );
   7732 			this._updateAlternate( inst );
   7733 		}
   7734 	},
   7735 
   7736 	/* Get the date(s) for the first entry in a jQuery selection.
   7737 	 * @param  target element - the target input field or division or span
   7738 	 * @param  noDefault boolean - true if no default date is to be used
   7739 	 * @return Date - the current date
   7740 	 */
   7741 	_getDateDatepicker: function( target, noDefault ) {
   7742 		var inst = this._getInst( target );
   7743 		if ( inst && !inst.inline ) {
   7744 			this._setDateFromField( inst, noDefault );
   7745 		}
   7746 		return ( inst ? this._getDate( inst ) : null );
   7747 	},
   7748 
   7749 	/* Handle keystrokes. */
   7750 	_doKeyDown: function( event ) {
   7751 		var onSelect, dateStr, sel,
   7752 			inst = $.datepicker._getInst( event.target ),
   7753 			handled = true,
   7754 			isRTL = inst.dpDiv.is( ".ui-datepicker-rtl" );
   7755 
   7756 		inst._keyEvent = true;
   7757 		if ( $.datepicker._datepickerShowing ) {
   7758 			switch ( event.keyCode ) {
   7759 				case 9: $.datepicker._hideDatepicker();
   7760 						handled = false;
   7761 						break; // hide on tab out
   7762 				case 13: sel = $( "td." + $.datepicker._dayOverClass + ":not(." +
   7763 									$.datepicker._currentClass + ")", inst.dpDiv );
   7764 						if ( sel[ 0 ] ) {
   7765 							$.datepicker._selectDay( event.target, inst.selectedMonth, inst.selectedYear, sel[ 0 ] );
   7766 						}
   7767 
   7768 						onSelect = $.datepicker._get( inst, "onSelect" );
   7769 						if ( onSelect ) {
   7770 							dateStr = $.datepicker._formatDate( inst );
   7771 
   7772 							// Trigger custom callback
   7773 							onSelect.apply( ( inst.input ? inst.input[ 0 ] : null ), [ dateStr, inst ] );
   7774 						} else {
   7775 							$.datepicker._hideDatepicker();
   7776 						}
   7777 
   7778 						return false; // don't submit the form
   7779 				case 27: $.datepicker._hideDatepicker();
   7780 						break; // hide on escape
   7781 				case 33: $.datepicker._adjustDate( event.target, ( event.ctrlKey ?
   7782 							-$.datepicker._get( inst, "stepBigMonths" ) :
   7783 							-$.datepicker._get( inst, "stepMonths" ) ), "M" );
   7784 						break; // previous month/year on page up/+ ctrl
   7785 				case 34: $.datepicker._adjustDate( event.target, ( event.ctrlKey ?
   7786 							+$.datepicker._get( inst, "stepBigMonths" ) :
   7787 							+$.datepicker._get( inst, "stepMonths" ) ), "M" );
   7788 						break; // next month/year on page down/+ ctrl
   7789 				case 35: if ( event.ctrlKey || event.metaKey ) {
   7790 							$.datepicker._clearDate( event.target );
   7791 						}
   7792 						handled = event.ctrlKey || event.metaKey;
   7793 						break; // clear on ctrl or command +end
   7794 				case 36: if ( event.ctrlKey || event.metaKey ) {
   7795 							$.datepicker._gotoToday( event.target );
   7796 						}
   7797 						handled = event.ctrlKey || event.metaKey;
   7798 						break; // current on ctrl or command +home
   7799 				case 37: if ( event.ctrlKey || event.metaKey ) {
   7800 							$.datepicker._adjustDate( event.target, ( isRTL ? +1 : -1 ), "D" );
   7801 						}
   7802 						handled = event.ctrlKey || event.metaKey;
   7803 
   7804 						// -1 day on ctrl or command +left
   7805 						if ( event.originalEvent.altKey ) {
   7806 							$.datepicker._adjustDate( event.target, ( event.ctrlKey ?
   7807 								-$.datepicker._get( inst, "stepBigMonths" ) :
   7808 								-$.datepicker._get( inst, "stepMonths" ) ), "M" );
   7809 						}
   7810 
   7811 						// next month/year on alt +left on Mac
   7812 						break;
   7813 				case 38: if ( event.ctrlKey || event.metaKey ) {
   7814 							$.datepicker._adjustDate( event.target, -7, "D" );
   7815 						}
   7816 						handled = event.ctrlKey || event.metaKey;
   7817 						break; // -1 week on ctrl or command +up
   7818 				case 39: if ( event.ctrlKey || event.metaKey ) {
   7819 							$.datepicker._adjustDate( event.target, ( isRTL ? -1 : +1 ), "D" );
   7820 						}
   7821 						handled = event.ctrlKey || event.metaKey;
   7822 
   7823 						// +1 day on ctrl or command +right
   7824 						if ( event.originalEvent.altKey ) {
   7825 							$.datepicker._adjustDate( event.target, ( event.ctrlKey ?
   7826 								+$.datepicker._get( inst, "stepBigMonths" ) :
   7827 								+$.datepicker._get( inst, "stepMonths" ) ), "M" );
   7828 						}
   7829 
   7830 						// next month/year on alt +right
   7831 						break;
   7832 				case 40: if ( event.ctrlKey || event.metaKey ) {
   7833 							$.datepicker._adjustDate( event.target, +7, "D" );
   7834 						}
   7835 						handled = event.ctrlKey || event.metaKey;
   7836 						break; // +1 week on ctrl or command +down
   7837 				default: handled = false;
   7838 			}
   7839 		} else if ( event.keyCode === 36 && event.ctrlKey ) { // display the date picker on ctrl+home
   7840 			$.datepicker._showDatepicker( this );
   7841 		} else {
   7842 			handled = false;
   7843 		}
   7844 
   7845 		if ( handled ) {
   7846 			event.preventDefault();
   7847 			event.stopPropagation();
   7848 		}
   7849 	},
   7850 
   7851 	/* Filter entered characters - based on date format. */
   7852 	_doKeyPress: function( event ) {
   7853 		var chars, chr,
   7854 			inst = $.datepicker._getInst( event.target );
   7855 
   7856 		if ( $.datepicker._get( inst, "constrainInput" ) ) {
   7857 			chars = $.datepicker._possibleChars( $.datepicker._get( inst, "dateFormat" ) );
   7858 			chr = String.fromCharCode( event.charCode == null ? event.keyCode : event.charCode );
   7859 			return event.ctrlKey || event.metaKey || ( chr < " " || !chars || chars.indexOf( chr ) > -1 );
   7860 		}
   7861 	},
   7862 
   7863 	/* Synchronise manual entry and field/alternate field. */
   7864 	_doKeyUp: function( event ) {
   7865 		var date,
   7866 			inst = $.datepicker._getInst( event.target );
   7867 
   7868 		if ( inst.input.val() !== inst.lastVal ) {
   7869 			try {
   7870 				date = $.datepicker.parseDate( $.datepicker._get( inst, "dateFormat" ),
   7871 					( inst.input ? inst.input.val() : null ),
   7872 					$.datepicker._getFormatConfig( inst ) );
   7873 
   7874 				if ( date ) { // only if valid
   7875 					$.datepicker._setDateFromField( inst );
   7876 					$.datepicker._updateAlternate( inst );
   7877 					$.datepicker._updateDatepicker( inst );
   7878 				}
   7879 			}
   7880 			catch ( err ) {
   7881 			}
   7882 		}
   7883 		return true;
   7884 	},
   7885 
   7886 	/* Pop-up the date picker for a given input field.
   7887 	 * If false returned from beforeShow event handler do not show.
   7888 	 * @param  input  element - the input field attached to the date picker or
   7889 	 *					event - if triggered by focus
   7890 	 */
   7891 	_showDatepicker: function( input ) {
   7892 		input = input.target || input;
   7893 		if ( input.nodeName.toLowerCase() !== "input" ) { // find from button/image trigger
   7894 			input = $( "input", input.parentNode )[ 0 ];
   7895 		}
   7896 
   7897 		if ( $.datepicker._isDisabledDatepicker( input ) || $.datepicker._lastInput === input ) { // already here
   7898 			return;
   7899 		}
   7900 
   7901 		var inst, beforeShow, beforeShowSettings, isFixed,
   7902 			offset, showAnim, duration;
   7903 
   7904 		inst = $.datepicker._getInst( input );
   7905 		if ( $.datepicker._curInst && $.datepicker._curInst !== inst ) {
   7906 			$.datepicker._curInst.dpDiv.stop( true, true );
   7907 			if ( inst && $.datepicker._datepickerShowing ) {
   7908 				$.datepicker._hideDatepicker( $.datepicker._curInst.input[ 0 ] );
   7909 			}
   7910 		}
   7911 
   7912 		beforeShow = $.datepicker._get( inst, "beforeShow" );
   7913 		beforeShowSettings = beforeShow ? beforeShow.apply( input, [ input, inst ] ) : {};
   7914 		if ( beforeShowSettings === false ) {
   7915 			return;
   7916 		}
   7917 		datepicker_extendRemove( inst.settings, beforeShowSettings );
   7918 
   7919 		inst.lastVal = null;
   7920 		$.datepicker._lastInput = input;
   7921 		$.datepicker._setDateFromField( inst );
   7922 
   7923 		if ( $.datepicker._inDialog ) { // hide cursor
   7924 			input.value = "";
   7925 		}
   7926 		if ( !$.datepicker._pos ) { // position below input
   7927 			$.datepicker._pos = $.datepicker._findPos( input );
   7928 			$.datepicker._pos[ 1 ] += input.offsetHeight; // add the height
   7929 		}
   7930 
   7931 		isFixed = false;
   7932 		$( input ).parents().each( function() {
   7933 			isFixed |= $( this ).css( "position" ) === "fixed";
   7934 			return !isFixed;
   7935 		} );
   7936 
   7937 		offset = { left: $.datepicker._pos[ 0 ], top: $.datepicker._pos[ 1 ] };
   7938 		$.datepicker._pos = null;
   7939 
   7940 		//to avoid flashes on Firefox
   7941 		inst.dpDiv.empty();
   7942 
   7943 		// determine sizing offscreen
   7944 		inst.dpDiv.css( { position: "absolute", display: "block", top: "-1000px" } );
   7945 		$.datepicker._updateDatepicker( inst );
   7946 
   7947 		// fix width for dynamic number of date pickers
   7948 		// and adjust position before showing
   7949 		offset = $.datepicker._checkOffset( inst, offset, isFixed );
   7950 		inst.dpDiv.css( { position: ( $.datepicker._inDialog && $.blockUI ?
   7951 			"static" : ( isFixed ? "fixed" : "absolute" ) ), display: "none",
   7952 			left: offset.left + "px", top: offset.top + "px" } );
   7953 
   7954 		if ( !inst.inline ) {
   7955 			showAnim = $.datepicker._get( inst, "showAnim" );
   7956 			duration = $.datepicker._get( inst, "duration" );
   7957 			inst.dpDiv.css( "z-index", datepicker_getZindex( $( input ) ) + 1 );
   7958 			$.datepicker._datepickerShowing = true;
   7959 
   7960 			if ( $.effects && $.effects.effect[ showAnim ] ) {
   7961 				inst.dpDiv.show( showAnim, $.datepicker._get( inst, "showOptions" ), duration );
   7962 			} else {
   7963 				inst.dpDiv[ showAnim || "show" ]( showAnim ? duration : null );
   7964 			}
   7965 
   7966 			if ( $.datepicker._shouldFocusInput( inst ) ) {
   7967 				inst.input.trigger( "focus" );
   7968 			}
   7969 
   7970 			$.datepicker._curInst = inst;
   7971 		}
   7972 	},
   7973 
   7974 	/* Generate the date picker content. */
   7975 	_updateDatepicker: function( inst ) {
   7976 		this.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
   7977 		datepicker_instActive = inst; // for delegate hover events
   7978 		inst.dpDiv.empty().append( this._generateHTML( inst ) );
   7979 		this._attachHandlers( inst );
   7980 
   7981 		var origyearshtml,
   7982 			numMonths = this._getNumberOfMonths( inst ),
   7983 			cols = numMonths[ 1 ],
   7984 			width = 17,
   7985 			activeCell = inst.dpDiv.find( "." + this._dayOverClass + " a" );
   7986 
   7987 		if ( activeCell.length > 0 ) {
   7988 			datepicker_handleMouseover.apply( activeCell.get( 0 ) );
   7989 		}
   7990 
   7991 		inst.dpDiv.removeClass( "ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4" ).width( "" );
   7992 		if ( cols > 1 ) {
   7993 			inst.dpDiv.addClass( "ui-datepicker-multi-" + cols ).css( "width", ( width * cols ) + "em" );
   7994 		}
   7995 		inst.dpDiv[ ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ? "add" : "remove" ) +
   7996 			"Class" ]( "ui-datepicker-multi" );
   7997 		inst.dpDiv[ ( this._get( inst, "isRTL" ) ? "add" : "remove" ) +
   7998 			"Class" ]( "ui-datepicker-rtl" );
   7999 
   8000 		if ( inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) {
   8001 			inst.input.trigger( "focus" );
   8002 		}
   8003 
   8004 		// Deffered render of the years select (to avoid flashes on Firefox)
   8005 		if ( inst.yearshtml ) {
   8006 			origyearshtml = inst.yearshtml;
   8007 			setTimeout( function() {
   8008 
   8009 				//assure that inst.yearshtml didn't change.
   8010 				if ( origyearshtml === inst.yearshtml && inst.yearshtml ) {
   8011 					inst.dpDiv.find( "select.ui-datepicker-year:first" ).replaceWith( inst.yearshtml );
   8012 				}
   8013 				origyearshtml = inst.yearshtml = null;
   8014 			}, 0 );
   8015 		}
   8016 	},
   8017 
   8018 	// #6694 - don't focus the input if it's already focused
   8019 	// this breaks the change event in IE
   8020 	// Support: IE and jQuery <1.9
   8021 	_shouldFocusInput: function( inst ) {
   8022 		return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" ) && !inst.input.is( ":focus" );
   8023 	},
   8024 
   8025 	/* Check positioning to remain on screen. */
   8026 	_checkOffset: function( inst, offset, isFixed ) {
   8027 		var dpWidth = inst.dpDiv.outerWidth(),
   8028 			dpHeight = inst.dpDiv.outerHeight(),
   8029 			inputWidth = inst.input ? inst.input.outerWidth() : 0,
   8030 			inputHeight = inst.input ? inst.input.outerHeight() : 0,
   8031 			viewWidth = document.documentElement.clientWidth + ( isFixed ? 0 : $( document ).scrollLeft() ),
   8032 			viewHeight = document.documentElement.clientHeight + ( isFixed ? 0 : $( document ).scrollTop() );
   8033 
   8034 		offset.left -= ( this._get( inst, "isRTL" ) ? ( dpWidth - inputWidth ) : 0 );
   8035 		offset.left -= ( isFixed && offset.left === inst.input.offset().left ) ? $( document ).scrollLeft() : 0;
   8036 		offset.top -= ( isFixed && offset.top === ( inst.input.offset().top + inputHeight ) ) ? $( document ).scrollTop() : 0;
   8037 
   8038 		// Now check if datepicker is showing outside window viewport - move to a better place if so.
   8039 		offset.left -= Math.min( offset.left, ( offset.left + dpWidth > viewWidth && viewWidth > dpWidth ) ?
   8040 			Math.abs( offset.left + dpWidth - viewWidth ) : 0 );
   8041 		offset.top -= Math.min( offset.top, ( offset.top + dpHeight > viewHeight && viewHeight > dpHeight ) ?
   8042 			Math.abs( dpHeight + inputHeight ) : 0 );
   8043 
   8044 		return offset;
   8045 	},
   8046 
   8047 	/* Find an object's position on the screen. */
   8048 	_findPos: function( obj ) {
   8049 		var position,
   8050 			inst = this._getInst( obj ),
   8051 			isRTL = this._get( inst, "isRTL" );
   8052 
   8053 		while ( obj && ( obj.type === "hidden" || obj.nodeType !== 1 || $.expr.filters.hidden( obj ) ) ) {
   8054 			obj = obj[ isRTL ? "previousSibling" : "nextSibling" ];
   8055 		}
   8056 
   8057 		position = $( obj ).offset();
   8058 		return [ position.left, position.top ];
   8059 	},
   8060 
   8061 	/* Hide the date picker from view.
   8062 	 * @param  input  element - the input field attached to the date picker
   8063 	 */
   8064 	_hideDatepicker: function( input ) {
   8065 		var showAnim, duration, postProcess, onClose,
   8066 			inst = this._curInst;
   8067 
   8068 		if ( !inst || ( input && inst !== $.data( input, "datepicker" ) ) ) {
   8069 			return;
   8070 		}
   8071 
   8072 		if ( this._datepickerShowing ) {
   8073 			showAnim = this._get( inst, "showAnim" );
   8074 			duration = this._get( inst, "duration" );
   8075 			postProcess = function() {
   8076 				$.datepicker._tidyDialog( inst );
   8077 			};
   8078 
   8079 			// DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed
   8080 			if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) {
   8081 				inst.dpDiv.hide( showAnim, $.datepicker._get( inst, "showOptions" ), duration, postProcess );
   8082 			} else {
   8083 				inst.dpDiv[ ( showAnim === "slideDown" ? "slideUp" :
   8084 					( showAnim === "fadeIn" ? "fadeOut" : "hide" ) ) ]( ( showAnim ? duration : null ), postProcess );
   8085 			}
   8086 
   8087 			if ( !showAnim ) {
   8088 				postProcess();
   8089 			}
   8090 			this._datepickerShowing = false;
   8091 
   8092 			onClose = this._get( inst, "onClose" );
   8093 			if ( onClose ) {
   8094 				onClose.apply( ( inst.input ? inst.input[ 0 ] : null ), [ ( inst.input ? inst.input.val() : "" ), inst ] );
   8095 			}
   8096 
   8097 			this._lastInput = null;
   8098 			if ( this._inDialog ) {
   8099 				this._dialogInput.css( { position: "absolute", left: "0", top: "-100px" } );
   8100 				if ( $.blockUI ) {
   8101 					$.unblockUI();
   8102 					$( "body" ).append( this.dpDiv );
   8103 				}
   8104 			}
   8105 			this._inDialog = false;
   8106 		}
   8107 	},
   8108 
   8109 	/* Tidy up after a dialog display. */
   8110 	_tidyDialog: function( inst ) {
   8111 		inst.dpDiv.removeClass( this._dialogClass ).off( ".ui-datepicker-calendar" );
   8112 	},
   8113 
   8114 	/* Close date picker if clicked elsewhere. */
   8115 	_checkExternalClick: function( event ) {
   8116 		if ( !$.datepicker._curInst ) {
   8117 			return;
   8118 		}
   8119 
   8120 		var $target = $( event.target ),
   8121 			inst = $.datepicker._getInst( $target[ 0 ] );
   8122 
   8123 		if ( ( ( $target[ 0 ].id !== $.datepicker._mainDivId &&
   8124 				$target.parents( "#" + $.datepicker._mainDivId ).length === 0 &&
   8125 				!$target.hasClass( $.datepicker.markerClassName ) &&
   8126 				!$target.closest( "." + $.datepicker._triggerClass ).length &&
   8127 				$.datepicker._datepickerShowing && !( $.datepicker._inDialog && $.blockUI ) ) ) ||
   8128 			( $target.hasClass( $.datepicker.markerClassName ) && $.datepicker._curInst !== inst ) ) {
   8129 				$.datepicker._hideDatepicker();
   8130 		}
   8131 	},
   8132 
   8133 	/* Adjust one of the date sub-fields. */
   8134 	_adjustDate: function( id, offset, period ) {
   8135 		var target = $( id ),
   8136 			inst = this._getInst( target[ 0 ] );
   8137 
   8138 		if ( this._isDisabledDatepicker( target[ 0 ] ) ) {
   8139 			return;
   8140 		}
   8141 		this._adjustInstDate( inst, offset +
   8142 			( period === "M" ? this._get( inst, "showCurrentAtPos" ) : 0 ), // undo positioning
   8143 			period );
   8144 		this._updateDatepicker( inst );
   8145 	},
   8146 
   8147 	/* Action for current link. */
   8148 	_gotoToday: function( id ) {
   8149 		var date,
   8150 			target = $( id ),
   8151 			inst = this._getInst( target[ 0 ] );
   8152 
   8153 		if ( this._get( inst, "gotoCurrent" ) && inst.currentDay ) {
   8154 			inst.selectedDay = inst.currentDay;
   8155 			inst.drawMonth = inst.selectedMonth = inst.currentMonth;
   8156 			inst.drawYear = inst.selectedYear = inst.currentYear;
   8157 		} else {
   8158 			date = new Date();
   8159 			inst.selectedDay = date.getDate();
   8160 			inst.drawMonth = inst.selectedMonth = date.getMonth();
   8161 			inst.drawYear = inst.selectedYear = date.getFullYear();
   8162 		}
   8163 		this._notifyChange( inst );
   8164 		this._adjustDate( target );
   8165 	},
   8166 
   8167 	/* Action for selecting a new month/year. */
   8168 	_selectMonthYear: function( id, select, period ) {
   8169 		var target = $( id ),
   8170 			inst = this._getInst( target[ 0 ] );
   8171 
   8172 		inst[ "selected" + ( period === "M" ? "Month" : "Year" ) ] =
   8173 		inst[ "draw" + ( period === "M" ? "Month" : "Year" ) ] =
   8174 			parseInt( select.options[ select.selectedIndex ].value, 10 );
   8175 
   8176 		this._notifyChange( inst );
   8177 		this._adjustDate( target );
   8178 	},
   8179 
   8180 	/* Action for selecting a day. */
   8181 	_selectDay: function( id, month, year, td ) {
   8182 		var inst,
   8183 			target = $( id );
   8184 
   8185 		if ( $( td ).hasClass( this._unselectableClass ) || this._isDisabledDatepicker( target[ 0 ] ) ) {
   8186 			return;
   8187 		}
   8188 
   8189 		inst = this._getInst( target[ 0 ] );
   8190 		inst.selectedDay = inst.currentDay = $( "a", td ).html();
   8191 		inst.selectedMonth = inst.currentMonth = month;
   8192 		inst.selectedYear = inst.currentYear = year;
   8193 		this._selectDate( id, this._formatDate( inst,
   8194 			inst.currentDay, inst.currentMonth, inst.currentYear ) );
   8195 	},
   8196 
   8197 	/* Erase the input field and hide the date picker. */
   8198 	_clearDate: function( id ) {
   8199 		var target = $( id );
   8200 		this._selectDate( target, "" );
   8201 	},
   8202 
   8203 	/* Update the input field with the selected date. */
   8204 	_selectDate: function( id, dateStr ) {
   8205 		var onSelect,
   8206 			target = $( id ),
   8207 			inst = this._getInst( target[ 0 ] );
   8208 
   8209 		dateStr = ( dateStr != null ? dateStr : this._formatDate( inst ) );
   8210 		if ( inst.input ) {
   8211 			inst.input.val( dateStr );
   8212 		}
   8213 		this._updateAlternate( inst );
   8214 
   8215 		onSelect = this._get( inst, "onSelect" );
   8216 		if ( onSelect ) {
   8217 			onSelect.apply( ( inst.input ? inst.input[ 0 ] : null ), [ dateStr, inst ] );  // trigger custom callback
   8218 		} else if ( inst.input ) {
   8219 			inst.input.trigger( "change" ); // fire the change event
   8220 		}
   8221 
   8222 		if ( inst.inline ) {
   8223 			this._updateDatepicker( inst );
   8224 		} else {
   8225 			this._hideDatepicker();
   8226 			this._lastInput = inst.input[ 0 ];
   8227 			if ( typeof( inst.input[ 0 ] ) !== "object" ) {
   8228 				inst.input.trigger( "focus" ); // restore focus
   8229 			}
   8230 			this._lastInput = null;
   8231 		}
   8232 	},
   8233 
   8234 	/* Update any alternate field to synchronise with the main field. */
   8235 	_updateAlternate: function( inst ) {
   8236 		var altFormat, date, dateStr,
   8237 			altField = this._get( inst, "altField" );
   8238 
   8239 		if ( altField ) { // update alternate field too
   8240 			altFormat = this._get( inst, "altFormat" ) || this._get( inst, "dateFormat" );
   8241 			date = this._getDate( inst );
   8242 			dateStr = this.formatDate( altFormat, date, this._getFormatConfig( inst ) );
   8243 			$( altField ).val( dateStr );
   8244 		}
   8245 	},
   8246 
   8247 	/* Set as beforeShowDay function to prevent selection of weekends.
   8248 	 * @param  date  Date - the date to customise
   8249 	 * @return [boolean, string] - is this date selectable?, what is its CSS class?
   8250 	 */
   8251 	noWeekends: function( date ) {
   8252 		var day = date.getDay();
   8253 		return [ ( day > 0 && day < 6 ), "" ];
   8254 	},
   8255 
   8256 	/* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
   8257 	 * @param  date  Date - the date to get the week for
   8258 	 * @return  number - the number of the week within the year that contains this date
   8259 	 */
   8260 	iso8601Week: function( date ) {
   8261 		var time,
   8262 			checkDate = new Date( date.getTime() );
   8263 
   8264 		// Find Thursday of this week starting on Monday
   8265 		checkDate.setDate( checkDate.getDate() + 4 - ( checkDate.getDay() || 7 ) );
   8266 
   8267 		time = checkDate.getTime();
   8268 		checkDate.setMonth( 0 ); // Compare with Jan 1
   8269 		checkDate.setDate( 1 );
   8270 		return Math.floor( Math.round( ( time - checkDate ) / 86400000 ) / 7 ) + 1;
   8271 	},
   8272 
   8273 	/* Parse a string value into a date object.
   8274 	 * See formatDate below for the possible formats.
   8275 	 *
   8276 	 * @param  format string - the expected format of the date
   8277 	 * @param  value string - the date in the above format
   8278 	 * @param  settings Object - attributes include:
   8279 	 *					shortYearCutoff  number - the cutoff year for determining the century (optional)
   8280 	 *					dayNamesShort	string[7] - abbreviated names of the days from Sunday (optional)
   8281 	 *					dayNames		string[7] - names of the days from Sunday (optional)
   8282 	 *					monthNamesShort string[12] - abbreviated names of the months (optional)
   8283 	 *					monthNames		string[12] - names of the months (optional)
   8284 	 * @return  Date - the extracted date value or null if value is blank
   8285 	 */
   8286 	parseDate: function( format, value, settings ) {
   8287 		if ( format == null || value == null ) {
   8288 			throw "Invalid arguments";
   8289 		}
   8290 
   8291 		value = ( typeof value === "object" ? value.toString() : value + "" );
   8292 		if ( value === "" ) {
   8293 			return null;
   8294 		}
   8295 
   8296 		var iFormat, dim, extra,
   8297 			iValue = 0,
   8298 			shortYearCutoffTemp = ( settings ? settings.shortYearCutoff : null ) || this._defaults.shortYearCutoff,
   8299 			shortYearCutoff = ( typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp :
   8300 				new Date().getFullYear() % 100 + parseInt( shortYearCutoffTemp, 10 ) ),
   8301 			dayNamesShort = ( settings ? settings.dayNamesShort : null ) || this._defaults.dayNamesShort,
   8302 			dayNames = ( settings ? settings.dayNames : null ) || this._defaults.dayNames,
   8303 			monthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort,
   8304 			monthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames,
   8305 			year = -1,
   8306 			month = -1,
   8307 			day = -1,
   8308 			doy = -1,
   8309 			literal = false,
   8310 			date,
   8311 
   8312 			// Check whether a format character is doubled
   8313 			lookAhead = function( match ) {
   8314 				var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );
   8315 				if ( matches ) {
   8316 					iFormat++;
   8317 				}
   8318 				return matches;
   8319 			},
   8320 
   8321 			// Extract a number from the string value
   8322 			getNumber = function( match ) {
   8323 				var isDoubled = lookAhead( match ),
   8324 					size = ( match === "@" ? 14 : ( match === "!" ? 20 :
   8325 					( match === "y" && isDoubled ? 4 : ( match === "o" ? 3 : 2 ) ) ) ),
   8326 					minSize = ( match === "y" ? size : 1 ),
   8327 					digits = new RegExp( "^\\d{" + minSize + "," + size + "}" ),
   8328 					num = value.substring( iValue ).match( digits );
   8329 				if ( !num ) {
   8330 					throw "Missing number at position " + iValue;
   8331 				}
   8332 				iValue += num[ 0 ].length;
   8333 				return parseInt( num[ 0 ], 10 );
   8334 			},
   8335 
   8336 			// Extract a name from the string value and convert to an index
   8337 			getName = function( match, shortNames, longNames ) {
   8338 				var index = -1,
   8339 					names = $.map( lookAhead( match ) ? longNames : shortNames, function( v, k ) {
   8340 						return [ [ k, v ] ];
   8341 					} ).sort( function( a, b ) {
   8342 						return -( a[ 1 ].length - b[ 1 ].length );
   8343 					} );
   8344 
   8345 				$.each( names, function( i, pair ) {
   8346 					var name = pair[ 1 ];
   8347 					if ( value.substr( iValue, name.length ).toLowerCase() === name.toLowerCase() ) {
   8348 						index = pair[ 0 ];
   8349 						iValue += name.length;
   8350 						return false;
   8351 					}
   8352 				} );
   8353 				if ( index !== -1 ) {
   8354 					return index + 1;
   8355 				} else {
   8356 					throw "Unknown name at position " + iValue;
   8357 				}
   8358 			},
   8359 
   8360 			// Confirm that a literal character matches the string value
   8361 			checkLiteral = function() {
   8362 				if ( value.charAt( iValue ) !== format.charAt( iFormat ) ) {
   8363 					throw "Unexpected literal at position " + iValue;
   8364 				}
   8365 				iValue++;
   8366 			};
   8367 
   8368 		for ( iFormat = 0; iFormat < format.length; iFormat++ ) {
   8369 			if ( literal ) {
   8370 				if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) {
   8371 					literal = false;
   8372 				} else {
   8373 					checkLiteral();
   8374 				}
   8375 			} else {
   8376 				switch ( format.charAt( iFormat ) ) {
   8377 					case "d":
   8378 						day = getNumber( "d" );
   8379 						break;
   8380 					case "D":
   8381 						getName( "D", dayNamesShort, dayNames );
   8382 						break;
   8383 					case "o":
   8384 						doy = getNumber( "o" );
   8385 						break;
   8386 					case "m":
   8387 						month = getNumber( "m" );
   8388 						break;
   8389 					case "M":
   8390 						month = getName( "M", monthNamesShort, monthNames );
   8391 						break;
   8392 					case "y":
   8393 						year = getNumber( "y" );
   8394 						break;
   8395 					case "@":
   8396 						date = new Date( getNumber( "@" ) );
   8397 						year = date.getFullYear();
   8398 						month = date.getMonth() + 1;
   8399 						day = date.getDate();
   8400 						break;
   8401 					case "!":
   8402 						date = new Date( ( getNumber( "!" ) - this._ticksTo1970 ) / 10000 );
   8403 						year = date.getFullYear();
   8404 						month = date.getMonth() + 1;
   8405 						day = date.getDate();
   8406 						break;
   8407 					case "'":
   8408 						if ( lookAhead( "'" ) ) {
   8409 							checkLiteral();
   8410 						} else {
   8411 							literal = true;
   8412 						}
   8413 						break;
   8414 					default:
   8415 						checkLiteral();
   8416 				}
   8417 			}
   8418 		}
   8419 
   8420 		if ( iValue < value.length ) {
   8421 			extra = value.substr( iValue );
   8422 			if ( !/^\s+/.test( extra ) ) {
   8423 				throw "Extra/unparsed characters found in date: " + extra;
   8424 			}
   8425 		}
   8426 
   8427 		if ( year === -1 ) {
   8428 			year = new Date().getFullYear();
   8429 		} else if ( year < 100 ) {
   8430 			year += new Date().getFullYear() - new Date().getFullYear() % 100 +
   8431 				( year <= shortYearCutoff ? 0 : -100 );
   8432 		}
   8433 
   8434 		if ( doy > -1 ) {
   8435 			month = 1;
   8436 			day = doy;
   8437 			do {
   8438 				dim = this._getDaysInMonth( year, month - 1 );
   8439 				if ( day <= dim ) {
   8440 					break;
   8441 				}
   8442 				month++;
   8443 				day -= dim;
   8444 			} while ( true );
   8445 		}
   8446 
   8447 		date = this._daylightSavingAdjust( new Date( year, month - 1, day ) );
   8448 		if ( date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day ) {
   8449 			throw "Invalid date"; // E.g. 31/02/00
   8450 		}
   8451 		return date;
   8452 	},
   8453 
   8454 	/* Standard date formats. */
   8455 	ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601)
   8456 	COOKIE: "D, dd M yy",
   8457 	ISO_8601: "yy-mm-dd",
   8458 	RFC_822: "D, d M y",
   8459 	RFC_850: "DD, dd-M-y",
   8460 	RFC_1036: "D, d M y",
   8461 	RFC_1123: "D, d M yy",
   8462 	RFC_2822: "D, d M yy",
   8463 	RSS: "D, d M y", // RFC 822
   8464 	TICKS: "!",
   8465 	TIMESTAMP: "@",
   8466 	W3C: "yy-mm-dd", // ISO 8601
   8467 
   8468 	_ticksTo1970: ( ( ( 1970 - 1 ) * 365 + Math.floor( 1970 / 4 ) - Math.floor( 1970 / 100 ) +
   8469 		Math.floor( 1970 / 400 ) ) * 24 * 60 * 60 * 10000000 ),
   8470 
   8471 	/* Format a date object into a string value.
   8472 	 * The format can be combinations of the following:
   8473 	 * d  - day of month (no leading zero)
   8474 	 * dd - day of month (two digit)
   8475 	 * o  - day of year (no leading zeros)
   8476 	 * oo - day of year (three digit)
   8477 	 * D  - day name short
   8478 	 * DD - day name long
   8479 	 * m  - month of year (no leading zero)
   8480 	 * mm - month of year (two digit)
   8481 	 * M  - month name short
   8482 	 * MM - month name long
   8483 	 * y  - year (two digit)
   8484 	 * yy - year (four digit)
   8485 	 * @ - Unix timestamp (ms since 01/01/1970)
   8486 	 * ! - Windows ticks (100ns since 01/01/0001)
   8487 	 * "..." - literal text
   8488 	 * '' - single quote
   8489 	 *
   8490 	 * @param  format string - the desired format of the date
   8491 	 * @param  date Date - the date value to format
   8492 	 * @param  settings Object - attributes include:
   8493 	 *					dayNamesShort	string[7] - abbreviated names of the days from Sunday (optional)
   8494 	 *					dayNames		string[7] - names of the days from Sunday (optional)
   8495 	 *					monthNamesShort string[12] - abbreviated names of the months (optional)
   8496 	 *					monthNames		string[12] - names of the months (optional)
   8497 	 * @return  string - the date in the above format
   8498 	 */
   8499 	formatDate: function( format, date, settings ) {
   8500 		if ( !date ) {
   8501 			return "";
   8502 		}
   8503 
   8504 		var iFormat,
   8505 			dayNamesShort = ( settings ? settings.dayNamesShort : null ) || this._defaults.dayNamesShort,
   8506 			dayNames = ( settings ? settings.dayNames : null ) || this._defaults.dayNames,
   8507 			monthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort,
   8508 			monthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames,
   8509 
   8510 			// Check whether a format character is doubled
   8511 			lookAhead = function( match ) {
   8512 				var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );
   8513 				if ( matches ) {
   8514 					iFormat++;
   8515 				}
   8516 				return matches;
   8517 			},
   8518 
   8519 			// Format a number, with leading zero if necessary
   8520 			formatNumber = function( match, value, len ) {
   8521 				var num = "" + value;
   8522 				if ( lookAhead( match ) ) {
   8523 					while ( num.length < len ) {
   8524 						num = "0" + num;
   8525 					}
   8526 				}
   8527 				return num;
   8528 			},
   8529 
   8530 			// Format a name, short or long as requested
   8531 			formatName = function( match, value, shortNames, longNames ) {
   8532 				return ( lookAhead( match ) ? longNames[ value ] : shortNames[ value ] );
   8533 			},
   8534 			output = "",
   8535 			literal = false;
   8536 
   8537 		if ( date ) {
   8538 			for ( iFormat = 0; iFormat < format.length; iFormat++ ) {
   8539 				if ( literal ) {
   8540 					if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) {
   8541 						literal = false;
   8542 					} else {
   8543 						output += format.charAt( iFormat );
   8544 					}
   8545 				} else {
   8546 					switch ( format.charAt( iFormat ) ) {
   8547 						case "d":
   8548 							output += formatNumber( "d", date.getDate(), 2 );
   8549 							break;
   8550 						case "D":
   8551 							output += formatName( "D", date.getDay(), dayNamesShort, dayNames );
   8552 							break;
   8553 						case "o":
   8554 							output += formatNumber( "o",
   8555 								Math.round( ( new Date( date.getFullYear(), date.getMonth(), date.getDate() ).getTime() - new Date( date.getFullYear(), 0, 0 ).getTime() ) / 86400000 ), 3 );
   8556 							break;
   8557 						case "m":
   8558 							output += formatNumber( "m", date.getMonth() + 1, 2 );
   8559 							break;
   8560 						case "M":
   8561 							output += formatName( "M", date.getMonth(), monthNamesShort, monthNames );
   8562 							break;
   8563 						case "y":
   8564 							output += ( lookAhead( "y" ) ? date.getFullYear() :
   8565 								( date.getFullYear() % 100 < 10 ? "0" : "" ) + date.getFullYear() % 100 );
   8566 							break;
   8567 						case "@":
   8568 							output += date.getTime();
   8569 							break;
   8570 						case "!":
   8571 							output += date.getTime() * 10000 + this._ticksTo1970;
   8572 							break;
   8573 						case "'":
   8574 							if ( lookAhead( "'" ) ) {
   8575 								output += "'";
   8576 							} else {
   8577 								literal = true;
   8578 							}
   8579 							break;
   8580 						default:
   8581 							output += format.charAt( iFormat );
   8582 					}
   8583 				}
   8584 			}
   8585 		}
   8586 		return output;
   8587 	},
   8588 
   8589 	/* Extract all possible characters from the date format. */
   8590 	_possibleChars: function( format ) {
   8591 		var iFormat,
   8592 			chars = "",
   8593 			literal = false,
   8594 
   8595 			// Check whether a format character is doubled
   8596 			lookAhead = function( match ) {
   8597 				var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );
   8598 				if ( matches ) {
   8599 					iFormat++;
   8600 				}
   8601 				return matches;
   8602 			};
   8603 
   8604 		for ( iFormat = 0; iFormat < format.length; iFormat++ ) {
   8605 			if ( literal ) {
   8606 				if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) {
   8607 					literal = false;
   8608 				} else {
   8609 					chars += format.charAt( iFormat );
   8610 				}
   8611 			} else {
   8612 				switch ( format.charAt( iFormat ) ) {
   8613 					case "d": case "m": case "y": case "@":
   8614 						chars += "0123456789";
   8615 						break;
   8616 					case "D": case "M":
   8617 						return null; // Accept anything
   8618 					case "'":
   8619 						if ( lookAhead( "'" ) ) {
   8620 							chars += "'";
   8621 						} else {
   8622 							literal = true;
   8623 						}
   8624 						break;
   8625 					default:
   8626 						chars += format.charAt( iFormat );
   8627 				}
   8628 			}
   8629 		}
   8630 		return chars;
   8631 	},
   8632 
   8633 	/* Get a setting value, defaulting if necessary. */
   8634 	_get: function( inst, name ) {
   8635 		return inst.settings[ name ] !== undefined ?
   8636 			inst.settings[ name ] : this._defaults[ name ];
   8637 	},
   8638 
   8639 	/* Parse existing date and initialise date picker. */
   8640 	_setDateFromField: function( inst, noDefault ) {
   8641 		if ( inst.input.val() === inst.lastVal ) {
   8642 			return;
   8643 		}
   8644 
   8645 		var dateFormat = this._get( inst, "dateFormat" ),
   8646 			dates = inst.lastVal = inst.input ? inst.input.val() : null,
   8647 			defaultDate = this._getDefaultDate( inst ),
   8648 			date = defaultDate,
   8649 			settings = this._getFormatConfig( inst );
   8650 
   8651 		try {
   8652 			date = this.parseDate( dateFormat, dates, settings ) || defaultDate;
   8653 		} catch ( event ) {
   8654 			dates = ( noDefault ? "" : dates );
   8655 		}
   8656 		inst.selectedDay = date.getDate();
   8657 		inst.drawMonth = inst.selectedMonth = date.getMonth();
   8658 		inst.drawYear = inst.selectedYear = date.getFullYear();
   8659 		inst.currentDay = ( dates ? date.getDate() : 0 );
   8660 		inst.currentMonth = ( dates ? date.getMonth() : 0 );
   8661 		inst.currentYear = ( dates ? date.getFullYear() : 0 );
   8662 		this._adjustInstDate( inst );
   8663 	},
   8664 
   8665 	/* Retrieve the default date shown on opening. */
   8666 	_getDefaultDate: function( inst ) {
   8667 		return this._restrictMinMax( inst,
   8668 			this._determineDate( inst, this._get( inst, "defaultDate" ), new Date() ) );
   8669 	},
   8670 
   8671 	/* A date may be specified as an exact value or a relative one. */
   8672 	_determineDate: function( inst, date, defaultDate ) {
   8673 		var offsetNumeric = function( offset ) {
   8674 				var date = new Date();
   8675 				date.setDate( date.getDate() + offset );
   8676 				return date;
   8677 			},
   8678 			offsetString = function( offset ) {
   8679 				try {
   8680 					return $.datepicker.parseDate( $.datepicker._get( inst, "dateFormat" ),
   8681 						offset, $.datepicker._getFormatConfig( inst ) );
   8682 				}
   8683 				catch ( e ) {
   8684 
   8685 					// Ignore
   8686 				}
   8687 
   8688 				var date = ( offset.toLowerCase().match( /^c/ ) ?
   8689 					$.datepicker._getDate( inst ) : null ) || new Date(),
   8690 					year = date.getFullYear(),
   8691 					month = date.getMonth(),
   8692 					day = date.getDate(),
   8693 					pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,
   8694 					matches = pattern.exec( offset );
   8695 
   8696 				while ( matches ) {
   8697 					switch ( matches[ 2 ] || "d" ) {
   8698 						case "d" : case "D" :
   8699 							day += parseInt( matches[ 1 ], 10 ); break;
   8700 						case "w" : case "W" :
   8701 							day += parseInt( matches[ 1 ], 10 ) * 7; break;
   8702 						case "m" : case "M" :
   8703 							month += parseInt( matches[ 1 ], 10 );
   8704 							day = Math.min( day, $.datepicker._getDaysInMonth( year, month ) );
   8705 							break;
   8706 						case "y": case "Y" :
   8707 							year += parseInt( matches[ 1 ], 10 );
   8708 							day = Math.min( day, $.datepicker._getDaysInMonth( year, month ) );
   8709 							break;
   8710 					}
   8711 					matches = pattern.exec( offset );
   8712 				}
   8713 				return new Date( year, month, day );
   8714 			},
   8715 			newDate = ( date == null || date === "" ? defaultDate : ( typeof date === "string" ? offsetString( date ) :
   8716 				( typeof date === "number" ? ( isNaN( date ) ? defaultDate : offsetNumeric( date ) ) : new Date( date.getTime() ) ) ) );
   8717 
   8718 		newDate = ( newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate );
   8719 		if ( newDate ) {
   8720 			newDate.setHours( 0 );
   8721 			newDate.setMinutes( 0 );
   8722 			newDate.setSeconds( 0 );
   8723 			newDate.setMilliseconds( 0 );
   8724 		}
   8725 		return this._daylightSavingAdjust( newDate );
   8726 	},
   8727 
   8728 	/* Handle switch to/from daylight saving.
   8729 	 * Hours may be non-zero on daylight saving cut-over:
   8730 	 * > 12 when midnight changeover, but then cannot generate
   8731 	 * midnight datetime, so jump to 1AM, otherwise reset.
   8732 	 * @param  date  (Date) the date to check
   8733 	 * @return  (Date) the corrected date
   8734 	 */
   8735 	_daylightSavingAdjust: function( date ) {
   8736 		if ( !date ) {
   8737 			return null;
   8738 		}
   8739 		date.setHours( date.getHours() > 12 ? date.getHours() + 2 : 0 );
   8740 		return date;
   8741 	},
   8742 
   8743 	/* Set the date(s) directly. */
   8744 	_setDate: function( inst, date, noChange ) {
   8745 		var clear = !date,
   8746 			origMonth = inst.selectedMonth,
   8747 			origYear = inst.selectedYear,
   8748 			newDate = this._restrictMinMax( inst, this._determineDate( inst, date, new Date() ) );
   8749 
   8750 		inst.selectedDay = inst.currentDay = newDate.getDate();
   8751 		inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
   8752 		inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
   8753 		if ( ( origMonth !== inst.selectedMonth || origYear !== inst.selectedYear ) && !noChange ) {
   8754 			this._notifyChange( inst );
   8755 		}
   8756 		this._adjustInstDate( inst );
   8757 		if ( inst.input ) {
   8758 			inst.input.val( clear ? "" : this._formatDate( inst ) );
   8759 		}
   8760 	},
   8761 
   8762 	/* Retrieve the date(s) directly. */
   8763 	_getDate: function( inst ) {
   8764 		var startDate = ( !inst.currentYear || ( inst.input && inst.input.val() === "" ) ? null :
   8765 			this._daylightSavingAdjust( new Date(
   8766 			inst.currentYear, inst.currentMonth, inst.currentDay ) ) );
   8767 			return startDate;
   8768 	},
   8769 
   8770 	/* Attach the onxxx handlers.  These are declared statically so
   8771 	 * they work with static code transformers like Caja.
   8772 	 */
   8773 	_attachHandlers: function( inst ) {
   8774 		var stepMonths = this._get( inst, "stepMonths" ),
   8775 			id = "#" + inst.id.replace( /\\\\/g, "\\" );
   8776 		inst.dpDiv.find( "[data-handler]" ).map( function() {
   8777 			var handler = {
   8778 				prev: function() {
   8779 					$.datepicker._adjustDate( id, -stepMonths, "M" );
   8780 				},
   8781 				next: function() {
   8782 					$.datepicker._adjustDate( id, +stepMonths, "M" );
   8783 				},
   8784 				hide: function() {
   8785 					$.datepicker._hideDatepicker();
   8786 				},
   8787 				today: function() {
   8788 					$.datepicker._gotoToday( id );
   8789 				},
   8790 				selectDay: function() {
   8791 					$.datepicker._selectDay( id, +this.getAttribute( "data-month" ), +this.getAttribute( "data-year" ), this );
   8792 					return false;
   8793 				},
   8794 				selectMonth: function() {
   8795 					$.datepicker._selectMonthYear( id, this, "M" );
   8796 					return false;
   8797 				},
   8798 				selectYear: function() {
   8799 					$.datepicker._selectMonthYear( id, this, "Y" );
   8800 					return false;
   8801 				}
   8802 			};
   8803 			$( this ).on( this.getAttribute( "data-event" ), handler[ this.getAttribute( "data-handler" ) ] );
   8804 		} );
   8805 	},
   8806 
   8807 	/* Generate the HTML for the current state of the date picker. */
   8808 	_generateHTML: function( inst ) {
   8809 		var maxDraw, prevText, prev, nextText, next, currentText, gotoDate,
   8810 			controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin,
   8811 			monthNames, monthNamesShort, beforeShowDay, showOtherMonths,
   8812 			selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate,
   8813 			cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows,
   8814 			printDate, dRow, tbody, daySettings, otherMonth, unselectable,
   8815 			tempDate = new Date(),
   8816 			today = this._daylightSavingAdjust(
   8817 				new Date( tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate() ) ), // clear time
   8818 			isRTL = this._get( inst, "isRTL" ),
   8819 			showButtonPanel = this._get( inst, "showButtonPanel" ),
   8820 			hideIfNoPrevNext = this._get( inst, "hideIfNoPrevNext" ),
   8821 			navigationAsDateFormat = this._get( inst, "navigationAsDateFormat" ),
   8822 			numMonths = this._getNumberOfMonths( inst ),
   8823 			showCurrentAtPos = this._get( inst, "showCurrentAtPos" ),
   8824 			stepMonths = this._get( inst, "stepMonths" ),
   8825 			isMultiMonth = ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ),
   8826 			currentDate = this._daylightSavingAdjust( ( !inst.currentDay ? new Date( 9999, 9, 9 ) :
   8827 				new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) ),
   8828 			minDate = this._getMinMaxDate( inst, "min" ),
   8829 			maxDate = this._getMinMaxDate( inst, "max" ),
   8830 			drawMonth = inst.drawMonth - showCurrentAtPos,
   8831 			drawYear = inst.drawYear;
   8832 
   8833 		if ( drawMonth < 0 ) {
   8834 			drawMonth += 12;
   8835 			drawYear--;
   8836 		}
   8837 		if ( maxDate ) {
   8838 			maxDraw = this._daylightSavingAdjust( new Date( maxDate.getFullYear(),
   8839 				maxDate.getMonth() - ( numMonths[ 0 ] * numMonths[ 1 ] ) + 1, maxDate.getDate() ) );
   8840 			maxDraw = ( minDate && maxDraw < minDate ? minDate : maxDraw );
   8841 			while ( this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 ) ) > maxDraw ) {
   8842 				drawMonth--;
   8843 				if ( drawMonth < 0 ) {
   8844 					drawMonth = 11;
   8845 					drawYear--;
   8846 				}
   8847 			}
   8848 		}
   8849 		inst.drawMonth = drawMonth;
   8850 		inst.drawYear = drawYear;
   8851 
   8852 		prevText = this._get( inst, "prevText" );
   8853 		prevText = ( !navigationAsDateFormat ? prevText : this.formatDate( prevText,
   8854 			this._daylightSavingAdjust( new Date( drawYear, drawMonth - stepMonths, 1 ) ),
   8855 			this._getFormatConfig( inst ) ) );
   8856 
   8857 		prev = ( this._canAdjustMonth( inst, -1, drawYear, drawMonth ) ?
   8858 			"<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click'" +
   8859 			" title='" + prevText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w" ) + "'>" + prevText + "</span></a>" :
   8860 			( 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>" ) );
   8861 
   8862 		nextText = this._get( inst, "nextText" );
   8863 		nextText = ( !navigationAsDateFormat ? nextText : this.formatDate( nextText,
   8864 			this._daylightSavingAdjust( new Date( drawYear, drawMonth + stepMonths, 1 ) ),
   8865 			this._getFormatConfig( inst ) ) );
   8866 
   8867 		next = ( this._canAdjustMonth( inst, +1, drawYear, drawMonth ) ?
   8868 			"<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click'" +
   8869 			" title='" + nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e" ) + "'>" + nextText + "</span></a>" :
   8870 			( 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>" ) );
   8871 
   8872 		currentText = this._get( inst, "currentText" );
   8873 		gotoDate = ( this._get( inst, "gotoCurrent" ) && inst.currentDay ? currentDate : today );
   8874 		currentText = ( !navigationAsDateFormat ? currentText :
   8875 			this.formatDate( currentText, gotoDate, this._getFormatConfig( inst ) ) );
   8876 
   8877 		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'>" +
   8878 			this._get( inst, "closeText" ) + "</button>" : "" );
   8879 
   8880 		buttonPanel = ( showButtonPanel ) ? "<div class='ui-datepicker-buttonpane ui-widget-content'>" + ( isRTL ? controls : "" ) +
   8881 			( 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'" +
   8882 			">" + currentText + "</button>" : "" ) + ( isRTL ? "" : controls ) + "</div>" : "";
   8883 
   8884 		firstDay = parseInt( this._get( inst, "firstDay" ), 10 );
   8885 		firstDay = ( isNaN( firstDay ) ? 0 : firstDay );
   8886 
   8887 		showWeek = this._get( inst, "showWeek" );
   8888 		dayNames = this._get( inst, "dayNames" );
   8889 		dayNamesMin = this._get( inst, "dayNamesMin" );
   8890 		monthNames = this._get( inst, "monthNames" );
   8891 		monthNamesShort = this._get( inst, "monthNamesShort" );
   8892 		beforeShowDay = this._get( inst, "beforeShowDay" );
   8893 		showOtherMonths = this._get( inst, "showOtherMonths" );
   8894 		selectOtherMonths = this._get( inst, "selectOtherMonths" );
   8895 		defaultDate = this._getDefaultDate( inst );
   8896 		html = "";
   8897 
   8898 		for ( row = 0; row < numMonths[ 0 ]; row++ ) {
   8899 			group = "";
   8900 			this.maxRows = 4;
   8901 			for ( col = 0; col < numMonths[ 1 ]; col++ ) {
   8902 				selectedDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, inst.selectedDay ) );
   8903 				cornerClass = " ui-corner-all";
   8904 				calender = "";
   8905 				if ( isMultiMonth ) {
   8906 					calender += "<div class='ui-datepicker-group";
   8907 					if ( numMonths[ 1 ] > 1 ) {
   8908 						switch ( col ) {
   8909 							case 0: calender += " ui-datepicker-group-first";
   8910 								cornerClass = " ui-corner-" + ( isRTL ? "right" : "left" ); break;
   8911 							case numMonths[ 1 ] - 1: calender += " ui-datepicker-group-last";
   8912 								cornerClass = " ui-corner-" + ( isRTL ? "left" : "right" ); break;
   8913 							default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break;
   8914 						}
   8915 					}
   8916 					calender += "'>";
   8917 				}
   8918 				calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" +
   8919 					( /all|left/.test( cornerClass ) && row === 0 ? ( isRTL ? next : prev ) : "" ) +
   8920 					( /all|right/.test( cornerClass ) && row === 0 ? ( isRTL ? prev : next ) : "" ) +
   8921 					this._generateMonthYearHeader( inst, drawMonth, drawYear, minDate, maxDate,
   8922 					row > 0 || col > 0, monthNames, monthNamesShort ) + // draw month headers
   8923 					"</div><table class='ui-datepicker-calendar'><thead>" +
   8924 					"<tr>";
   8925 				thead = ( showWeek ? "<th class='ui-datepicker-week-col'>" + this._get( inst, "weekHeader" ) + "</th>" : "" );
   8926 				for ( dow = 0; dow < 7; dow++ ) { // days of the week
   8927 					day = ( dow + firstDay ) % 7;
   8928 					thead += "<th scope='col'" + ( ( dow + firstDay + 6 ) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "" ) + ">" +
   8929 						"<span title='" + dayNames[ day ] + "'>" + dayNamesMin[ day ] + "</span></th>";
   8930 				}
   8931 				calender += thead + "</tr></thead><tbody>";
   8932 				daysInMonth = this._getDaysInMonth( drawYear, drawMonth );
   8933 				if ( drawYear === inst.selectedYear && drawMonth === inst.selectedMonth ) {
   8934 					inst.selectedDay = Math.min( inst.selectedDay, daysInMonth );
   8935 				}
   8936 				leadDays = ( this._getFirstDayOfMonth( drawYear, drawMonth ) - firstDay + 7 ) % 7;
   8937 				curRows = Math.ceil( ( leadDays + daysInMonth ) / 7 ); // calculate the number of rows to generate
   8938 				numRows = ( isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows ); //If multiple months, use the higher number of rows (see #7043)
   8939 				this.maxRows = numRows;
   8940 				printDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 - leadDays ) );
   8941 				for ( dRow = 0; dRow < numRows; dRow++ ) { // create date picker rows
   8942 					calender += "<tr>";
   8943 					tbody = ( !showWeek ? "" : "<td class='ui-datepicker-week-col'>" +
   8944 						this._get( inst, "calculateWeek" )( printDate ) + "</td>" );
   8945 					for ( dow = 0; dow < 7; dow++ ) { // create date picker days
   8946 						daySettings = ( beforeShowDay ?
   8947 							beforeShowDay.apply( ( inst.input ? inst.input[ 0 ] : null ), [ printDate ] ) : [ true, "" ] );
   8948 						otherMonth = ( printDate.getMonth() !== drawMonth );
   8949 						unselectable = ( otherMonth && !selectOtherMonths ) || !daySettings[ 0 ] ||
   8950 							( minDate && printDate < minDate ) || ( maxDate && printDate > maxDate );
   8951 						tbody += "<td class='" +
   8952 							( ( dow + firstDay + 6 ) % 7 >= 5 ? " ui-datepicker-week-end" : "" ) + // highlight weekends
   8953 							( otherMonth ? " ui-datepicker-other-month" : "" ) + // highlight days from other months
   8954 							( ( printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent ) || // user pressed key
   8955 							( defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime() ) ?
   8956 
   8957 							// or defaultDate is current printedDate and defaultDate is selectedDate
   8958 							" " + this._dayOverClass : "" ) + // highlight selected day
   8959 							( unselectable ? " " + this._unselectableClass + " ui-state-disabled" : "" ) +  // highlight unselectable days
   8960 							( otherMonth && !showOtherMonths ? "" : " " + daySettings[ 1 ] + // highlight custom dates
   8961 							( printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "" ) + // highlight selected day
   8962 							( printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "" ) ) + "'" + // highlight today (if different)
   8963 							( ( !otherMonth || showOtherMonths ) && daySettings[ 2 ] ? " title='" + daySettings[ 2 ].replace( /'/g, "&#39;" ) + "'" : "" ) + // cell title
   8964 							( unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'" ) + ">" + // actions
   8965 							( otherMonth && !showOtherMonths ? "&#xa0;" : // display for other months
   8966 							( unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" +
   8967 							( printDate.getTime() === today.getTime() ? " ui-state-highlight" : "" ) +
   8968 							( printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "" ) + // highlight selected day
   8969 							( otherMonth ? " ui-priority-secondary" : "" ) + // distinguish dates from other months
   8970 							"' href='#'>" + printDate.getDate() + "</a>" ) ) + "</td>"; // display selectable date
   8971 						printDate.setDate( printDate.getDate() + 1 );
   8972 						printDate = this._daylightSavingAdjust( printDate );
   8973 					}
   8974 					calender += tbody + "</tr>";
   8975 				}
   8976 				drawMonth++;
   8977 				if ( drawMonth > 11 ) {
   8978 					drawMonth = 0;
   8979 					drawYear++;
   8980 				}
   8981 				calender += "</tbody></table>" + ( isMultiMonth ? "</div>" +
   8982 							( ( numMonths[ 0 ] > 0 && col === numMonths[ 1 ] - 1 ) ? "<div class='ui-datepicker-row-break'></div>" : "" ) : "" );
   8983 				group += calender;
   8984 			}
   8985 			html += group;
   8986 		}
   8987 		html += buttonPanel;
   8988 		inst._keyEvent = false;
   8989 		return html;
   8990 	},
   8991 
   8992 	/* Generate the month and year header. */
   8993 	_generateMonthYearHeader: function( inst, drawMonth, drawYear, minDate, maxDate,
   8994 			secondary, monthNames, monthNamesShort ) {
   8995 
   8996 		var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear,
   8997 			changeMonth = this._get( inst, "changeMonth" ),
   8998 			changeYear = this._get( inst, "changeYear" ),
   8999 			showMonthAfterYear = this._get( inst, "showMonthAfterYear" ),
   9000 			html = "<div class='ui-datepicker-title'>",
   9001 			monthHtml = "";
   9002 
   9003 		// Month selection
   9004 		if ( secondary || !changeMonth ) {
   9005 			monthHtml += "<span class='ui-datepicker-month'>" + monthNames[ drawMonth ] + "</span>";
   9006 		} else {
   9007 			inMinYear = ( minDate && minDate.getFullYear() === drawYear );
   9008 			inMaxYear = ( maxDate && maxDate.getFullYear() === drawYear );
   9009 			monthHtml += "<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>";
   9010 			for ( month = 0; month < 12; month++ ) {
   9011 				if ( ( !inMinYear || month >= minDate.getMonth() ) && ( !inMaxYear || month <= maxDate.getMonth() ) ) {
   9012 					monthHtml += "<option value='" + month + "'" +
   9013 						( month === drawMonth ? " selected='selected'" : "" ) +
   9014 						">" + monthNamesShort[ month ] + "</option>";
   9015 				}
   9016 			}
   9017 			monthHtml += "</select>";
   9018 		}
   9019 
   9020 		if ( !showMonthAfterYear ) {
   9021 			html += monthHtml + ( secondary || !( changeMonth && changeYear ) ? "&#xa0;" : "" );
   9022 		}
   9023 
   9024 		// Year selection
   9025 		if ( !inst.yearshtml ) {
   9026 			inst.yearshtml = "";
   9027 			if ( secondary || !changeYear ) {
   9028 				html += "<span class='ui-datepicker-year'>" + drawYear + "</span>";
   9029 			} else {
   9030 
   9031 				// determine range of years to display
   9032 				years = this._get( inst, "yearRange" ).split( ":" );
   9033 				thisYear = new Date().getFullYear();
   9034 				determineYear = function( value ) {
   9035 					var year = ( value.match( /c[+\-].*/ ) ? drawYear + parseInt( value.substring( 1 ), 10 ) :
   9036 						( value.match( /[+\-].*/ ) ? thisYear + parseInt( value, 10 ) :
   9037 						parseInt( value, 10 ) ) );
   9038 					return ( isNaN( year ) ? thisYear : year );
   9039 				};
   9040 				year = determineYear( years[ 0 ] );
   9041 				endYear = Math.max( year, determineYear( years[ 1 ] || "" ) );
   9042 				year = ( minDate ? Math.max( year, minDate.getFullYear() ) : year );
   9043 				endYear = ( maxDate ? Math.min( endYear, maxDate.getFullYear() ) : endYear );
   9044 				inst.yearshtml += "<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>";
   9045 				for ( ; year <= endYear; year++ ) {
   9046 					inst.yearshtml += "<option value='" + year + "'" +
   9047 						( year === drawYear ? " selected='selected'" : "" ) +
   9048 						">" + year + "</option>";
   9049 				}
   9050 				inst.yearshtml += "</select>";
   9051 
   9052 				html += inst.yearshtml;
   9053 				inst.yearshtml = null;
   9054 			}
   9055 		}
   9056 
   9057 		html += this._get( inst, "yearSuffix" );
   9058 		if ( showMonthAfterYear ) {
   9059 			html += ( secondary || !( changeMonth && changeYear ) ? "&#xa0;" : "" ) + monthHtml;
   9060 		}
   9061 		html += "</div>"; // Close datepicker_header
   9062 		return html;
   9063 	},
   9064 
   9065 	/* Adjust one of the date sub-fields. */
   9066 	_adjustInstDate: function( inst, offset, period ) {
   9067 		var year = inst.selectedYear + ( period === "Y" ? offset : 0 ),
   9068 			month = inst.selectedMonth + ( period === "M" ? offset : 0 ),
   9069 			day = Math.min( inst.selectedDay, this._getDaysInMonth( year, month ) ) + ( period === "D" ? offset : 0 ),
   9070 			date = this._restrictMinMax( inst, this._daylightSavingAdjust( new Date( year, month, day ) ) );
   9071 
   9072 		inst.selectedDay = date.getDate();
   9073 		inst.drawMonth = inst.selectedMonth = date.getMonth();
   9074 		inst.drawYear = inst.selectedYear = date.getFullYear();
   9075 		if ( period === "M" || period === "Y" ) {
   9076 			this._notifyChange( inst );
   9077 		}
   9078 	},
   9079 
   9080 	/* Ensure a date is within any min/max bounds. */
   9081 	_restrictMinMax: function( inst, date ) {
   9082 		var minDate = this._getMinMaxDate( inst, "min" ),
   9083 			maxDate = this._getMinMaxDate( inst, "max" ),
   9084 			newDate = ( minDate && date < minDate ? minDate : date );
   9085 		return ( maxDate && newDate > maxDate ? maxDate : newDate );
   9086 	},
   9087 
   9088 	/* Notify change of month/year. */
   9089 	_notifyChange: function( inst ) {
   9090 		var onChange = this._get( inst, "onChangeMonthYear" );
   9091 		if ( onChange ) {
   9092 			onChange.apply( ( inst.input ? inst.input[ 0 ] : null ),
   9093 				[ inst.selectedYear, inst.selectedMonth + 1, inst ] );
   9094 		}
   9095 	},
   9096 
   9097 	/* Determine the number of months to show. */
   9098 	_getNumberOfMonths: function( inst ) {
   9099 		var numMonths = this._get( inst, "numberOfMonths" );
   9100 		return ( numMonths == null ? [ 1, 1 ] : ( typeof numMonths === "number" ? [ 1, numMonths ] : numMonths ) );
   9101 	},
   9102 
   9103 	/* Determine the current maximum date - ensure no time components are set. */
   9104 	_getMinMaxDate: function( inst, minMax ) {
   9105 		return this._determineDate( inst, this._get( inst, minMax + "Date" ), null );
   9106 	},
   9107 
   9108 	/* Find the number of days in a given month. */
   9109 	_getDaysInMonth: function( year, month ) {
   9110 		return 32 - this._daylightSavingAdjust( new Date( year, month, 32 ) ).getDate();
   9111 	},
   9112 
   9113 	/* Find the day of the week of the first of a month. */
   9114 	_getFirstDayOfMonth: function( year, month ) {
   9115 		return new Date( year, month, 1 ).getDay();
   9116 	},
   9117 
   9118 	/* Determines if we should allow a "next/prev" month display change. */
   9119 	_canAdjustMonth: function( inst, offset, curYear, curMonth ) {
   9120 		var numMonths = this._getNumberOfMonths( inst ),
   9121 			date = this._daylightSavingAdjust( new Date( curYear,
   9122 			curMonth + ( offset < 0 ? offset : numMonths[ 0 ] * numMonths[ 1 ] ), 1 ) );
   9123 
   9124 		if ( offset < 0 ) {
   9125 			date.setDate( this._getDaysInMonth( date.getFullYear(), date.getMonth() ) );
   9126 		}
   9127 		return this._isInRange( inst, date );
   9128 	},
   9129 
   9130 	/* Is the given date in the accepted range? */
   9131 	_isInRange: function( inst, date ) {
   9132 		var yearSplit, currentYear,
   9133 			minDate = this._getMinMaxDate( inst, "min" ),
   9134 			maxDate = this._getMinMaxDate( inst, "max" ),
   9135 			minYear = null,
   9136 			maxYear = null,
   9137 			years = this._get( inst, "yearRange" );
   9138 			if ( years ) {
   9139 				yearSplit = years.split( ":" );
   9140 				currentYear = new Date().getFullYear();
   9141 				minYear = parseInt( yearSplit[ 0 ], 10 );
   9142 				maxYear = parseInt( yearSplit[ 1 ], 10 );
   9143 				if ( yearSplit[ 0 ].match( /[+\-].*/ ) ) {
   9144 					minYear += currentYear;
   9145 				}
   9146 				if ( yearSplit[ 1 ].match( /[+\-].*/ ) ) {
   9147 					maxYear += currentYear;
   9148 				}
   9149 			}
   9150 
   9151 		return ( ( !minDate || date.getTime() >= minDate.getTime() ) &&
   9152 			( !maxDate || date.getTime() <= maxDate.getTime() ) &&
   9153 			( !minYear || date.getFullYear() >= minYear ) &&
   9154 			( !maxYear || date.getFullYear() <= maxYear ) );
   9155 	},
   9156 
   9157 	/* Provide the configuration settings for formatting/parsing. */
   9158 	_getFormatConfig: function( inst ) {
   9159 		var shortYearCutoff = this._get( inst, "shortYearCutoff" );
   9160 		shortYearCutoff = ( typeof shortYearCutoff !== "string" ? shortYearCutoff :
   9161 			new Date().getFullYear() % 100 + parseInt( shortYearCutoff, 10 ) );
   9162 		return { shortYearCutoff: shortYearCutoff,
   9163 			dayNamesShort: this._get( inst, "dayNamesShort" ), dayNames: this._get( inst, "dayNames" ),
   9164 			monthNamesShort: this._get( inst, "monthNamesShort" ), monthNames: this._get( inst, "monthNames" ) };
   9165 	},
   9166 
   9167 	/* Format the given date for display. */
   9168 	_formatDate: function( inst, day, month, year ) {
   9169 		if ( !day ) {
   9170 			inst.currentDay = inst.selectedDay;
   9171 			inst.currentMonth = inst.selectedMonth;
   9172 			inst.currentYear = inst.selectedYear;
   9173 		}
   9174 		var date = ( day ? ( typeof day === "object" ? day :
   9175 			this._daylightSavingAdjust( new Date( year, month, day ) ) ) :
   9176 			this._daylightSavingAdjust( new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) );
   9177 		return this.formatDate( this._get( inst, "dateFormat" ), date, this._getFormatConfig( inst ) );
   9178 	}
   9179 } );
   9180 
   9181 /*
   9182  * Bind hover events for datepicker elements.
   9183  * Done via delegate so the binding only occurs once in the lifetime of the parent div.
   9184  * Global datepicker_instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
   9185  */
   9186 function datepicker_bindHover( dpDiv ) {
   9187 	var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";
   9188 	return dpDiv.on( "mouseout", selector, function() {
   9189 			$( this ).removeClass( "ui-state-hover" );
   9190 			if ( this.className.indexOf( "ui-datepicker-prev" ) !== -1 ) {
   9191 				$( this ).removeClass( "ui-datepicker-prev-hover" );
   9192 			}
   9193 			if ( this.className.indexOf( "ui-datepicker-next" ) !== -1 ) {
   9194 				$( this ).removeClass( "ui-datepicker-next-hover" );
   9195 			}
   9196 		} )
   9197 		.on( "mouseover", selector, datepicker_handleMouseover );
   9198 }
   9199 
   9200 function datepicker_handleMouseover() {
   9201 	if ( !$.datepicker._isDisabledDatepicker( datepicker_instActive.inline ? datepicker_instActive.dpDiv.parent()[ 0 ] : datepicker_instActive.input[ 0 ] ) ) {
   9202 		$( this ).parents( ".ui-datepicker-calendar" ).find( "a" ).removeClass( "ui-state-hover" );
   9203 		$( this ).addClass( "ui-state-hover" );
   9204 		if ( this.className.indexOf( "ui-datepicker-prev" ) !== -1 ) {
   9205 			$( this ).addClass( "ui-datepicker-prev-hover" );
   9206 		}
   9207 		if ( this.className.indexOf( "ui-datepicker-next" ) !== -1 ) {
   9208 			$( this ).addClass( "ui-datepicker-next-hover" );
   9209 		}
   9210 	}
   9211 }
   9212 
   9213 /* jQuery extend now ignores nulls! */
   9214 function datepicker_extendRemove( target, props ) {
   9215 	$.extend( target, props );
   9216 	for ( var name in props ) {
   9217 		if ( props[ name ] == null ) {
   9218 			target[ name ] = props[ name ];
   9219 		}
   9220 	}
   9221 	return target;
   9222 }
   9223 
   9224 /* Invoke the datepicker functionality.
   9225    @param  options  string - a command, optionally followed by additional parameters or
   9226 					Object - settings for attaching new datepicker functionality
   9227    @return  jQuery object */
   9228 $.fn.datepicker = function( options ) {
   9229 
   9230 	/* Verify an empty collection wasn't passed - Fixes #6976 */
   9231 	if ( !this.length ) {
   9232 		return this;
   9233 	}
   9234 
   9235 	/* Initialise the date picker. */
   9236 	if ( !$.datepicker.initialized ) {
   9237 		$( document ).on( "mousedown", $.datepicker._checkExternalClick );
   9238 		$.datepicker.initialized = true;
   9239 	}
   9240 
   9241 	/* Append datepicker main container to body if not exist. */
   9242 	if ( $( "#" + $.datepicker._mainDivId ).length === 0 ) {
   9243 		$( "body" ).append( $.datepicker.dpDiv );
   9244 	}
   9245 
   9246 	var otherArgs = Array.prototype.slice.call( arguments, 1 );
   9247 	if ( typeof options === "string" && ( options === "isDisabled" || options === "getDate" || options === "widget" ) ) {
   9248 		return $.datepicker[ "_" + options + "Datepicker" ].
   9249 			apply( $.datepicker, [ this[ 0 ] ].concat( otherArgs ) );
   9250 	}
   9251 	if ( options === "option" && arguments.length === 2 && typeof arguments[ 1 ] === "string" ) {
   9252 		return $.datepicker[ "_" + options + "Datepicker" ].
   9253 			apply( $.datepicker, [ this[ 0 ] ].concat( otherArgs ) );
   9254 	}
   9255 	return this.each( function() {
   9256 		typeof options === "string" ?
   9257 			$.datepicker[ "_" + options + "Datepicker" ].
   9258 				apply( $.datepicker, [ this ].concat( otherArgs ) ) :
   9259 			$.datepicker._attachDatepicker( this, options );
   9260 	} );
   9261 };
   9262 
   9263 $.datepicker = new Datepicker(); // singleton instance
   9264 $.datepicker.initialized = false;
   9265 $.datepicker.uuid = new Date().getTime();
   9266 $.datepicker.version = "1.12.1";
   9267 
   9268 var widgetsDatepicker = $.datepicker;
   9269 
   9270 
   9271 
   9272 
   9273 // This file is deprecated
   9274 var ie = $.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() );
   9275 
   9276 /*!
   9277  * jQuery UI Mouse 1.12.1
   9278  * http://jqueryui.com
   9279  *
   9280  * Copyright jQuery Foundation and other contributors
   9281  * Released under the MIT license.
   9282  * http://jquery.org/license
   9283  */
   9284 
   9285 //>>label: Mouse
   9286 //>>group: Widgets
   9287 //>>description: Abstracts mouse-based interactions to assist in creating certain widgets.
   9288 //>>docs: http://api.jqueryui.com/mouse/
   9289 
   9290 
   9291 
   9292 var mouseHandled = false;
   9293 $( document ).on( "mouseup", function() {
   9294 	mouseHandled = false;
   9295 } );
   9296 
   9297 var widgetsMouse = $.widget( "ui.mouse", {
   9298 	version: "1.12.1",
   9299 	options: {
   9300 		cancel: "input, textarea, button, select, option",
   9301 		distance: 1,
   9302 		delay: 0
   9303 	},
   9304 	_mouseInit: function() {
   9305 		var that = this;
   9306 
   9307 		this.element
   9308 			.on( "mousedown." + this.widgetName, function( event ) {
   9309 				return that._mouseDown( event );
   9310 			} )
   9311 			.on( "click." + this.widgetName, function( event ) {
   9312 				if ( true === $.data( event.target, that.widgetName + ".preventClickEvent" ) ) {
   9313 					$.removeData( event.target, that.widgetName + ".preventClickEvent" );
   9314 					event.stopImmediatePropagation();
   9315 					return false;
   9316 				}
   9317 			} );
   9318 
   9319 		this.started = false;
   9320 	},
   9321 
   9322 	// TODO: make sure destroying one instance of mouse doesn't mess with
   9323 	// other instances of mouse
   9324 	_mouseDestroy: function() {
   9325 		this.element.off( "." + this.widgetName );
   9326 		if ( this._mouseMoveDelegate ) {
   9327 			this.document
   9328 				.off( "mousemove." + this.widgetName, this._mouseMoveDelegate )
   9329 				.off( "mouseup." + this.widgetName, this._mouseUpDelegate );
   9330 		}
   9331 	},
   9332 
   9333 	_mouseDown: function( event ) {
   9334 
   9335 		// don't let more than one widget handle mouseStart
   9336 		if ( mouseHandled ) {
   9337 			return;
   9338 		}
   9339 
   9340 		this._mouseMoved = false;
   9341 
   9342 		// We may have missed mouseup (out of window)
   9343 		( this._mouseStarted && this._mouseUp( event ) );
   9344 
   9345 		this._mouseDownEvent = event;
   9346 
   9347 		var that = this,
   9348 			btnIsLeft = ( event.which === 1 ),
   9349 
   9350 			// event.target.nodeName works around a bug in IE 8 with
   9351 			// disabled inputs (#7620)
   9352 			elIsCancel = ( typeof this.options.cancel === "string" && event.target.nodeName ?
   9353 				$( event.target ).closest( this.options.cancel ).length : false );
   9354 		if ( !btnIsLeft || elIsCancel || !this._mouseCapture( event ) ) {
   9355 			return true;
   9356 		}
   9357 
   9358 		this.mouseDelayMet = !this.options.delay;
   9359 		if ( !this.mouseDelayMet ) {
   9360 			this._mouseDelayTimer = setTimeout( function() {
   9361 				that.mouseDelayMet = true;
   9362 			}, this.options.delay );
   9363 		}
   9364 
   9365 		if ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) {
   9366 			this._mouseStarted = ( this._mouseStart( event ) !== false );
   9367 			if ( !this._mouseStarted ) {
   9368 				event.preventDefault();
   9369 				return true;
   9370 			}
   9371 		}
   9372 
   9373 		// Click event may never have fired (Gecko & Opera)
   9374 		if ( true === $.data( event.target, this.widgetName + ".preventClickEvent" ) ) {
   9375 			$.removeData( event.target, this.widgetName + ".preventClickEvent" );
   9376 		}
   9377 
   9378 		// These delegates are required to keep context
   9379 		this._mouseMoveDelegate = function( event ) {
   9380 			return that._mouseMove( event );
   9381 		};
   9382 		this._mouseUpDelegate = function( event ) {
   9383 			return that._mouseUp( event );
   9384 		};
   9385 
   9386 		this.document
   9387 			.on( "mousemove." + this.widgetName, this._mouseMoveDelegate )
   9388 			.on( "mouseup." + this.widgetName, this._mouseUpDelegate );
   9389 
   9390 		event.preventDefault();
   9391 
   9392 		mouseHandled = true;
   9393 		return true;
   9394 	},
   9395 
   9396 	_mouseMove: function( event ) {
   9397 
   9398 		// Only check for mouseups outside the document if you've moved inside the document
   9399 		// at least once. This prevents the firing of mouseup in the case of IE<9, which will
   9400 		// fire a mousemove event if content is placed under the cursor. See #7778
   9401 		// Support: IE <9
   9402 		if ( this._mouseMoved ) {
   9403 
   9404 			// IE mouseup check - mouseup happened when mouse was out of window
   9405 			if ( $.ui.ie && ( !document.documentMode || document.documentMode < 9 ) &&
   9406 					!event.button ) {
   9407 				return this._mouseUp( event );
   9408 
   9409 			// Iframe mouseup check - mouseup occurred in another document
   9410 			} else if ( !event.which ) {
   9411 
   9412 				// Support: Safari <=8 - 9
   9413 				// Safari sets which to 0 if you press any of the following keys
   9414 				// during a drag (#14461)
   9415 				if ( event.originalEvent.altKey || event.originalEvent.ctrlKey ||
   9416 						event.originalEvent.metaKey || event.originalEvent.shiftKey ) {
   9417 					this.ignoreMissingWhich = true;
   9418 				} else if ( !this.ignoreMissingWhich ) {
   9419 					return this._mouseUp( event );
   9420 				}
   9421 			}
   9422 		}
   9423 
   9424 		if ( event.which || event.button ) {
   9425 			this._mouseMoved = true;
   9426 		}
   9427 
   9428 		if ( this._mouseStarted ) {
   9429 			this._mouseDrag( event );
   9430 			return event.preventDefault();
   9431 		}
   9432 
   9433 		if ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) {
   9434 			this._mouseStarted =
   9435 				( this._mouseStart( this._mouseDownEvent, event ) !== false );
   9436 			( this._mouseStarted ? this._mouseDrag( event ) : this._mouseUp( event ) );
   9437 		}
   9438 
   9439 		return !this._mouseStarted;
   9440 	},
   9441 
   9442 	_mouseUp: function( event ) {
   9443 		this.document
   9444 			.off( "mousemove." + this.widgetName, this._mouseMoveDelegate )
   9445 			.off( "mouseup." + this.widgetName, this._mouseUpDelegate );
   9446 
   9447 		if ( this._mouseStarted ) {
   9448 			this._mouseStarted = false;
   9449 
   9450 			if ( event.target === this._mouseDownEvent.target ) {
   9451 				$.data( event.target, this.widgetName + ".preventClickEvent", true );
   9452 			}
   9453 
   9454 			this._mouseStop( event );
   9455 		}
   9456 
   9457 		if ( this._mouseDelayTimer ) {
   9458 			clearTimeout( this._mouseDelayTimer );
   9459 			delete this._mouseDelayTimer;
   9460 		}
   9461 
   9462 		this.ignoreMissingWhich = false;
   9463 		mouseHandled = false;
   9464 		event.preventDefault();
   9465 	},
   9466 
   9467 	_mouseDistanceMet: function( event ) {
   9468 		return ( Math.max(
   9469 				Math.abs( this._mouseDownEvent.pageX - event.pageX ),
   9470 				Math.abs( this._mouseDownEvent.pageY - event.pageY )
   9471 			) >= this.options.distance
   9472 		);
   9473 	},
   9474 
   9475 	_mouseDelayMet: function( /* event */ ) {
   9476 		return this.mouseDelayMet;
   9477 	},
   9478 
   9479 	// These are placeholder methods, to be overriden by extending plugin
   9480 	_mouseStart: function( /* event */ ) {},
   9481 	_mouseDrag: function( /* event */ ) {},
   9482 	_mouseStop: function( /* event */ ) {},
   9483 	_mouseCapture: function( /* event */ ) { return true; }
   9484 } );
   9485 
   9486 
   9487 
   9488 
   9489 // $.ui.plugin is deprecated. Use $.widget() extensions instead.
   9490 var plugin = $.ui.plugin = {
   9491 	add: function( module, option, set ) {
   9492 		var i,
   9493 			proto = $.ui[ module ].prototype;
   9494 		for ( i in set ) {
   9495 			proto.plugins[ i ] = proto.plugins[ i ] || [];
   9496 			proto.plugins[ i ].push( [ option, set[ i ] ] );
   9497 		}
   9498 	},
   9499 	call: function( instance, name, args, allowDisconnected ) {
   9500 		var i,
   9501 			set = instance.plugins[ name ];
   9502 
   9503 		if ( !set ) {
   9504 			return;
   9505 		}
   9506 
   9507 		if ( !allowDisconnected && ( !instance.element[ 0 ].parentNode ||
   9508 				instance.element[ 0 ].parentNode.nodeType === 11 ) ) {
   9509 			return;
   9510 		}
   9511 
   9512 		for ( i = 0; i < set.length; i++ ) {
   9513 			if ( instance.options[ set[ i ][ 0 ] ] ) {
   9514 				set[ i ][ 1 ].apply( instance.element, args );
   9515 			}
   9516 		}
   9517 	}
   9518 };
   9519 
   9520 
   9521 
   9522 var safeBlur = $.ui.safeBlur = function( element ) {
   9523 
   9524 	// Support: IE9 - 10 only
   9525 	// If the <body> is blurred, IE will switch windows, see #9420
   9526 	if ( element && element.nodeName.toLowerCase() !== "body" ) {
   9527 		$( element ).trigger( "blur" );
   9528 	}
   9529 };
   9530 
   9531 
   9532 /*!
   9533  * jQuery UI Draggable 1.12.1
   9534  * http://jqueryui.com
   9535  *
   9536  * Copyright jQuery Foundation and other contributors
   9537  * Released under the MIT license.
   9538  * http://jquery.org/license
   9539  */
   9540 
   9541 //>>label: Draggable
   9542 //>>group: Interactions
   9543 //>>description: Enables dragging functionality for any element.
   9544 //>>docs: http://api.jqueryui.com/draggable/
   9545 //>>demos: http://jqueryui.com/draggable/
   9546 //>>css.structure: ../../themes/base/draggable.css
   9547 
   9548 
   9549 
   9550 $.widget( "ui.draggable", $.ui.mouse, {
   9551 	version: "1.12.1",
   9552 	widgetEventPrefix: "drag",
   9553 	options: {
   9554 		addClasses: true,
   9555 		appendTo: "parent",
   9556 		axis: false,
   9557 		connectToSortable: false,
   9558 		containment: false,
   9559 		cursor: "auto",
   9560 		cursorAt: false,
   9561 		grid: false,
   9562 		handle: false,
   9563 		helper: "original",
   9564 		iframeFix: false,
   9565 		opacity: false,
   9566 		refreshPositions: false,
   9567 		revert: false,
   9568 		revertDuration: 500,
   9569 		scope: "default",
   9570 		scroll: true,
   9571 		scrollSensitivity: 20,
   9572 		scrollSpeed: 20,
   9573 		snap: false,
   9574 		snapMode: "both",
   9575 		snapTolerance: 20,
   9576 		stack: false,
   9577 		zIndex: false,
   9578 
   9579 		// Callbacks
   9580 		drag: null,
   9581 		start: null,
   9582 		stop: null
   9583 	},
   9584 	_create: function() {
   9585 
   9586 		if ( this.options.helper === "original" ) {
   9587 			this._setPositionRelative();
   9588 		}
   9589 		if ( this.options.addClasses ) {
   9590 			this._addClass( "ui-draggable" );
   9591 		}
   9592 		this._setHandleClassName();
   9593 
   9594 		this._mouseInit();
   9595 	},
   9596 
   9597 	_setOption: function( key, value ) {
   9598 		this._super( key, value );
   9599 		if ( key === "handle" ) {
   9600 			this._removeHandleClassName();
   9601 			this._setHandleClassName();
   9602 		}
   9603 	},
   9604 
   9605 	_destroy: function() {
   9606 		if ( ( this.helper || this.element ).is( ".ui-draggable-dragging" ) ) {
   9607 			this.destroyOnClear = true;
   9608 			return;
   9609 		}
   9610 		this._removeHandleClassName();
   9611 		this._mouseDestroy();
   9612 	},
   9613 
   9614 	_mouseCapture: function( event ) {
   9615 		var o = this.options;
   9616 
   9617 		// Among others, prevent a drag on a resizable-handle
   9618 		if ( this.helper || o.disabled ||
   9619 				$( event.target ).closest( ".ui-resizable-handle" ).length > 0 ) {
   9620 			return false;
   9621 		}
   9622 
   9623 		//Quit if we're not on a valid handle
   9624 		this.handle = this._getHandle( event );
   9625 		if ( !this.handle ) {
   9626 			return false;
   9627 		}
   9628 
   9629 		this._blurActiveElement( event );
   9630 
   9631 		this._blockFrames( o.iframeFix === true ? "iframe" : o.iframeFix );
   9632 
   9633 		return true;
   9634 
   9635 	},
   9636 
   9637 	_blockFrames: function( selector ) {
   9638 		this.iframeBlocks = this.document.find( selector ).map( function() {
   9639 			var iframe = $( this );
   9640 
   9641 			return $( "<div>" )
   9642 				.css( "position", "absolute" )
   9643 				.appendTo( iframe.parent() )
   9644 				.outerWidth( iframe.outerWidth() )
   9645 				.outerHeight( iframe.outerHeight() )
   9646 				.offset( iframe.offset() )[ 0 ];
   9647 		} );
   9648 	},
   9649 
   9650 	_unblockFrames: function() {
   9651 		if ( this.iframeBlocks ) {
   9652 			this.iframeBlocks.remove();
   9653 			delete this.iframeBlocks;
   9654 		}
   9655 	},
   9656 
   9657 	_blurActiveElement: function( event ) {
   9658 		var activeElement = $.ui.safeActiveElement( this.document[ 0 ] ),
   9659 			target = $( event.target );
   9660 
   9661 		// Don't blur if the event occurred on an element that is within
   9662 		// the currently focused element
   9663 		// See #10527, #12472
   9664 		if ( target.closest( activeElement ).length ) {
   9665 			return;
   9666 		}
   9667 
   9668 		// Blur any element that currently has focus, see #4261
   9669 		$.ui.safeBlur( activeElement );
   9670 	},
   9671 
   9672 	_mouseStart: function( event ) {
   9673 
   9674 		var o = this.options;
   9675 
   9676 		//Create and append the visible helper
   9677 		this.helper = this._createHelper( event );
   9678 
   9679 		this._addClass( this.helper, "ui-draggable-dragging" );
   9680 
   9681 		//Cache the helper size
   9682 		this._cacheHelperProportions();
   9683 
   9684 		//If ddmanager is used for droppables, set the global draggable
   9685 		if ( $.ui.ddmanager ) {
   9686 			$.ui.ddmanager.current = this;
   9687 		}
   9688 
   9689 		/*
   9690 		 * - Position generation -
   9691 		 * This block generates everything position related - it's the core of draggables.
   9692 		 */
   9693 
   9694 		//Cache the margins of the original element
   9695 		this._cacheMargins();
   9696 
   9697 		//Store the helper's css position
   9698 		this.cssPosition = this.helper.css( "position" );
   9699 		this.scrollParent = this.helper.scrollParent( true );
   9700 		this.offsetParent = this.helper.offsetParent();
   9701 		this.hasFixedAncestor = this.helper.parents().filter( function() {
   9702 				return $( this ).css( "position" ) === "fixed";
   9703 			} ).length > 0;
   9704 
   9705 		//The element's absolute position on the page minus margins
   9706 		this.positionAbs = this.element.offset();
   9707 		this._refreshOffsets( event );
   9708 
   9709 		//Generate the original position
   9710 		this.originalPosition = this.position = this._generatePosition( event, false );
   9711 		this.originalPageX = event.pageX;
   9712 		this.originalPageY = event.pageY;
   9713 
   9714 		//Adjust the mouse offset relative to the helper if "cursorAt" is supplied
   9715 		( o.cursorAt && this._adjustOffsetFromHelper( o.cursorAt ) );
   9716 
   9717 		//Set a containment if given in the options
   9718 		this._setContainment();
   9719 
   9720 		//Trigger event + callbacks
   9721 		if ( this._trigger( "start", event ) === false ) {
   9722 			this._clear();
   9723 			return false;
   9724 		}
   9725 
   9726 		//Recache the helper size
   9727 		this._cacheHelperProportions();
   9728 
   9729 		//Prepare the droppable offsets
   9730 		if ( $.ui.ddmanager && !o.dropBehaviour ) {
   9731 			$.ui.ddmanager.prepareOffsets( this, event );
   9732 		}
   9733 
   9734 		// Execute the drag once - this causes the helper not to be visible before getting its
   9735 		// correct position
   9736 		this._mouseDrag( event, true );
   9737 
   9738 		// If the ddmanager is used for droppables, inform the manager that dragging has started
   9739 		// (see #5003)
   9740 		if ( $.ui.ddmanager ) {
   9741 			$.ui.ddmanager.dragStart( this, event );
   9742 		}
   9743 
   9744 		return true;
   9745 	},
   9746 
   9747 	_refreshOffsets: function( event ) {
   9748 		this.offset = {
   9749 			top: this.positionAbs.top - this.margins.top,
   9750 			left: this.positionAbs.left - this.margins.left,
   9751 			scroll: false,
   9752 			parent: this._getParentOffset(),
   9753 			relative: this._getRelativeOffset()
   9754 		};
   9755 
   9756 		this.offset.click = {
   9757 			left: event.pageX - this.offset.left,
   9758 			top: event.pageY - this.offset.top
   9759 		};
   9760 	},
   9761 
   9762 	_mouseDrag: function( event, noPropagation ) {
   9763 
   9764 		// reset any necessary cached properties (see #5009)
   9765 		if ( this.hasFixedAncestor ) {
   9766 			this.offset.parent = this._getParentOffset();
   9767 		}
   9768 
   9769 		//Compute the helpers position
   9770 		this.position = this._generatePosition( event, true );
   9771 		this.positionAbs = this._convertPositionTo( "absolute" );
   9772 
   9773 		//Call plugins and callbacks and use the resulting position if something is returned
   9774 		if ( !noPropagation ) {
   9775 			var ui = this._uiHash();
   9776 			if ( this._trigger( "drag", event, ui ) === false ) {
   9777 				this._mouseUp( new $.Event( "mouseup", event ) );
   9778 				return false;
   9779 			}
   9780 			this.position = ui.position;
   9781 		}
   9782 
   9783 		this.helper[ 0 ].style.left = this.position.left + "px";
   9784 		this.helper[ 0 ].style.top = this.position.top + "px";
   9785 
   9786 		if ( $.ui.ddmanager ) {
   9787 			$.ui.ddmanager.drag( this, event );
   9788 		}
   9789 
   9790 		return false;
   9791 	},
   9792 
   9793 	_mouseStop: function( event ) {
   9794 
   9795 		//If we are using droppables, inform the manager about the drop
   9796 		var that = this,
   9797 			dropped = false;
   9798 		if ( $.ui.ddmanager && !this.options.dropBehaviour ) {
   9799 			dropped = $.ui.ddmanager.drop( this, event );
   9800 		}
   9801 
   9802 		//if a drop comes from outside (a sortable)
   9803 		if ( this.dropped ) {
   9804 			dropped = this.dropped;
   9805 			this.dropped = false;
   9806 		}
   9807 
   9808 		if ( ( this.options.revert === "invalid" && !dropped ) ||
   9809 				( this.options.revert === "valid" && dropped ) ||
   9810 				this.options.revert === true || ( $.isFunction( this.options.revert ) &&
   9811 				this.options.revert.call( this.element, dropped ) )
   9812 		) {
   9813 			$( this.helper ).animate(
   9814 				this.originalPosition,
   9815 				parseInt( this.options.revertDuration, 10 ),
   9816 				function() {
   9817 					if ( that._trigger( "stop", event ) !== false ) {
   9818 						that._clear();
   9819 					}
   9820 				}
   9821 			);
   9822 		} else {
   9823 			if ( this._trigger( "stop", event ) !== false ) {
   9824 				this._clear();
   9825 			}
   9826 		}
   9827 
   9828 		return false;
   9829 	},
   9830 
   9831 	_mouseUp: function( event ) {
   9832 		this._unblockFrames();
   9833 
   9834 		// If the ddmanager is used for droppables, inform the manager that dragging has stopped
   9835 		// (see #5003)
   9836 		if ( $.ui.ddmanager ) {
   9837 			$.ui.ddmanager.dragStop( this, event );
   9838 		}
   9839 
   9840 		// Only need to focus if the event occurred on the draggable itself, see #10527
   9841 		if ( this.handleElement.is( event.target ) ) {
   9842 
   9843 			// The interaction is over; whether or not the click resulted in a drag,
   9844 			// focus the element
   9845 			this.element.trigger( "focus" );
   9846 		}
   9847 
   9848 		return $.ui.mouse.prototype._mouseUp.call( this, event );
   9849 	},
   9850 
   9851 	cancel: function() {
   9852 
   9853 		if ( this.helper.is( ".ui-draggable-dragging" ) ) {
   9854 			this._mouseUp( new $.Event( "mouseup", { target: this.element[ 0 ] } ) );
   9855 		} else {
   9856 			this._clear();
   9857 		}
   9858 
   9859 		return this;
   9860 
   9861 	},
   9862 
   9863 	_getHandle: function( event ) {
   9864 		return this.options.handle ?
   9865 			!!$( event.target ).closest( this.element.find( this.options.handle ) ).length :
   9866 			true;
   9867 	},
   9868 
   9869 	_setHandleClassName: function() {
   9870 		this.handleElement = this.options.handle ?
   9871 			this.element.find( this.options.handle ) : this.element;
   9872 		this._addClass( this.handleElement, "ui-draggable-handle" );
   9873 	},
   9874 
   9875 	_removeHandleClassName: function() {
   9876 		this._removeClass( this.handleElement, "ui-draggable-handle" );
   9877 	},
   9878 
   9879 	_createHelper: function( event ) {
   9880 
   9881 		var o = this.options,
   9882 			helperIsFunction = $.isFunction( o.helper ),
   9883 			helper = helperIsFunction ?
   9884 				$( o.helper.apply( this.element[ 0 ], [ event ] ) ) :
   9885 				( o.helper === "clone" ?
   9886 					this.element.clone().removeAttr( "id" ) :
   9887 					this.element );
   9888 
   9889 		if ( !helper.parents( "body" ).length ) {
   9890 			helper.appendTo( ( o.appendTo === "parent" ?
   9891 				this.element[ 0 ].parentNode :
   9892 				o.appendTo ) );
   9893 		}
   9894 
   9895 		// Http://bugs.jqueryui.com/ticket/9446
   9896 		// a helper function can return the original element
   9897 		// which wouldn't have been set to relative in _create
   9898 		if ( helperIsFunction && helper[ 0 ] === this.element[ 0 ] ) {
   9899 			this._setPositionRelative();
   9900 		}
   9901 
   9902 		if ( helper[ 0 ] !== this.element[ 0 ] &&
   9903 				!( /(fixed|absolute)/ ).test( helper.css( "position" ) ) ) {
   9904 			helper.css( "position", "absolute" );
   9905 		}
   9906 
   9907 		return helper;
   9908 
   9909 	},
   9910 
   9911 	_setPositionRelative: function() {
   9912 		if ( !( /^(?:r|a|f)/ ).test( this.element.css( "position" ) ) ) {
   9913 			this.element[ 0 ].style.position = "relative";
   9914 		}
   9915 	},
   9916 
   9917 	_adjustOffsetFromHelper: function( obj ) {
   9918 		if ( typeof obj === "string" ) {
   9919 			obj = obj.split( " " );
   9920 		}
   9921 		if ( $.isArray( obj ) ) {
   9922 			obj = { left: +obj[ 0 ], top: +obj[ 1 ] || 0 };
   9923 		}
   9924 		if ( "left" in obj ) {
   9925 			this.offset.click.left = obj.left + this.margins.left;
   9926 		}
   9927 		if ( "right" in obj ) {
   9928 			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
   9929 		}
   9930 		if ( "top" in obj ) {
   9931 			this.offset.click.top = obj.top + this.margins.top;
   9932 		}
   9933 		if ( "bottom" in obj ) {
   9934 			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
   9935 		}
   9936 	},
   9937 
   9938 	_isRootNode: function( element ) {
   9939 		return ( /(html|body)/i ).test( element.tagName ) || element === this.document[ 0 ];
   9940 	},
   9941 
   9942 	_getParentOffset: function() {
   9943 
   9944 		//Get the offsetParent and cache its position
   9945 		var po = this.offsetParent.offset(),
   9946 			document = this.document[ 0 ];
   9947 
   9948 		// This is a special case where we need to modify a offset calculated on start, since the
   9949 		// following happened:
   9950 		// 1. The position of the helper is absolute, so it's position is calculated based on the
   9951 		// next positioned parent
   9952 		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't
   9953 		// the document, which means that the scroll is included in the initial calculation of the
   9954 		// offset of the parent, and never recalculated upon drag
   9955 		if ( this.cssPosition === "absolute" && this.scrollParent[ 0 ] !== document &&
   9956 				$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) {
   9957 			po.left += this.scrollParent.scrollLeft();
   9958 			po.top += this.scrollParent.scrollTop();
   9959 		}
   9960 
   9961 		if ( this._isRootNode( this.offsetParent[ 0 ] ) ) {
   9962 			po = { top: 0, left: 0 };
   9963 		}
   9964 
   9965 		return {
   9966 			top: po.top + ( parseInt( this.offsetParent.css( "borderTopWidth" ), 10 ) || 0 ),
   9967 			left: po.left + ( parseInt( this.offsetParent.css( "borderLeftWidth" ), 10 ) || 0 )
   9968 		};
   9969 
   9970 	},
   9971 
   9972 	_getRelativeOffset: function() {
   9973 		if ( this.cssPosition !== "relative" ) {
   9974 			return { top: 0, left: 0 };
   9975 		}
   9976 
   9977 		var p = this.element.position(),
   9978 			scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );
   9979 
   9980 		return {
   9981 			top: p.top - ( parseInt( this.helper.css( "top" ), 10 ) || 0 ) +
   9982 				( !scrollIsRootNode ? this.scrollParent.scrollTop() : 0 ),
   9983 			left: p.left - ( parseInt( this.helper.css( "left" ), 10 ) || 0 ) +
   9984 				( !scrollIsRootNode ? this.scrollParent.scrollLeft() : 0 )
   9985 		};
   9986 
   9987 	},
   9988 
   9989 	_cacheMargins: function() {
   9990 		this.margins = {
   9991 			left: ( parseInt( this.element.css( "marginLeft" ), 10 ) || 0 ),
   9992 			top: ( parseInt( this.element.css( "marginTop" ), 10 ) || 0 ),
   9993 			right: ( parseInt( this.element.css( "marginRight" ), 10 ) || 0 ),
   9994 			bottom: ( parseInt( this.element.css( "marginBottom" ), 10 ) || 0 )
   9995 		};
   9996 	},
   9997 
   9998 	_cacheHelperProportions: function() {
   9999 		this.helperProportions = {
  10000 			width: this.helper.outerWidth(),
  10001 			height: this.helper.outerHeight()
  10002 		};
  10003 	},
  10004 
  10005 	_setContainment: function() {
  10006 
  10007 		var isUserScrollable, c, ce,
  10008 			o = this.options,
  10009 			document = this.document[ 0 ];
  10010 
  10011 		this.relativeContainer = null;
  10012 
  10013 		if ( !o.containment ) {
  10014 			this.containment = null;
  10015 			return;
  10016 		}
  10017 
  10018 		if ( o.containment === "window" ) {
  10019 			this.containment = [
  10020 				$( window ).scrollLeft() - this.offset.relative.left - this.offset.parent.left,
  10021 				$( window ).scrollTop() - this.offset.relative.top - this.offset.parent.top,
  10022 				$( window ).scrollLeft() + $( window ).width() -
  10023 					this.helperProportions.width - this.margins.left,
  10024 				$( window ).scrollTop() +
  10025 					( $( window ).height() || document.body.parentNode.scrollHeight ) -
  10026 					this.helperProportions.height - this.margins.top
  10027 			];
  10028 			return;
  10029 		}
  10030 
  10031 		if ( o.containment === "document" ) {
  10032 			this.containment = [
  10033 				0,
  10034 				0,
  10035 				$( document ).width() - this.helperProportions.width - this.margins.left,
  10036 				( $( document ).height() || document.body.parentNode.scrollHeight ) -
  10037 					this.helperProportions.height - this.margins.top
  10038 			];
  10039 			return;
  10040 		}
  10041 
  10042 		if ( o.containment.constructor === Array ) {
  10043 			this.containment = o.containment;
  10044 			return;
  10045 		}
  10046 
  10047 		if ( o.containment === "parent" ) {
  10048 			o.containment = this.helper[ 0 ].parentNode;
  10049 		}
  10050 
  10051 		c = $( o.containment );
  10052 		ce = c[ 0 ];
  10053 
  10054 		if ( !ce ) {
  10055 			return;
  10056 		}
  10057 
  10058 		isUserScrollable = /(scroll|auto)/.test( c.css( "overflow" ) );
  10059 
  10060 		this.containment = [
  10061 			( parseInt( c.css( "borderLeftWidth" ), 10 ) || 0 ) +
  10062 				( parseInt( c.css( "paddingLeft" ), 10 ) || 0 ),
  10063 			( parseInt( c.css( "borderTopWidth" ), 10 ) || 0 ) +
  10064 				( parseInt( c.css( "paddingTop" ), 10 ) || 0 ),
  10065 			( isUserScrollable ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) -
  10066 				( parseInt( c.css( "borderRightWidth" ), 10 ) || 0 ) -
  10067 				( parseInt( c.css( "paddingRight" ), 10 ) || 0 ) -
  10068 				this.helperProportions.width -
  10069 				this.margins.left -
  10070 				this.margins.right,
  10071 			( isUserScrollable ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) -
  10072 				( parseInt( c.css( "borderBottomWidth" ), 10 ) || 0 ) -
  10073 				( parseInt( c.css( "paddingBottom" ), 10 ) || 0 ) -
  10074 				this.helperProportions.height -
  10075 				this.margins.top -
  10076 				this.margins.bottom
  10077 		];
  10078 		this.relativeContainer = c;
  10079 	},
  10080 
  10081 	_convertPositionTo: function( d, pos ) {
  10082 
  10083 		if ( !pos ) {
  10084 			pos = this.position;
  10085 		}
  10086 
  10087 		var mod = d === "absolute" ? 1 : -1,
  10088 			scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );
  10089 
  10090 		return {
  10091 			top: (
  10092 
  10093 				// The absolute mouse position
  10094 				pos.top	+
  10095 
  10096 				// Only for relative positioned nodes: Relative offset from element to offset parent
  10097 				this.offset.relative.top * mod +
  10098 
  10099 				// The offsetParent's offset without borders (offset + border)
  10100 				this.offset.parent.top * mod -
  10101 				( ( this.cssPosition === "fixed" ?
  10102 					-this.offset.scroll.top :
  10103 					( scrollIsRootNode ? 0 : this.offset.scroll.top ) ) * mod )
  10104 			),
  10105 			left: (
  10106 
  10107 				// The absolute mouse position
  10108 				pos.left +
  10109 
  10110 				// Only for relative positioned nodes: Relative offset from element to offset parent
  10111 				this.offset.relative.left * mod +
  10112 
  10113 				// The offsetParent's offset without borders (offset + border)
  10114 				this.offset.parent.left * mod	-
  10115 				( ( this.cssPosition === "fixed" ?
  10116 					-this.offset.scroll.left :
  10117 					( scrollIsRootNode ? 0 : this.offset.scroll.left ) ) * mod )
  10118 			)
  10119 		};
  10120 
  10121 	},
  10122 
  10123 	_generatePosition: function( event, constrainPosition ) {
  10124 
  10125 		var containment, co, top, left,
  10126 			o = this.options,
  10127 			scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ),
  10128 			pageX = event.pageX,
  10129 			pageY = event.pageY;
  10130 
  10131 		// Cache the scroll
  10132 		if ( !scrollIsRootNode || !this.offset.scroll ) {
  10133 			this.offset.scroll = {
  10134 				top: this.scrollParent.scrollTop(),
  10135 				left: this.scrollParent.scrollLeft()
  10136 			};
  10137 		}
  10138 
  10139 		/*
  10140 		 * - Position constraining -
  10141 		 * Constrain the position to a mix of grid, containment.
  10142 		 */
  10143 
  10144 		// If we are not dragging yet, we won't check for options
  10145 		if ( constrainPosition ) {
  10146 			if ( this.containment ) {
  10147 				if ( this.relativeContainer ) {
  10148 					co = this.relativeContainer.offset();
  10149 					containment = [
  10150 						this.containment[ 0 ] + co.left,
  10151 						this.containment[ 1 ] + co.top,
  10152 						this.containment[ 2 ] + co.left,
  10153 						this.containment[ 3 ] + co.top
  10154 					];
  10155 				} else {
  10156 					containment = this.containment;
  10157 				}
  10158 
  10159 				if ( event.pageX - this.offset.click.left < containment[ 0 ] ) {
  10160 					pageX = containment[ 0 ] + this.offset.click.left;
  10161 				}
  10162 				if ( event.pageY - this.offset.click.top < containment[ 1 ] ) {
  10163 					pageY = containment[ 1 ] + this.offset.click.top;
  10164 				}
  10165 				if ( event.pageX - this.offset.click.left > containment[ 2 ] ) {
  10166 					pageX = containment[ 2 ] + this.offset.click.left;
  10167 				}
  10168 				if ( event.pageY - this.offset.click.top > containment[ 3 ] ) {
  10169 					pageY = containment[ 3 ] + this.offset.click.top;
  10170 				}
  10171 			}
  10172 
  10173 			if ( o.grid ) {
  10174 
  10175 				//Check for grid elements set to 0 to prevent divide by 0 error causing invalid
  10176 				// argument errors in IE (see ticket #6950)
  10177 				top = o.grid[ 1 ] ? this.originalPageY + Math.round( ( pageY -
  10178 					this.originalPageY ) / o.grid[ 1 ] ) * o.grid[ 1 ] : this.originalPageY;
  10179 				pageY = containment ? ( ( top - this.offset.click.top >= containment[ 1 ] ||
  10180 					top - this.offset.click.top > containment[ 3 ] ) ?
  10181 						top :
  10182 						( ( top - this.offset.click.top >= containment[ 1 ] ) ?
  10183 							top - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) : top;
  10184 
  10185 				left = o.grid[ 0 ] ? this.originalPageX +
  10186 					Math.round( ( pageX - this.originalPageX ) / o.grid[ 0 ] ) * o.grid[ 0 ] :
  10187 					this.originalPageX;
  10188 				pageX = containment ? ( ( left - this.offset.click.left >= containment[ 0 ] ||
  10189 					left - this.offset.click.left > containment[ 2 ] ) ?
  10190 						left :
  10191 						( ( left - this.offset.click.left >= containment[ 0 ] ) ?
  10192 							left - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) : left;
  10193 			}
  10194 
  10195 			if ( o.axis === "y" ) {
  10196 				pageX = this.originalPageX;
  10197 			}
  10198 
  10199 			if ( o.axis === "x" ) {
  10200 				pageY = this.originalPageY;
  10201 			}
  10202 		}
  10203 
  10204 		return {
  10205 			top: (
  10206 
  10207 				// The absolute mouse position
  10208 				pageY -
  10209 
  10210 				// Click offset (relative to the element)
  10211 				this.offset.click.top -
  10212 
  10213 				// Only for relative positioned nodes: Relative offset from element to offset parent
  10214 				this.offset.relative.top -
  10215 
  10216 				// The offsetParent's offset without borders (offset + border)
  10217 				this.offset.parent.top +
  10218 				( this.cssPosition === "fixed" ?
  10219 					-this.offset.scroll.top :
  10220 					( scrollIsRootNode ? 0 : this.offset.scroll.top ) )
  10221 			),
  10222 			left: (
  10223 
  10224 				// The absolute mouse position
  10225 				pageX -
  10226 
  10227 				// Click offset (relative to the element)
  10228 				this.offset.click.left -
  10229 
  10230 				// Only for relative positioned nodes: Relative offset from element to offset parent
  10231 				this.offset.relative.left -
  10232 
  10233 				// The offsetParent's offset without borders (offset + border)
  10234 				this.offset.parent.left +
  10235 				( this.cssPosition === "fixed" ?
  10236 					-this.offset.scroll.left :
  10237 					( scrollIsRootNode ? 0 : this.offset.scroll.left ) )
  10238 			)
  10239 		};
  10240 
  10241 	},
  10242 
  10243 	_clear: function() {
  10244 		this._removeClass( this.helper, "ui-draggable-dragging" );
  10245 		if ( this.helper[ 0 ] !== this.element[ 0 ] && !this.cancelHelperRemoval ) {
  10246 			this.helper.remove();
  10247 		}
  10248 		this.helper = null;
  10249 		this.cancelHelperRemoval = false;
  10250 		if ( this.destroyOnClear ) {
  10251 			this.destroy();
  10252 		}
  10253 	},
  10254 
  10255 	// From now on bulk stuff - mainly helpers
  10256 
  10257 	_trigger: function( type, event, ui ) {
  10258 		ui = ui || this._uiHash();
  10259 		$.ui.plugin.call( this, type, [ event, ui, this ], true );
  10260 
  10261 		// Absolute position and offset (see #6884 ) have to be recalculated after plugins
  10262 		if ( /^(drag|start|stop)/.test( type ) ) {
  10263 			this.positionAbs = this._convertPositionTo( "absolute" );
  10264 			ui.offset = this.positionAbs;
  10265 		}
  10266 		return $.Widget.prototype._trigger.call( this, type, event, ui );
  10267 	},
  10268 
  10269 	plugins: {},
  10270 
  10271 	_uiHash: function() {
  10272 		return {
  10273 			helper: this.helper,
  10274 			position: this.position,
  10275 			originalPosition: this.originalPosition,
  10276 			offset: this.positionAbs
  10277 		};
  10278 	}
  10279 
  10280 } );
  10281 
  10282 $.ui.plugin.add( "draggable", "connectToSortable", {
  10283 	start: function( event, ui, draggable ) {
  10284 		var uiSortable = $.extend( {}, ui, {
  10285 			item: draggable.element
  10286 		} );
  10287 
  10288 		draggable.sortables = [];
  10289 		$( draggable.options.connectToSortable ).each( function() {
  10290 			var sortable = $( this ).sortable( "instance" );
  10291 
  10292 			if ( sortable && !sortable.options.disabled ) {
  10293 				draggable.sortables.push( sortable );
  10294 
  10295 				// RefreshPositions is called at drag start to refresh the containerCache
  10296 				// which is used in drag. This ensures it's initialized and synchronized
  10297 				// with any changes that might have happened on the page since initialization.
  10298 				sortable.refreshPositions();
  10299 				sortable._trigger( "activate", event, uiSortable );
  10300 			}
  10301 		} );
  10302 	},
  10303 	stop: function( event, ui, draggable ) {
  10304 		var uiSortable = $.extend( {}, ui, {
  10305 			item: draggable.element
  10306 		} );
  10307 
  10308 		draggable.cancelHelperRemoval = false;
  10309 
  10310 		$.each( draggable.sortables, function() {
  10311 			var sortable = this;
  10312 
  10313 			if ( sortable.isOver ) {
  10314 				sortable.isOver = 0;
  10315 
  10316 				// Allow this sortable to handle removing the helper
  10317 				draggable.cancelHelperRemoval = true;
  10318 				sortable.cancelHelperRemoval = false;
  10319 
  10320 				// Use _storedCSS To restore properties in the sortable,
  10321 				// as this also handles revert (#9675) since the draggable
  10322 				// may have modified them in unexpected ways (#8809)
  10323 				sortable._storedCSS = {
  10324 					position: sortable.placeholder.css( "position" ),
  10325 					top: sortable.placeholder.css( "top" ),
  10326 					left: sortable.placeholder.css( "left" )
  10327 				};
  10328 
  10329 				sortable._mouseStop( event );
  10330 
  10331 				// Once drag has ended, the sortable should return to using
  10332 				// its original helper, not the shared helper from draggable
  10333 				sortable.options.helper = sortable.options._helper;
  10334 			} else {
  10335 
  10336 				// Prevent this Sortable from removing the helper.
  10337 				// However, don't set the draggable to remove the helper
  10338 				// either as another connected Sortable may yet handle the removal.
  10339 				sortable.cancelHelperRemoval = true;
  10340 
  10341 				sortable._trigger( "deactivate", event, uiSortable );
  10342 			}
  10343 		} );
  10344 	},
  10345 	drag: function( event, ui, draggable ) {
  10346 		$.each( draggable.sortables, function() {
  10347 			var innermostIntersecting = false,
  10348 				sortable = this;
  10349 
  10350 			// Copy over variables that sortable's _intersectsWith uses
  10351 			sortable.positionAbs = draggable.positionAbs;
  10352 			sortable.helperProportions = draggable.helperProportions;
  10353 			sortable.offset.click = draggable.offset.click;
  10354 
  10355 			if ( sortable._intersectsWith( sortable.containerCache ) ) {
  10356 				innermostIntersecting = true;
  10357 
  10358 				$.each( draggable.sortables, function() {
  10359 
  10360 					// Copy over variables that sortable's _intersectsWith uses
  10361 					this.positionAbs = draggable.positionAbs;
  10362 					this.helperProportions = draggable.helperProportions;
  10363 					this.offset.click = draggable.offset.click;
  10364 
  10365 					if ( this !== sortable &&
  10366 							this._intersectsWith( this.containerCache ) &&
  10367 							$.contains( sortable.element[ 0 ], this.element[ 0 ] ) ) {
  10368 						innermostIntersecting = false;
  10369 					}
  10370 
  10371 					return innermostIntersecting;
  10372 				} );
  10373 			}
  10374 
  10375 			if ( innermostIntersecting ) {
  10376 
  10377 				// If it intersects, we use a little isOver variable and set it once,
  10378 				// so that the move-in stuff gets fired only once.
  10379 				if ( !sortable.isOver ) {
  10380 					sortable.isOver = 1;
  10381 
  10382 					// Store draggable's parent in case we need to reappend to it later.
  10383 					draggable._parent = ui.helper.parent();
  10384 
  10385 					sortable.currentItem = ui.helper
  10386 						.appendTo( sortable.element )
  10387 						.data( "ui-sortable-item", true );
  10388 
  10389 					// Store helper option to later restore it
  10390 					sortable.options._helper = sortable.options.helper;
  10391 
  10392 					sortable.options.helper = function() {
  10393 						return ui.helper[ 0 ];
  10394 					};
  10395 
  10396 					// Fire the start events of the sortable with our passed browser event,
  10397 					// and our own helper (so it doesn't create a new one)
  10398 					event.target = sortable.currentItem[ 0 ];
  10399 					sortable._mouseCapture( event, true );
  10400 					sortable._mouseStart( event, true, true );
  10401 
  10402 					// Because the browser event is way off the new appended portlet,
  10403 					// modify necessary variables to reflect the changes
  10404 					sortable.offset.click.top = draggable.offset.click.top;
  10405 					sortable.offset.click.left = draggable.offset.click.left;
  10406 					sortable.offset.parent.left -= draggable.offset.parent.left -
  10407 						sortable.offset.parent.left;
  10408 					sortable.offset.parent.top -= draggable.offset.parent.top -
  10409 						sortable.offset.parent.top;
  10410 
  10411 					draggable._trigger( "toSortable", event );
  10412 
  10413 					// Inform draggable that the helper is in a valid drop zone,
  10414 					// used solely in the revert option to handle "valid/invalid".
  10415 					draggable.dropped = sortable.element;
  10416 
  10417 					// Need to refreshPositions of all sortables in the case that
  10418 					// adding to one sortable changes the location of the other sortables (#9675)
  10419 					$.each( draggable.sortables, function() {
  10420 						this.refreshPositions();
  10421 					} );
  10422 
  10423 					// Hack so receive/update callbacks work (mostly)
  10424 					draggable.currentItem = draggable.element;
  10425 					sortable.fromOutside = draggable;
  10426 				}
  10427 
  10428 				if ( sortable.currentItem ) {
  10429 					sortable._mouseDrag( event );
  10430 
  10431 					// Copy the sortable's position because the draggable's can potentially reflect
  10432 					// a relative position, while sortable is always absolute, which the dragged
  10433 					// element has now become. (#8809)
  10434 					ui.position = sortable.position;
  10435 				}
  10436 			} else {
  10437 
  10438 				// If it doesn't intersect with the sortable, and it intersected before,
  10439 				// we fake the drag stop of the sortable, but make sure it doesn't remove
  10440 				// the helper by using cancelHelperRemoval.
  10441 				if ( sortable.isOver ) {
  10442 
  10443 					sortable.isOver = 0;
  10444 					sortable.cancelHelperRemoval = true;
  10445 
  10446 					// Calling sortable's mouseStop would trigger a revert,
  10447 					// so revert must be temporarily false until after mouseStop is called.
  10448 					sortable.options._revert = sortable.options.revert;
  10449 					sortable.options.revert = false;
  10450 
  10451 					sortable._trigger( "out", event, sortable._uiHash( sortable ) );
  10452 					sortable._mouseStop( event, true );
  10453 
  10454 					// Restore sortable behaviors that were modfied
  10455 					// when the draggable entered the sortable area (#9481)
  10456 					sortable.options.revert = sortable.options._revert;
  10457 					sortable.options.helper = sortable.options._helper;
  10458 
  10459 					if ( sortable.placeholder ) {
  10460 						sortable.placeholder.remove();
  10461 					}
  10462 
  10463 					// Restore and recalculate the draggable's offset considering the sortable
  10464 					// may have modified them in unexpected ways. (#8809, #10669)
  10465 					ui.helper.appendTo( draggable._parent );
  10466 					draggable._refreshOffsets( event );
  10467 					ui.position = draggable._generatePosition( event, true );
  10468 
  10469 					draggable._trigger( "fromSortable", event );
  10470 
  10471 					// Inform draggable that the helper is no longer in a valid drop zone
  10472 					draggable.dropped = false;
  10473 
  10474 					// Need to refreshPositions of all sortables just in case removing
  10475 					// from one sortable changes the location of other sortables (#9675)
  10476 					$.each( draggable.sortables, function() {
  10477 						this.refreshPositions();
  10478 					} );
  10479 				}
  10480 			}
  10481 		} );
  10482 	}
  10483 } );
  10484 
  10485 $.ui.plugin.add( "draggable", "cursor", {
  10486 	start: function( event, ui, instance ) {
  10487 		var t = $( "body" ),
  10488 			o = instance.options;
  10489 
  10490 		if ( t.css( "cursor" ) ) {
  10491 			o._cursor = t.css( "cursor" );
  10492 		}
  10493 		t.css( "cursor", o.cursor );
  10494 	},
  10495 	stop: function( event, ui, instance ) {
  10496 		var o = instance.options;
  10497 		if ( o._cursor ) {
  10498 			$( "body" ).css( "cursor", o._cursor );
  10499 		}
  10500 	}
  10501 } );
  10502 
  10503 $.ui.plugin.add( "draggable", "opacity", {
  10504 	start: function( event, ui, instance ) {
  10505 		var t = $( ui.helper ),
  10506 			o = instance.options;
  10507 		if ( t.css( "opacity" ) ) {
  10508 			o._opacity = t.css( "opacity" );
  10509 		}
  10510 		t.css( "opacity", o.opacity );
  10511 	},
  10512 	stop: function( event, ui, instance ) {
  10513 		var o = instance.options;
  10514 		if ( o._opacity ) {
  10515 			$( ui.helper ).css( "opacity", o._opacity );
  10516 		}
  10517 	}
  10518 } );
  10519 
  10520 $.ui.plugin.add( "draggable", "scroll", {
  10521 	start: function( event, ui, i ) {
  10522 		if ( !i.scrollParentNotHidden ) {
  10523 			i.scrollParentNotHidden = i.helper.scrollParent( false );
  10524 		}
  10525 
  10526 		if ( i.scrollParentNotHidden[ 0 ] !== i.document[ 0 ] &&
  10527 				i.scrollParentNotHidden[ 0 ].tagName !== "HTML" ) {
  10528 			i.overflowOffset = i.scrollParentNotHidden.offset();
  10529 		}
  10530 	},
  10531 	drag: function( event, ui, i  ) {
  10532 
  10533 		var o = i.options,
  10534 			scrolled = false,
  10535 			scrollParent = i.scrollParentNotHidden[ 0 ],
  10536 			document = i.document[ 0 ];
  10537 
  10538 		if ( scrollParent !== document && scrollParent.tagName !== "HTML" ) {
  10539 			if ( !o.axis || o.axis !== "x" ) {
  10540 				if ( ( i.overflowOffset.top + scrollParent.offsetHeight ) - event.pageY <
  10541 						o.scrollSensitivity ) {
  10542 					scrollParent.scrollTop = scrolled = scrollParent.scrollTop + o.scrollSpeed;
  10543 				} else if ( event.pageY - i.overflowOffset.top < o.scrollSensitivity ) {
  10544 					scrollParent.scrollTop = scrolled = scrollParent.scrollTop - o.scrollSpeed;
  10545 				}
  10546 			}
  10547 
  10548 			if ( !o.axis || o.axis !== "y" ) {
  10549 				if ( ( i.overflowOffset.left + scrollParent.offsetWidth ) - event.pageX <
  10550 						o.scrollSensitivity ) {
  10551 					scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft + o.scrollSpeed;
  10552 				} else if ( event.pageX - i.overflowOffset.left < o.scrollSensitivity ) {
  10553 					scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft - o.scrollSpeed;
  10554 				}
  10555 			}
  10556 
  10557 		} else {
  10558 
  10559 			if ( !o.axis || o.axis !== "x" ) {
  10560 				if ( event.pageY - $( document ).scrollTop() < o.scrollSensitivity ) {
  10561 					scrolled = $( document ).scrollTop( $( document ).scrollTop() - o.scrollSpeed );
  10562 				} else if ( $( window ).height() - ( event.pageY - $( document ).scrollTop() ) <
  10563 						o.scrollSensitivity ) {
  10564 					scrolled = $( document ).scrollTop( $( document ).scrollTop() + o.scrollSpeed );
  10565 				}
  10566 			}
  10567 
  10568 			if ( !o.axis || o.axis !== "y" ) {
  10569 				if ( event.pageX - $( document ).scrollLeft() < o.scrollSensitivity ) {
  10570 					scrolled = $( document ).scrollLeft(
  10571 						$( document ).scrollLeft() - o.scrollSpeed
  10572 					);
  10573 				} else if ( $( window ).width() - ( event.pageX - $( document ).scrollLeft() ) <
  10574 						o.scrollSensitivity ) {
  10575 					scrolled = $( document ).scrollLeft(
  10576 						$( document ).scrollLeft() + o.scrollSpeed
  10577 					);
  10578 				}
  10579 			}
  10580 
  10581 		}
  10582 
  10583 		if ( scrolled !== false && $.ui.ddmanager && !o.dropBehaviour ) {
  10584 			$.ui.ddmanager.prepareOffsets( i, event );
  10585 		}
  10586 
  10587 	}
  10588 } );
  10589 
  10590 $.ui.plugin.add( "draggable", "snap", {
  10591 	start: function( event, ui, i ) {
  10592 
  10593 		var o = i.options;
  10594 
  10595 		i.snapElements = [];
  10596 
  10597 		$( o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap )
  10598 			.each( function() {
  10599 				var $t = $( this ),
  10600 					$o = $t.offset();
  10601 				if ( this !== i.element[ 0 ] ) {
  10602 					i.snapElements.push( {
  10603 						item: this,
  10604 						width: $t.outerWidth(), height: $t.outerHeight(),
  10605 						top: $o.top, left: $o.left
  10606 					} );
  10607 				}
  10608 			} );
  10609 
  10610 	},
  10611 	drag: function( event, ui, inst ) {
  10612 
  10613 		var ts, bs, ls, rs, l, r, t, b, i, first,
  10614 			o = inst.options,
  10615 			d = o.snapTolerance,
  10616 			x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
  10617 			y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
  10618 
  10619 		for ( i = inst.snapElements.length - 1; i >= 0; i-- ) {
  10620 
  10621 			l = inst.snapElements[ i ].left - inst.margins.left;
  10622 			r = l + inst.snapElements[ i ].width;
  10623 			t = inst.snapElements[ i ].top - inst.margins.top;
  10624 			b = t + inst.snapElements[ i ].height;
  10625 
  10626 			if ( x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d ||
  10627 					!$.contains( inst.snapElements[ i ].item.ownerDocument,
  10628 					inst.snapElements[ i ].item ) ) {
  10629 				if ( inst.snapElements[ i ].snapping ) {
  10630 					( inst.options.snap.release &&
  10631 						inst.options.snap.release.call(
  10632 							inst.element,
  10633 							event,
  10634 							$.extend( inst._uiHash(), { snapItem: inst.snapElements[ i ].item } )
  10635 						) );
  10636 				}
  10637 				inst.snapElements[ i ].snapping = false;
  10638 				continue;
  10639 			}
  10640 
  10641 			if ( o.snapMode !== "inner" ) {
  10642 				ts = Math.abs( t - y2 ) <= d;
  10643 				bs = Math.abs( b - y1 ) <= d;
  10644 				ls = Math.abs( l - x2 ) <= d;
  10645 				rs = Math.abs( r - x1 ) <= d;
  10646 				if ( ts ) {
  10647 					ui.position.top = inst._convertPositionTo( "relative", {
  10648 						top: t - inst.helperProportions.height,
  10649 						left: 0
  10650 					} ).top;
  10651 				}
  10652 				if ( bs ) {
  10653 					ui.position.top = inst._convertPositionTo( "relative", {
  10654 						top: b,
  10655 						left: 0
  10656 					} ).top;
  10657 				}
  10658 				if ( ls ) {
  10659 					ui.position.left = inst._convertPositionTo( "relative", {
  10660 						top: 0,
  10661 						left: l - inst.helperProportions.width
  10662 					} ).left;
  10663 				}
  10664 				if ( rs ) {
  10665 					ui.position.left = inst._convertPositionTo( "relative", {
  10666 						top: 0,
  10667 						left: r
  10668 					} ).left;
  10669 				}
  10670 			}
  10671 
  10672 			first = ( ts || bs || ls || rs );
  10673 
  10674 			if ( o.snapMode !== "outer" ) {
  10675 				ts = Math.abs( t - y1 ) <= d;
  10676 				bs = Math.abs( b - y2 ) <= d;
  10677 				ls = Math.abs( l - x1 ) <= d;
  10678 				rs = Math.abs( r - x2 ) <= d;
  10679 				if ( ts ) {
  10680 					ui.position.top = inst._convertPositionTo( "relative", {
  10681 						top: t,
  10682 						left: 0
  10683 					} ).top;
  10684 				}
  10685 				if ( bs ) {
  10686 					ui.position.top = inst._convertPositionTo( "relative", {
  10687 						top: b - inst.helperProportions.height,
  10688 						left: 0
  10689 					} ).top;
  10690 				}
  10691 				if ( ls ) {
  10692 					ui.position.left = inst._convertPositionTo( "relative", {
  10693 						top: 0,
  10694 						left: l
  10695 					} ).left;
  10696 				}
  10697 				if ( rs ) {
  10698 					ui.position.left = inst._convertPositionTo( "relative", {
  10699 						top: 0,
  10700 						left: r - inst.helperProportions.width
  10701 					} ).left;
  10702 				}
  10703 			}
  10704 
  10705 			if ( !inst.snapElements[ i ].snapping && ( ts || bs || ls || rs || first ) ) {
  10706 				( inst.options.snap.snap &&
  10707 					inst.options.snap.snap.call(
  10708 						inst.element,
  10709 						event,
  10710 						$.extend( inst._uiHash(), {
  10711 							snapItem: inst.snapElements[ i ].item
  10712 						} ) ) );
  10713 			}
  10714 			inst.snapElements[ i ].snapping = ( ts || bs || ls || rs || first );
  10715 
  10716 		}
  10717 
  10718 	}
  10719 } );
  10720 
  10721 $.ui.plugin.add( "draggable", "stack", {
  10722 	start: function( event, ui, instance ) {
  10723 		var min,
  10724 			o = instance.options,
  10725 			group = $.makeArray( $( o.stack ) ).sort( function( a, b ) {
  10726 				return ( parseInt( $( a ).css( "zIndex" ), 10 ) || 0 ) -
  10727 					( parseInt( $( b ).css( "zIndex" ), 10 ) || 0 );
  10728 			} );
  10729 
  10730 		if ( !group.length ) { return; }
  10731 
  10732 		min = parseInt( $( group[ 0 ] ).css( "zIndex" ), 10 ) || 0;
  10733 		$( group ).each( function( i ) {
  10734 			$( this ).css( "zIndex", min + i );
  10735 		} );
  10736 		this.css( "zIndex", ( min + group.length ) );
  10737 	}
  10738 } );
  10739 
  10740 $.ui.plugin.add( "draggable", "zIndex", {
  10741 	start: function( event, ui, instance ) {
  10742 		var t = $( ui.helper ),
  10743 			o = instance.options;
  10744 
  10745 		if ( t.css( "zIndex" ) ) {
  10746 			o._zIndex = t.css( "zIndex" );
  10747 		}
  10748 		t.css( "zIndex", o.zIndex );
  10749 	},
  10750 	stop: function( event, ui, instance ) {
  10751 		var o = instance.options;
  10752 
  10753 		if ( o._zIndex ) {
  10754 			$( ui.helper ).css( "zIndex", o._zIndex );
  10755 		}
  10756 	}
  10757 } );
  10758 
  10759 var widgetsDraggable = $.ui.draggable;
  10760 
  10761 
  10762 /*!
  10763  * jQuery UI Resizable 1.12.1
  10764  * http://jqueryui.com
  10765  *
  10766  * Copyright jQuery Foundation and other contributors
  10767  * Released under the MIT license.
  10768  * http://jquery.org/license
  10769  */
  10770 
  10771 //>>label: Resizable
  10772 //>>group: Interactions
  10773 //>>description: Enables resize functionality for any element.
  10774 //>>docs: http://api.jqueryui.com/resizable/
  10775 //>>demos: http://jqueryui.com/resizable/
  10776 //>>css.structure: ../../themes/base/core.css
  10777 //>>css.structure: ../../themes/base/resizable.css
  10778 //>>css.theme: ../../themes/base/theme.css
  10779 
  10780 
  10781 
  10782 $.widget( "ui.resizable", $.ui.mouse, {
  10783 	version: "1.12.1",
  10784 	widgetEventPrefix: "resize",
  10785 	options: {
  10786 		alsoResize: false,
  10787 		animate: false,
  10788 		animateDuration: "slow",
  10789 		animateEasing: "swing",
  10790 		aspectRatio: false,
  10791 		autoHide: false,
  10792 		classes: {
  10793 			"ui-resizable-se": "ui-icon ui-icon-gripsmall-diagonal-se"
  10794 		},
  10795 		containment: false,
  10796 		ghost: false,
  10797 		grid: false,
  10798 		handles: "e,s,se",
  10799 		helper: false,
  10800 		maxHeight: null,
  10801 		maxWidth: null,
  10802 		minHeight: 10,
  10803 		minWidth: 10,
  10804 
  10805 		// See #7960
  10806 		zIndex: 90,
  10807 
  10808 		// Callbacks
  10809 		resize: null,
  10810 		start: null,
  10811 		stop: null
  10812 	},
  10813 
  10814 	_num: function( value ) {
  10815 		return parseFloat( value ) || 0;
  10816 	},
  10817 
  10818 	_isNumber: function( value ) {
  10819 		return !isNaN( parseFloat( value ) );
  10820 	},
  10821 
  10822 	_hasScroll: function( el, a ) {
  10823 
  10824 		if ( $( el ).css( "overflow" ) === "hidden" ) {
  10825 			return false;
  10826 		}
  10827 
  10828 		var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
  10829 			has = false;
  10830 
  10831 		if ( el[ scroll ] > 0 ) {
  10832 			return true;
  10833 		}
  10834 
  10835 		// TODO: determine which cases actually cause this to happen
  10836 		// if the element doesn't have the scroll set, see if it's possible to
  10837 		// set the scroll
  10838 		el[ scroll ] = 1;
  10839 		has = ( el[ scroll ] > 0 );
  10840 		el[ scroll ] = 0;
  10841 		return has;
  10842 	},
  10843 
  10844 	_create: function() {
  10845 
  10846 		var margins,
  10847 			o = this.options,
  10848 			that = this;
  10849 		this._addClass( "ui-resizable" );
  10850 
  10851 		$.extend( this, {
  10852 			_aspectRatio: !!( o.aspectRatio ),
  10853 			aspectRatio: o.aspectRatio,
  10854 			originalElement: this.element,
  10855 			_proportionallyResizeElements: [],
  10856 			_helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null
  10857 		} );
  10858 
  10859 		// Wrap the element if it cannot hold child nodes
  10860 		if ( this.element[ 0 ].nodeName.match( /^(canvas|textarea|input|select|button|img)$/i ) ) {
  10861 
  10862 			this.element.wrap(
  10863 				$( "<div class='ui-wrapper' style='overflow: hidden;'></div>" ).css( {
  10864 					position: this.element.css( "position" ),
  10865 					width: this.element.outerWidth(),
  10866 					height: this.element.outerHeight(),
  10867 					top: this.element.css( "top" ),
  10868 					left: this.element.css( "left" )
  10869 				} )
  10870 			);
  10871 
  10872 			this.element = this.element.parent().data(
  10873 				"ui-resizable", this.element.resizable( "instance" )
  10874 			);
  10875 
  10876 			this.elementIsWrapper = true;
  10877 
  10878 			margins = {
  10879 				marginTop: this.originalElement.css( "marginTop" ),
  10880 				marginRight: this.originalElement.css( "marginRight" ),
  10881 				marginBottom: this.originalElement.css( "marginBottom" ),
  10882 				marginLeft: this.originalElement.css( "marginLeft" )
  10883 			};
  10884 
  10885 			this.element.css( margins );
  10886 			this.originalElement.css( "margin", 0 );
  10887 
  10888 			// support: Safari
  10889 			// Prevent Safari textarea resize
  10890 			this.originalResizeStyle = this.originalElement.css( "resize" );
  10891 			this.originalElement.css( "resize", "none" );
  10892 
  10893 			this._proportionallyResizeElements.push( this.originalElement.css( {
  10894 				position: "static",
  10895 				zoom: 1,
  10896 				display: "block"
  10897 			} ) );
  10898 
  10899 			// Support: IE9
  10900 			// avoid IE jump (hard set the margin)
  10901 			this.originalElement.css( margins );
  10902 
  10903 			this._proportionallyResize();
  10904 		}
  10905 
  10906 		this._setupHandles();
  10907 
  10908 		if ( o.autoHide ) {
  10909 			$( this.element )
  10910 				.on( "mouseenter", function() {
  10911 					if ( o.disabled ) {
  10912 						return;
  10913 					}
  10914 					that._removeClass( "ui-resizable-autohide" );
  10915 					that._handles.show();
  10916 				} )
  10917 				.on( "mouseleave", function() {
  10918 					if ( o.disabled ) {
  10919 						return;
  10920 					}
  10921 					if ( !that.resizing ) {
  10922 						that._addClass( "ui-resizable-autohide" );
  10923 						that._handles.hide();
  10924 					}
  10925 				} );
  10926 		}
  10927 
  10928 		this._mouseInit();
  10929 	},
  10930 
  10931 	_destroy: function() {
  10932 
  10933 		this._mouseDestroy();
  10934 
  10935 		var wrapper,
  10936 			_destroy = function( exp ) {
  10937 				$( exp )
  10938 					.removeData( "resizable" )
  10939 					.removeData( "ui-resizable" )
  10940 					.off( ".resizable" )
  10941 					.find( ".ui-resizable-handle" )
  10942 						.remove();
  10943 			};
  10944 
  10945 		// TODO: Unwrap at same DOM position
  10946 		if ( this.elementIsWrapper ) {
  10947 			_destroy( this.element );
  10948 			wrapper = this.element;
  10949 			this.originalElement.css( {
  10950 				position: wrapper.css( "position" ),
  10951 				width: wrapper.outerWidth(),
  10952 				height: wrapper.outerHeight(),
  10953 				top: wrapper.css( "top" ),
  10954 				left: wrapper.css( "left" )
  10955 			} ).insertAfter( wrapper );
  10956 			wrapper.remove();
  10957 		}
  10958 
  10959 		this.originalElement.css( "resize", this.originalResizeStyle );
  10960 		_destroy( this.originalElement );
  10961 
  10962 		return this;
  10963 	},
  10964 
  10965 	_setOption: function( key, value ) {
  10966 		this._super( key, value );
  10967 
  10968 		switch ( key ) {
  10969 		case "handles":
  10970 			this._removeHandles();
  10971 			this._setupHandles();
  10972 			break;
  10973 		default:
  10974 			break;
  10975 		}
  10976 	},
  10977 
  10978 	_setupHandles: function() {
  10979 		var o = this.options, handle, i, n, hname, axis, that = this;
  10980 		this.handles = o.handles ||
  10981 			( !$( ".ui-resizable-handle", this.element ).length ?
  10982 				"e,s,se" : {
  10983 					n: ".ui-resizable-n",
  10984 					e: ".ui-resizable-e",
  10985 					s: ".ui-resizable-s",
  10986 					w: ".ui-resizable-w",
  10987 					se: ".ui-resizable-se",
  10988 					sw: ".ui-resizable-sw",
  10989 					ne: ".ui-resizable-ne",
  10990 					nw: ".ui-resizable-nw"
  10991 				} );
  10992 
  10993 		this._handles = $();
  10994 		if ( this.handles.constructor === String ) {
  10995 
  10996 			if ( this.handles === "all" ) {
  10997 				this.handles = "n,e,s,w,se,sw,ne,nw";
  10998 			}
  10999 
  11000 			n = this.handles.split( "," );
  11001 			this.handles = {};
  11002 
  11003 			for ( i = 0; i < n.length; i++ ) {
  11004 
  11005 				handle = $.trim( n[ i ] );
  11006 				hname = "ui-resizable-" + handle;
  11007 				axis = $( "<div>" );
  11008 				this._addClass( axis, "ui-resizable-handle " + hname );
  11009 
  11010 				axis.css( { zIndex: o.zIndex } );
  11011 
  11012 				this.handles[ handle ] = ".ui-resizable-" + handle;
  11013 				this.element.append( axis );
  11014 			}
  11015 
  11016 		}
  11017 
  11018 		this._renderAxis = function( target ) {
  11019 
  11020 			var i, axis, padPos, padWrapper;
  11021 
  11022 			target = target || this.element;
  11023 
  11024 			for ( i in this.handles ) {
  11025 
  11026 				if ( this.handles[ i ].constructor === String ) {
  11027 					this.handles[ i ] = this.element.children( this.handles[ i ] ).first().show();
  11028 				} else if ( this.handles[ i ].jquery || this.handles[ i ].nodeType ) {
  11029 					this.handles[ i ] = $( this.handles[ i ] );
  11030 					this._on( this.handles[ i ], { "mousedown": that._mouseDown } );
  11031 				}
  11032 
  11033 				if ( this.elementIsWrapper &&
  11034 						this.originalElement[ 0 ]
  11035 							.nodeName
  11036 							.match( /^(textarea|input|select|button)$/i ) ) {
  11037 					axis = $( this.handles[ i ], this.element );
  11038 
  11039 					padWrapper = /sw|ne|nw|se|n|s/.test( i ) ?
  11040 						axis.outerHeight() :
  11041 						axis.outerWidth();
  11042 
  11043 					padPos = [ "padding",
  11044 						/ne|nw|n/.test( i ) ? "Top" :
  11045 						/se|sw|s/.test( i ) ? "Bottom" :
  11046 						/^e$/.test( i ) ? "Right" : "Left" ].join( "" );
  11047 
  11048 					target.css( padPos, padWrapper );
  11049 
  11050 					this._proportionallyResize();
  11051 				}
  11052 
  11053 				this._handles = this._handles.add( this.handles[ i ] );
  11054 			}
  11055 		};
  11056 
  11057 		// TODO: make renderAxis a prototype function
  11058 		this._renderAxis( this.element );
  11059 
  11060 		this._handles = this._handles.add( this.element.find( ".ui-resizable-handle" ) );
  11061 		this._handles.disableSelection();
  11062 
  11063 		this._handles.on( "mouseover", function() {
  11064 			if ( !that.resizing ) {
  11065 				if ( this.className ) {
  11066 					axis = this.className.match( /ui-resizable-(se|sw|ne|nw|n|e|s|w)/i );
  11067 				}
  11068 				that.axis = axis && axis[ 1 ] ? axis[ 1 ] : "se";
  11069 			}
  11070 		} );
  11071 
  11072 		if ( o.autoHide ) {
  11073 			this._handles.hide();
  11074 			this._addClass( "ui-resizable-autohide" );
  11075 		}
  11076 	},
  11077 
  11078 	_removeHandles: function() {
  11079 		this._handles.remove();
  11080 	},
  11081 
  11082 	_mouseCapture: function( event ) {
  11083 		var i, handle,
  11084 			capture = false;
  11085 
  11086 		for ( i in this.handles ) {
  11087 			handle = $( this.handles[ i ] )[ 0 ];
  11088 			if ( handle === event.target || $.contains( handle, event.target ) ) {
  11089 				capture = true;
  11090 			}
  11091 		}
  11092 
  11093 		return !this.options.disabled && capture;
  11094 	},
  11095 
  11096 	_mouseStart: function( event ) {
  11097 
  11098 		var curleft, curtop, cursor,
  11099 			o = this.options,
  11100 			el = this.element;
  11101 
  11102 		this.resizing = true;
  11103 
  11104 		this._renderProxy();
  11105 
  11106 		curleft = this._num( this.helper.css( "left" ) );
  11107 		curtop = this._num( this.helper.css( "top" ) );
  11108 
  11109 		if ( o.containment ) {
  11110 			curleft += $( o.containment ).scrollLeft() || 0;
  11111 			curtop += $( o.containment ).scrollTop() || 0;
  11112 		}
  11113 
  11114 		this.offset = this.helper.offset();
  11115 		this.position = { left: curleft, top: curtop };
  11116 
  11117 		this.size = this._helper ? {
  11118 				width: this.helper.width(),
  11119 				height: this.helper.height()
  11120 			} : {
  11121 				width: el.width(),
  11122 				height: el.height()
  11123 			};
  11124 
  11125 		this.originalSize = this._helper ? {
  11126 				width: el.outerWidth(),
  11127 				height: el.outerHeight()
  11128 			} : {
  11129 				width: el.width(),
  11130 				height: el.height()
  11131 			};
  11132 
  11133 		this.sizeDiff = {
  11134 			width: el.outerWidth() - el.width(),
  11135 			height: el.outerHeight() - el.height()
  11136 		};
  11137 
  11138 		this.originalPosition = { left: curleft, top: curtop };
  11139 		this.originalMousePosition = { left: event.pageX, top: event.pageY };
  11140 
  11141 		this.aspectRatio = ( typeof o.aspectRatio === "number" ) ?
  11142 			o.aspectRatio :
  11143 			( ( this.originalSize.width / this.originalSize.height ) || 1 );
  11144 
  11145 		cursor = $( ".ui-resizable-" + this.axis ).css( "cursor" );
  11146 		$( "body" ).css( "cursor", cursor === "auto" ? this.axis + "-resize" : cursor );
  11147 
  11148 		this._addClass( "ui-resizable-resizing" );
  11149 		this._propagate( "start", event );
  11150 		return true;
  11151 	},
  11152 
  11153 	_mouseDrag: function( event ) {
  11154 
  11155 		var data, props,
  11156 			smp = this.originalMousePosition,
  11157 			a = this.axis,
  11158 			dx = ( event.pageX - smp.left ) || 0,
  11159 			dy = ( event.pageY - smp.top ) || 0,
  11160 			trigger = this._change[ a ];
  11161 
  11162 		this._updatePrevProperties();
  11163 
  11164 		if ( !trigger ) {
  11165 			return false;
  11166 		}
  11167 
  11168 		data = trigger.apply( this, [ event, dx, dy ] );
  11169 
  11170 		this._updateVirtualBoundaries( event.shiftKey );
  11171 		if ( this._aspectRatio || event.shiftKey ) {
  11172 			data = this._updateRatio( data, event );
  11173 		}
  11174 
  11175 		data = this._respectSize( data, event );
  11176 
  11177 		this._updateCache( data );
  11178 
  11179 		this._propagate( "resize", event );
  11180 
  11181 		props = this._applyChanges();
  11182 
  11183 		if ( !this._helper && this._proportionallyResizeElements.length ) {
  11184 			this._proportionallyResize();
  11185 		}
  11186 
  11187 		if ( !$.isEmptyObject( props ) ) {
  11188 			this._updatePrevProperties();
  11189 			this._trigger( "resize", event, this.ui() );
  11190 			this._applyChanges();
  11191 		}
  11192 
  11193 		return false;
  11194 	},
  11195 
  11196 	_mouseStop: function( event ) {
  11197 
  11198 		this.resizing = false;
  11199 		var pr, ista, soffseth, soffsetw, s, left, top,
  11200 			o = this.options, that = this;
  11201 
  11202 		if ( this._helper ) {
  11203 
  11204 			pr = this._proportionallyResizeElements;
  11205 			ista = pr.length && ( /textarea/i ).test( pr[ 0 ].nodeName );
  11206 			soffseth = ista && this._hasScroll( pr[ 0 ], "left" ) ? 0 : that.sizeDiff.height;
  11207 			soffsetw = ista ? 0 : that.sizeDiff.width;
  11208 
  11209 			s = {
  11210 				width: ( that.helper.width()  - soffsetw ),
  11211 				height: ( that.helper.height() - soffseth )
  11212 			};
  11213 			left = ( parseFloat( that.element.css( "left" ) ) +
  11214 				( that.position.left - that.originalPosition.left ) ) || null;
  11215 			top = ( parseFloat( that.element.css( "top" ) ) +
  11216 				( that.position.top - that.originalPosition.top ) ) || null;
  11217 
  11218 			if ( !o.animate ) {
  11219 				this.element.css( $.extend( s, { top: top, left: left } ) );
  11220 			}
  11221 
  11222 			that.helper.height( that.size.height );
  11223 			that.helper.width( that.size.width );
  11224 
  11225 			if ( this._helper && !o.animate ) {
  11226 				this._proportionallyResize();
  11227 			}
  11228 		}
  11229 
  11230 		$( "body" ).css( "cursor", "auto" );
  11231 
  11232 		this._removeClass( "ui-resizable-resizing" );
  11233 
  11234 		this._propagate( "stop", event );
  11235 
  11236 		if ( this._helper ) {
  11237 			this.helper.remove();
  11238 		}
  11239 
  11240 		return false;
  11241 
  11242 	},
  11243 
  11244 	_updatePrevProperties: function() {
  11245 		this.prevPosition = {
  11246 			top: this.position.top,
  11247 			left: this.position.left
  11248 		};
  11249 		this.prevSize = {
  11250 			width: this.size.width,
  11251 			height: this.size.height
  11252 		};
  11253 	},
  11254 
  11255 	_applyChanges: function() {
  11256 		var props = {};
  11257 
  11258 		if ( this.position.top !== this.prevPosition.top ) {
  11259 			props.top = this.position.top + "px";
  11260 		}
  11261 		if ( this.position.left !== this.prevPosition.left ) {
  11262 			props.left = this.position.left + "px";
  11263 		}
  11264 		if ( this.size.width !== this.prevSize.width ) {
  11265 			props.width = this.size.width + "px";
  11266 		}
  11267 		if ( this.size.height !== this.prevSize.height ) {
  11268 			props.height = this.size.height + "px";
  11269 		}
  11270 
  11271 		this.helper.css( props );
  11272 
  11273 		return props;
  11274 	},
  11275 
  11276 	_updateVirtualBoundaries: function( forceAspectRatio ) {
  11277 		var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b,
  11278 			o = this.options;
  11279 
  11280 		b = {
  11281 			minWidth: this._isNumber( o.minWidth ) ? o.minWidth : 0,
  11282 			maxWidth: this._isNumber( o.maxWidth ) ? o.maxWidth : Infinity,
  11283 			minHeight: this._isNumber( o.minHeight ) ? o.minHeight : 0,
  11284 			maxHeight: this._isNumber( o.maxHeight ) ? o.maxHeight : Infinity
  11285 		};
  11286 
  11287 		if ( this._aspectRatio || forceAspectRatio ) {
  11288 			pMinWidth = b.minHeight * this.aspectRatio;
  11289 			pMinHeight = b.minWidth / this.aspectRatio;
  11290 			pMaxWidth = b.maxHeight * this.aspectRatio;
  11291 			pMaxHeight = b.maxWidth / this.aspectRatio;
  11292 
  11293 			if ( pMinWidth > b.minWidth ) {
  11294 				b.minWidth = pMinWidth;
  11295 			}
  11296 			if ( pMinHeight > b.minHeight ) {
  11297 				b.minHeight = pMinHeight;
  11298 			}
  11299 			if ( pMaxWidth < b.maxWidth ) {
  11300 				b.maxWidth = pMaxWidth;
  11301 			}
  11302 			if ( pMaxHeight < b.maxHeight ) {
  11303 				b.maxHeight = pMaxHeight;
  11304 			}
  11305 		}
  11306 		this._vBoundaries = b;
  11307 	},
  11308 
  11309 	_updateCache: function( data ) {
  11310 		this.offset = this.helper.offset();
  11311 		if ( this._isNumber( data.left ) ) {
  11312 			this.position.left = data.left;
  11313 		}
  11314 		if ( this._isNumber( data.top ) ) {
  11315 			this.position.top = data.top;
  11316 		}
  11317 		if ( this._isNumber( data.height ) ) {
  11318 			this.size.height = data.height;
  11319 		}
  11320 		if ( this._isNumber( data.width ) ) {
  11321 			this.size.width = data.width;
  11322 		}
  11323 	},
  11324 
  11325 	_updateRatio: function( data ) {
  11326 
  11327 		var cpos = this.position,
  11328 			csize = this.size,
  11329 			a = this.axis;
  11330 
  11331 		if ( this._isNumber( data.height ) ) {
  11332 			data.width = ( data.height * this.aspectRatio );
  11333 		} else if ( this._isNumber( data.width ) ) {
  11334 			data.height = ( data.width / this.aspectRatio );
  11335 		}
  11336 
  11337 		if ( a === "sw" ) {
  11338 			data.left = cpos.left + ( csize.width - data.width );
  11339 			data.top = null;
  11340 		}
  11341 		if ( a === "nw" ) {
  11342 			data.top = cpos.top + ( csize.height - data.height );
  11343 			data.left = cpos.left + ( csize.width - data.width );
  11344 		}
  11345 
  11346 		return data;
  11347 	},
  11348 
  11349 	_respectSize: function( data ) {
  11350 
  11351 		var o = this._vBoundaries,
  11352 			a = this.axis,
  11353 			ismaxw = this._isNumber( data.width ) && o.maxWidth && ( o.maxWidth < data.width ),
  11354 			ismaxh = this._isNumber( data.height ) && o.maxHeight && ( o.maxHeight < data.height ),
  11355 			isminw = this._isNumber( data.width ) && o.minWidth && ( o.minWidth > data.width ),
  11356 			isminh = this._isNumber( data.height ) && o.minHeight && ( o.minHeight > data.height ),
  11357 			dw = this.originalPosition.left + this.originalSize.width,
  11358 			dh = this.originalPosition.top + this.originalSize.height,
  11359 			cw = /sw|nw|w/.test( a ), ch = /nw|ne|n/.test( a );
  11360 		if ( isminw ) {
  11361 			data.width = o.minWidth;
  11362 		}
  11363 		if ( isminh ) {
  11364 			data.height = o.minHeight;
  11365 		}
  11366 		if ( ismaxw ) {
  11367 			data.width = o.maxWidth;
  11368 		}
  11369 		if ( ismaxh ) {
  11370 			data.height = o.maxHeight;
  11371 		}
  11372 
  11373 		if ( isminw && cw ) {
  11374 			data.left = dw - o.minWidth;
  11375 		}
  11376 		if ( ismaxw && cw ) {
  11377 			data.left = dw - o.maxWidth;
  11378 		}
  11379 		if ( isminh && ch ) {
  11380 			data.top = dh - o.minHeight;
  11381 		}
  11382 		if ( ismaxh && ch ) {
  11383 			data.top = dh - o.maxHeight;
  11384 		}
  11385 
  11386 		// Fixing jump error on top/left - bug #2330
  11387 		if ( !data.width && !data.height && !data.left && data.top ) {
  11388 			data.top = null;
  11389 		} else if ( !data.width && !data.height && !data.top && data.left ) {
  11390 			data.left = null;
  11391 		}
  11392 
  11393 		return data;
  11394 	},
  11395 
  11396 	_getPaddingPlusBorderDimensions: function( element ) {
  11397 		var i = 0,
  11398 			widths = [],
  11399 			borders = [
  11400 				element.css( "borderTopWidth" ),
  11401 				element.css( "borderRightWidth" ),
  11402 				element.css( "borderBottomWidth" ),
  11403 				element.css( "borderLeftWidth" )
  11404 			],
  11405 			paddings = [
  11406 				element.css( "paddingTop" ),
  11407 				element.css( "paddingRight" ),
  11408 				element.css( "paddingBottom" ),
  11409 				element.css( "paddingLeft" )
  11410 			];
  11411 
  11412 		for ( ; i < 4; i++ ) {
  11413 			widths[ i ] = ( parseFloat( borders[ i ] ) || 0 );
  11414 			widths[ i ] += ( parseFloat( paddings[ i ] ) || 0 );
  11415 		}
  11416 
  11417 		return {
  11418 			height: widths[ 0 ] + widths[ 2 ],
  11419 			width: widths[ 1 ] + widths[ 3 ]
  11420 		};
  11421 	},
  11422 
  11423 	_proportionallyResize: function() {
  11424 
  11425 		if ( !this._proportionallyResizeElements.length ) {
  11426 			return;
  11427 		}
  11428 
  11429 		var prel,
  11430 			i = 0,
  11431 			element = this.helper || this.element;
  11432 
  11433 		for ( ; i < this._proportionallyResizeElements.length; i++ ) {
  11434 
  11435 			prel = this._proportionallyResizeElements[ i ];
  11436 
  11437 			// TODO: Seems like a bug to cache this.outerDimensions
  11438 			// considering that we are in a loop.
  11439 			if ( !this.outerDimensions ) {
  11440 				this.outerDimensions = this._getPaddingPlusBorderDimensions( prel );
  11441 			}
  11442 
  11443 			prel.css( {
  11444 				height: ( element.height() - this.outerDimensions.height ) || 0,
  11445 				width: ( element.width() - this.outerDimensions.width ) || 0
  11446 			} );
  11447 
  11448 		}
  11449 
  11450 	},
  11451 
  11452 	_renderProxy: function() {
  11453 
  11454 		var el = this.element, o = this.options;
  11455 		this.elementOffset = el.offset();
  11456 
  11457 		if ( this._helper ) {
  11458 
  11459 			this.helper = this.helper || $( "<div style='overflow:hidden;'></div>" );
  11460 
  11461 			this._addClass( this.helper, this._helper );
  11462 			this.helper.css( {
  11463 				width: this.element.outerWidth(),
  11464 				height: this.element.outerHeight(),
  11465 				position: "absolute",
  11466 				left: this.elementOffset.left + "px",
  11467 				top: this.elementOffset.top + "px",
  11468 				zIndex: ++o.zIndex //TODO: Don't modify option
  11469 			} );
  11470 
  11471 			this.helper
  11472 				.appendTo( "body" )
  11473 				.disableSelection();
  11474 
  11475 		} else {
  11476 			this.helper = this.element;
  11477 		}
  11478 
  11479 	},
  11480 
  11481 	_change: {
  11482 		e: function( event, dx ) {
  11483 			return { width: this.originalSize.width + dx };
  11484 		},
  11485 		w: function( event, dx ) {
  11486 			var cs = this.originalSize, sp = this.originalPosition;
  11487 			return { left: sp.left + dx, width: cs.width - dx };
  11488 		},
  11489 		n: function( event, dx, dy ) {
  11490 			var cs = this.originalSize, sp = this.originalPosition;
  11491 			return { top: sp.top + dy, height: cs.height - dy };
  11492 		},
  11493 		s: function( event, dx, dy ) {
  11494 			return { height: this.originalSize.height + dy };
  11495 		},
  11496 		se: function( event, dx, dy ) {
  11497 			return $.extend( this._change.s.apply( this, arguments ),
  11498 				this._change.e.apply( this, [ event, dx, dy ] ) );
  11499 		},
  11500 		sw: function( event, dx, dy ) {
  11501 			return $.extend( this._change.s.apply( this, arguments ),
  11502 				this._change.w.apply( this, [ event, dx, dy ] ) );
  11503 		},
  11504 		ne: function( event, dx, dy ) {
  11505 			return $.extend( this._change.n.apply( this, arguments ),
  11506 				this._change.e.apply( this, [ event, dx, dy ] ) );
  11507 		},
  11508 		nw: function( event, dx, dy ) {
  11509 			return $.extend( this._change.n.apply( this, arguments ),
  11510 				this._change.w.apply( this, [ event, dx, dy ] ) );
  11511 		}
  11512 	},
  11513 
  11514 	_propagate: function( n, event ) {
  11515 		$.ui.plugin.call( this, n, [ event, this.ui() ] );
  11516 		( n !== "resize" && this._trigger( n, event, this.ui() ) );
  11517 	},
  11518 
  11519 	plugins: {},
  11520 
  11521 	ui: function() {
  11522 		return {
  11523 			originalElement: this.originalElement,
  11524 			element: this.element,
  11525 			helper: this.helper,
  11526 			position: this.position,
  11527 			size: this.size,
  11528 			originalSize: this.originalSize,
  11529 			originalPosition: this.originalPosition
  11530 		};
  11531 	}
  11532 
  11533 } );
  11534 
  11535 /*
  11536  * Resizable Extensions
  11537  */
  11538 
  11539 $.ui.plugin.add( "resizable", "animate", {
  11540 
  11541 	stop: function( event ) {
  11542 		var that = $( this ).resizable( "instance" ),
  11543 			o = that.options,
  11544 			pr = that._proportionallyResizeElements,
  11545 			ista = pr.length && ( /textarea/i ).test( pr[ 0 ].nodeName ),
  11546 			soffseth = ista && that._hasScroll( pr[ 0 ], "left" ) ? 0 : that.sizeDiff.height,
  11547 			soffsetw = ista ? 0 : that.sizeDiff.width,
  11548 			style = {
  11549 				width: ( that.size.width - soffsetw ),
  11550 				height: ( that.size.height - soffseth )
  11551 			},
  11552 			left = ( parseFloat( that.element.css( "left" ) ) +
  11553 				( that.position.left - that.originalPosition.left ) ) || null,
  11554 			top = ( parseFloat( that.element.css( "top" ) ) +
  11555 				( that.position.top - that.originalPosition.top ) ) || null;
  11556 
  11557 		that.element.animate(
  11558 			$.extend( style, top && left ? { top: top, left: left } : {} ), {
  11559 				duration: o.animateDuration,
  11560 				easing: o.animateEasing,
  11561 				step: function() {
  11562 
  11563 					var data = {
  11564 						width: parseFloat( that.element.css( "width" ) ),
  11565 						height: parseFloat( that.element.css( "height" ) ),
  11566 						top: parseFloat( that.element.css( "top" ) ),
  11567 						left: parseFloat( that.element.css( "left" ) )
  11568 					};
  11569 
  11570 					if ( pr && pr.length ) {
  11571 						$( pr[ 0 ] ).css( { width: data.width, height: data.height } );
  11572 					}
  11573 
  11574 					// Propagating resize, and updating values for each animation step
  11575 					that._updateCache( data );
  11576 					that._propagate( "resize", event );
  11577 
  11578 				}
  11579 			}
  11580 		);
  11581 	}
  11582 
  11583 } );
  11584 
  11585 $.ui.plugin.add( "resizable", "containment", {
  11586 
  11587 	start: function() {
  11588 		var element, p, co, ch, cw, width, height,
  11589 			that = $( this ).resizable( "instance" ),
  11590 			o = that.options,
  11591 			el = that.element,
  11592 			oc = o.containment,
  11593 
  11594 			ce = ( oc instanceof $ ) ?
  11595 				oc.get( 0 ) :
  11596 				( /parent/.test( oc ) ) ? el.parent().get( 0 ) : oc;
  11597 
  11598 		if ( !ce ) {
  11599 			return;
  11600 		}
  11601 
  11602 		that.containerElement = $( ce );
  11603 
  11604 		if ( /document/.test( oc ) || oc === document ) {
  11605 			that.containerOffset = {
  11606 				left: 0,
  11607 				top: 0
  11608 			};
  11609 			that.containerPosition = {
  11610 				left: 0,
  11611 				top: 0
  11612 			};
  11613 
  11614 			that.parentData = {
  11615 				element: $( document ),
  11616 				left: 0,
  11617 				top: 0,
  11618 				width: $( document ).width(),
  11619 				height: $( document ).height() || document.body.parentNode.scrollHeight
  11620 			};
  11621 		} else {
  11622 			element = $( ce );
  11623 			p = [];
  11624 			$( [ "Top", "Right", "Left", "Bottom" ] ).each( function( i, name ) {
  11625 				p[ i ] = that._num( element.css( "padding" + name ) );
  11626 			} );
  11627 
  11628 			that.containerOffset = element.offset();
  11629 			that.containerPosition = element.position();
  11630 			that.containerSize = {
  11631 				height: ( element.innerHeight() - p[ 3 ] ),
  11632 				width: ( element.innerWidth() - p[ 1 ] )
  11633 			};
  11634 
  11635 			co = that.containerOffset;
  11636 			ch = that.containerSize.height;
  11637 			cw = that.containerSize.width;
  11638 			width = ( that._hasScroll ( ce, "left" ) ? ce.scrollWidth : cw );
  11639 			height = ( that._hasScroll ( ce ) ? ce.scrollHeight : ch ) ;
  11640 
  11641 			that.parentData = {
  11642 				element: ce,
  11643 				left: co.left,
  11644 				top: co.top,
  11645 				width: width,
  11646 				height: height
  11647 			};
  11648 		}
  11649 	},
  11650 
  11651 	resize: function( event ) {
  11652 		var woset, hoset, isParent, isOffsetRelative,
  11653 			that = $( this ).resizable( "instance" ),
  11654 			o = that.options,
  11655 			co = that.containerOffset,
  11656 			cp = that.position,
  11657 			pRatio = that._aspectRatio || event.shiftKey,
  11658 			cop = {
  11659 				top: 0,
  11660 				left: 0
  11661 			},
  11662 			ce = that.containerElement,
  11663 			continueResize = true;
  11664 
  11665 		if ( ce[ 0 ] !== document && ( /static/ ).test( ce.css( "position" ) ) ) {
  11666 			cop = co;
  11667 		}
  11668 
  11669 		if ( cp.left < ( that._helper ? co.left : 0 ) ) {
  11670 			that.size.width = that.size.width +
  11671 				( that._helper ?
  11672 					( that.position.left - co.left ) :
  11673 					( that.position.left - cop.left ) );
  11674 
  11675 			if ( pRatio ) {
  11676 				that.size.height = that.size.width / that.aspectRatio;
  11677 				continueResize = false;
  11678 			}
  11679 			that.position.left = o.helper ? co.left : 0;
  11680 		}
  11681 
  11682 		if ( cp.top < ( that._helper ? co.top : 0 ) ) {
  11683 			that.size.height = that.size.height +
  11684 				( that._helper ?
  11685 					( that.position.top - co.top ) :
  11686 					that.position.top );
  11687 
  11688 			if ( pRatio ) {
  11689 				that.size.width = that.size.height * that.aspectRatio;
  11690 				continueResize = false;
  11691 			}
  11692 			that.position.top = that._helper ? co.top : 0;
  11693 		}
  11694 
  11695 		isParent = that.containerElement.get( 0 ) === that.element.parent().get( 0 );
  11696 		isOffsetRelative = /relative|absolute/.test( that.containerElement.css( "position" ) );
  11697 
  11698 		if ( isParent && isOffsetRelative ) {
  11699 			that.offset.left = that.parentData.left + that.position.left;
  11700 			that.offset.top = that.parentData.top + that.position.top;
  11701 		} else {
  11702 			that.offset.left = that.element.offset().left;
  11703 			that.offset.top = that.element.offset().top;
  11704 		}
  11705 
  11706 		woset = Math.abs( that.sizeDiff.width +
  11707 			( that._helper ?
  11708 				that.offset.left - cop.left :
  11709 				( that.offset.left - co.left ) ) );
  11710 
  11711 		hoset = Math.abs( that.sizeDiff.height +
  11712 			( that._helper ?
  11713 				that.offset.top - cop.top :
  11714 				( that.offset.top - co.top ) ) );
  11715 
  11716 		if ( woset + that.size.width >= that.parentData.width ) {
  11717 			that.size.width = that.parentData.width - woset;
  11718 			if ( pRatio ) {
  11719 				that.size.height = that.size.width / that.aspectRatio;
  11720 				continueResize = false;
  11721 			}
  11722 		}
  11723 
  11724 		if ( hoset + that.size.height >= that.parentData.height ) {
  11725 			that.size.height = that.parentData.height - hoset;
  11726 			if ( pRatio ) {
  11727 				that.size.width = that.size.height * that.aspectRatio;
  11728 				continueResize = false;
  11729 			}
  11730 		}
  11731 
  11732 		if ( !continueResize ) {
  11733 			that.position.left = that.prevPosition.left;
  11734 			that.position.top = that.prevPosition.top;
  11735 			that.size.width = that.prevSize.width;
  11736 			that.size.height = that.prevSize.height;
  11737 		}
  11738 	},
  11739 
  11740 	stop: function() {
  11741 		var that = $( this ).resizable( "instance" ),
  11742 			o = that.options,
  11743 			co = that.containerOffset,
  11744 			cop = that.containerPosition,
  11745 			ce = that.containerElement,
  11746 			helper = $( that.helper ),
  11747 			ho = helper.offset(),
  11748 			w = helper.outerWidth() - that.sizeDiff.width,
  11749 			h = helper.outerHeight() - that.sizeDiff.height;
  11750 
  11751 		if ( that._helper && !o.animate && ( /relative/ ).test( ce.css( "position" ) ) ) {
  11752 			$( this ).css( {
  11753 				left: ho.left - cop.left - co.left,
  11754 				width: w,
  11755 				height: h
  11756 			} );
  11757 		}
  11758 
  11759 		if ( that._helper && !o.animate && ( /static/ ).test( ce.css( "position" ) ) ) {
  11760 			$( this ).css( {
  11761 				left: ho.left - cop.left - co.left,
  11762 				width: w,
  11763 				height: h
  11764 			} );
  11765 		}
  11766 	}
  11767 } );
  11768 
  11769 $.ui.plugin.add( "resizable", "alsoResize", {
  11770 
  11771 	start: function() {
  11772 		var that = $( this ).resizable( "instance" ),
  11773 			o = that.options;
  11774 
  11775 		$( o.alsoResize ).each( function() {
  11776 			var el = $( this );
  11777 			el.data( "ui-resizable-alsoresize", {
  11778 				width: parseFloat( el.width() ), height: parseFloat( el.height() ),
  11779 				left: parseFloat( el.css( "left" ) ), top: parseFloat( el.css( "top" ) )
  11780 			} );
  11781 		} );
  11782 	},
  11783 
  11784 	resize: function( event, ui ) {
  11785 		var that = $( this ).resizable( "instance" ),
  11786 			o = that.options,
  11787 			os = that.originalSize,
  11788 			op = that.originalPosition,
  11789 			delta = {
  11790 				height: ( that.size.height - os.height ) || 0,
  11791 				width: ( that.size.width - os.width ) || 0,
  11792 				top: ( that.position.top - op.top ) || 0,
  11793 				left: ( that.position.left - op.left ) || 0
  11794 			};
  11795 
  11796 			$( o.alsoResize ).each( function() {
  11797 				var el = $( this ), start = $( this ).data( "ui-resizable-alsoresize" ), style = {},
  11798 					css = el.parents( ui.originalElement[ 0 ] ).length ?
  11799 							[ "width", "height" ] :
  11800 							[ "width", "height", "top", "left" ];
  11801 
  11802 				$.each( css, function( i, prop ) {
  11803 					var sum = ( start[ prop ] || 0 ) + ( delta[ prop ] || 0 );
  11804 					if ( sum && sum >= 0 ) {
  11805 						style[ prop ] = sum || null;
  11806 					}
  11807 				} );
  11808 
  11809 				el.css( style );
  11810 			} );
  11811 	},
  11812 
  11813 	stop: function() {
  11814 		$( this ).removeData( "ui-resizable-alsoresize" );
  11815 	}
  11816 } );
  11817 
  11818 $.ui.plugin.add( "resizable", "ghost", {
  11819 
  11820 	start: function() {
  11821 
  11822 		var that = $( this ).resizable( "instance" ), cs = that.size;
  11823 
  11824 		that.ghost = that.originalElement.clone();
  11825 		that.ghost.css( {
  11826 			opacity: 0.25,
  11827 			display: "block",
  11828 			position: "relative",
  11829 			height: cs.height,
  11830 			width: cs.width,
  11831 			margin: 0,
  11832 			left: 0,
  11833 			top: 0
  11834 		} );
  11835 
  11836 		that._addClass( that.ghost, "ui-resizable-ghost" );
  11837 
  11838 		// DEPRECATED
  11839 		// TODO: remove after 1.12
  11840 		if ( $.uiBackCompat !== false && typeof that.options.ghost === "string" ) {
  11841 
  11842 			// Ghost option
  11843 			that.ghost.addClass( this.options.ghost );
  11844 		}
  11845 
  11846 		that.ghost.appendTo( that.helper );
  11847 
  11848 	},
  11849 
  11850 	resize: function() {
  11851 		var that = $( this ).resizable( "instance" );
  11852 		if ( that.ghost ) {
  11853 			that.ghost.css( {
  11854 				position: "relative",
  11855 				height: that.size.height,
  11856 				width: that.size.width
  11857 			} );
  11858 		}
  11859 	},
  11860 
  11861 	stop: function() {
  11862 		var that = $( this ).resizable( "instance" );
  11863 		if ( that.ghost && that.helper ) {
  11864 			that.helper.get( 0 ).removeChild( that.ghost.get( 0 ) );
  11865 		}
  11866 	}
  11867 
  11868 } );
  11869 
  11870 $.ui.plugin.add( "resizable", "grid", {
  11871 
  11872 	resize: function() {
  11873 		var outerDimensions,
  11874 			that = $( this ).resizable( "instance" ),
  11875 			o = that.options,
  11876 			cs = that.size,
  11877 			os = that.originalSize,
  11878 			op = that.originalPosition,
  11879 			a = that.axis,
  11880 			grid = typeof o.grid === "number" ? [ o.grid, o.grid ] : o.grid,
  11881 			gridX = ( grid[ 0 ] || 1 ),
  11882 			gridY = ( grid[ 1 ] || 1 ),
  11883 			ox = Math.round( ( cs.width - os.width ) / gridX ) * gridX,
  11884 			oy = Math.round( ( cs.height - os.height ) / gridY ) * gridY,
  11885 			newWidth = os.width + ox,
  11886 			newHeight = os.height + oy,
  11887 			isMaxWidth = o.maxWidth && ( o.maxWidth < newWidth ),
  11888 			isMaxHeight = o.maxHeight && ( o.maxHeight < newHeight ),
  11889 			isMinWidth = o.minWidth && ( o.minWidth > newWidth ),
  11890 			isMinHeight = o.minHeight && ( o.minHeight > newHeight );
  11891 
  11892 		o.grid = grid;
  11893 
  11894 		if ( isMinWidth ) {
  11895 			newWidth += gridX;
  11896 		}
  11897 		if ( isMinHeight ) {
  11898 			newHeight += gridY;
  11899 		}
  11900 		if ( isMaxWidth ) {
  11901 			newWidth -= gridX;
  11902 		}
  11903 		if ( isMaxHeight ) {
  11904 			newHeight -= gridY;
  11905 		}
  11906 
  11907 		if ( /^(se|s|e)$/.test( a ) ) {
  11908 			that.size.width = newWidth;
  11909 			that.size.height = newHeight;
  11910 		} else if ( /^(ne)$/.test( a ) ) {
  11911 			that.size.width = newWidth;
  11912 			that.size.height = newHeight;
  11913 			that.position.top = op.top - oy;
  11914 		} else if ( /^(sw)$/.test( a ) ) {
  11915 			that.size.width = newWidth;
  11916 			that.size.height = newHeight;
  11917 			that.position.left = op.left - ox;
  11918 		} else {
  11919 			if ( newHeight - gridY <= 0 || newWidth - gridX <= 0 ) {
  11920 				outerDimensions = that._getPaddingPlusBorderDimensions( this );
  11921 			}
  11922 
  11923 			if ( newHeight - gridY > 0 ) {
  11924 				that.size.height = newHeight;
  11925 				that.position.top = op.top - oy;
  11926 			} else {
  11927 				newHeight = gridY - outerDimensions.height;
  11928 				that.size.height = newHeight;
  11929 				that.position.top = op.top + os.height - newHeight;
  11930 			}
  11931 			if ( newWidth - gridX > 0 ) {
  11932 				that.size.width = newWidth;
  11933 				that.position.left = op.left - ox;
  11934 			} else {
  11935 				newWidth = gridX - outerDimensions.width;
  11936 				that.size.width = newWidth;
  11937 				that.position.left = op.left + os.width - newWidth;
  11938 			}
  11939 		}
  11940 	}
  11941 
  11942 } );
  11943 
  11944 var widgetsResizable = $.ui.resizable;
  11945 
  11946 
  11947 /*!
  11948  * jQuery UI Dialog 1.12.1
  11949  * http://jqueryui.com
  11950  *
  11951  * Copyright jQuery Foundation and other contributors
  11952  * Released under the MIT license.
  11953  * http://jquery.org/license
  11954  */
  11955 
  11956 //>>label: Dialog
  11957 //>>group: Widgets
  11958 //>>description: Displays customizable dialog windows.
  11959 //>>docs: http://api.jqueryui.com/dialog/
  11960 //>>demos: http://jqueryui.com/dialog/
  11961 //>>css.structure: ../../themes/base/core.css
  11962 //>>css.structure: ../../themes/base/dialog.css
  11963 //>>css.theme: ../../themes/base/theme.css
  11964 
  11965 
  11966 
  11967 $.widget( "ui.dialog", {
  11968 	version: "1.12.1",
  11969 	options: {
  11970 		appendTo: "body",
  11971 		autoOpen: true,
  11972 		buttons: [],
  11973 		classes: {
  11974 			"ui-dialog": "ui-corner-all",
  11975 			"ui-dialog-titlebar": "ui-corner-all"
  11976 		},
  11977 		closeOnEscape: true,
  11978 		closeText: "Close",
  11979 		draggable: true,
  11980 		hide: null,
  11981 		height: "auto",
  11982 		maxHeight: null,
  11983 		maxWidth: null,
  11984 		minHeight: 150,
  11985 		minWidth: 150,
  11986 		modal: false,
  11987 		position: {
  11988 			my: "center",
  11989 			at: "center",
  11990 			of: window,
  11991 			collision: "fit",
  11992 
  11993 			// Ensure the titlebar is always visible
  11994 			using: function( pos ) {
  11995 				var topOffset = $( this ).css( pos ).offset().top;
  11996 				if ( topOffset < 0 ) {
  11997 					$( this ).css( "top", pos.top - topOffset );
  11998 				}
  11999 			}
  12000 		},
  12001 		resizable: true,
  12002 		show: null,
  12003 		title: null,
  12004 		width: 300,
  12005 
  12006 		// Callbacks
  12007 		beforeClose: null,
  12008 		close: null,
  12009 		drag: null,
  12010 		dragStart: null,
  12011 		dragStop: null,
  12012 		focus: null,
  12013 		open: null,
  12014 		resize: null,
  12015 		resizeStart: null,
  12016 		resizeStop: null
  12017 	},
  12018 
  12019 	sizeRelatedOptions: {
  12020 		buttons: true,
  12021 		height: true,
  12022 		maxHeight: true,
  12023 		maxWidth: true,
  12024 		minHeight: true,
  12025 		minWidth: true,
  12026 		width: true
  12027 	},
  12028 
  12029 	resizableRelatedOptions: {
  12030 		maxHeight: true,
  12031 		maxWidth: true,
  12032 		minHeight: true,
  12033 		minWidth: true
  12034 	},
  12035 
  12036 	_create: function() {
  12037 		this.originalCss = {
  12038 			display: this.element[ 0 ].style.display,
  12039 			width: this.element[ 0 ].style.width,
  12040 			minHeight: this.element[ 0 ].style.minHeight,
  12041 			maxHeight: this.element[ 0 ].style.maxHeight,
  12042 			height: this.element[ 0 ].style.height
  12043 		};
  12044 		this.originalPosition = {
  12045 			parent: this.element.parent(),
  12046 			index: this.element.parent().children().index( this.element )
  12047 		};
  12048 		this.originalTitle = this.element.attr( "title" );
  12049 		if ( this.options.title == null && this.originalTitle != null ) {
  12050 			this.options.title = this.originalTitle;
  12051 		}
  12052 
  12053 		// Dialogs can't be disabled
  12054 		if ( this.options.disabled ) {
  12055 			this.options.disabled = false;
  12056 		}
  12057 
  12058 		this._createWrapper();
  12059 
  12060 		this.element
  12061 			.show()
  12062 			.removeAttr( "title" )
  12063 			.appendTo( this.uiDialog );
  12064 
  12065 		this._addClass( "ui-dialog-content", "ui-widget-content" );
  12066 
  12067 		this._createTitlebar();
  12068 		this._createButtonPane();
  12069 
  12070 		if ( this.options.draggable && $.fn.draggable ) {
  12071 			this._makeDraggable();
  12072 		}
  12073 		if ( this.options.resizable && $.fn.resizable ) {
  12074 			this._makeResizable();
  12075 		}
  12076 
  12077 		this._isOpen = false;
  12078 
  12079 		this._trackFocus();
  12080 	},
  12081 
  12082 	_init: function() {
  12083 		if ( this.options.autoOpen ) {
  12084 			this.open();
  12085 		}
  12086 	},
  12087 
  12088 	_appendTo: function() {
  12089 		var element = this.options.appendTo;
  12090 		if ( element && ( element.jquery || element.nodeType ) ) {
  12091 			return $( element );
  12092 		}
  12093 		return this.document.find( element || "body" ).eq( 0 );
  12094 	},
  12095 
  12096 	_destroy: function() {
  12097 		var next,
  12098 			originalPosition = this.originalPosition;
  12099 
  12100 		this._untrackInstance();
  12101 		this._destroyOverlay();
  12102 
  12103 		this.element
  12104 			.removeUniqueId()
  12105 			.css( this.originalCss )
  12106 
  12107 			// Without detaching first, the following becomes really slow
  12108 			.detach();
  12109 
  12110 		this.uiDialog.remove();
  12111 
  12112 		if ( this.originalTitle ) {
  12113 			this.element.attr( "title", this.originalTitle );
  12114 		}
  12115 
  12116 		next = originalPosition.parent.children().eq( originalPosition.index );
  12117 
  12118 		// Don't try to place the dialog next to itself (#8613)
  12119 		if ( next.length && next[ 0 ] !== this.element[ 0 ] ) {
  12120 			next.before( this.element );
  12121 		} else {
  12122 			originalPosition.parent.append( this.element );
  12123 		}
  12124 	},
  12125 
  12126 	widget: function() {
  12127 		return this.uiDialog;
  12128 	},
  12129 
  12130 	disable: $.noop,
  12131 	enable: $.noop,
  12132 
  12133 	close: function( event ) {
  12134 		var that = this;
  12135 
  12136 		if ( !this._isOpen || this._trigger( "beforeClose", event ) === false ) {
  12137 			return;
  12138 		}
  12139 
  12140 		this._isOpen = false;
  12141 		this._focusedElement = null;
  12142 		this._destroyOverlay();
  12143 		this._untrackInstance();
  12144 
  12145 		if ( !this.opener.filter( ":focusable" ).trigger( "focus" ).length ) {
  12146 
  12147 			// Hiding a focused element doesn't trigger blur in WebKit
  12148 			// so in case we have nothing to focus on, explicitly blur the active element
  12149 			// https://bugs.webkit.org/show_bug.cgi?id=47182
  12150 			$.ui.safeBlur( $.ui.safeActiveElement( this.document[ 0 ] ) );
  12151 		}
  12152 
  12153 		this._hide( this.uiDialog, this.options.hide, function() {
  12154 			that._trigger( "close", event );
  12155 		} );
  12156 	},
  12157 
  12158 	isOpen: function() {
  12159 		return this._isOpen;
  12160 	},
  12161 
  12162 	moveToTop: function() {
  12163 		this._moveToTop();
  12164 	},
  12165 
  12166 	_moveToTop: function( event, silent ) {
  12167 		var moved = false,
  12168 			zIndices = this.uiDialog.siblings( ".ui-front:visible" ).map( function() {
  12169 				return +$( this ).css( "z-index" );
  12170 			} ).get(),
  12171 			zIndexMax = Math.max.apply( null, zIndices );
  12172 
  12173 		if ( zIndexMax >= +this.uiDialog.css( "z-index" ) ) {
  12174 			this.uiDialog.css( "z-index", zIndexMax + 1 );
  12175 			moved = true;
  12176 		}
  12177 
  12178 		if ( moved && !silent ) {
  12179 			this._trigger( "focus", event );
  12180 		}
  12181 		return moved;
  12182 	},
  12183 
  12184 	open: function() {
  12185 		var that = this;
  12186 		if ( this._isOpen ) {
  12187 			if ( this._moveToTop() ) {
  12188 				this._focusTabbable();
  12189 			}
  12190 			return;
  12191 		}
  12192 
  12193 		this._isOpen = true;
  12194 		this.opener = $( $.ui.safeActiveElement( this.document[ 0 ] ) );
  12195 
  12196 		this._size();
  12197 		this._position();
  12198 		this._createOverlay();
  12199 		this._moveToTop( null, true );
  12200 
  12201 		// Ensure the overlay is moved to the top with the dialog, but only when
  12202 		// opening. The overlay shouldn't move after the dialog is open so that
  12203 		// modeless dialogs opened after the modal dialog stack properly.
  12204 		if ( this.overlay ) {
  12205 			this.overlay.css( "z-index", this.uiDialog.css( "z-index" ) - 1 );
  12206 		}
  12207 
  12208 		this._show( this.uiDialog, this.options.show, function() {
  12209 			that._focusTabbable();
  12210 			that._trigger( "focus" );
  12211 		} );
  12212 
  12213 		// Track the dialog immediately upon openening in case a focus event
  12214 		// somehow occurs outside of the dialog before an element inside the
  12215 		// dialog is focused (#10152)
  12216 		this._makeFocusTarget();
  12217 
  12218 		this._trigger( "open" );
  12219 	},
  12220 
  12221 	_focusTabbable: function() {
  12222 
  12223 		// Set focus to the first match:
  12224 		// 1. An element that was focused previously
  12225 		// 2. First element inside the dialog matching [autofocus]
  12226 		// 3. Tabbable element inside the content element
  12227 		// 4. Tabbable element inside the buttonpane
  12228 		// 5. The close button
  12229 		// 6. The dialog itself
  12230 		var hasFocus = this._focusedElement;
  12231 		if ( !hasFocus ) {
  12232 			hasFocus = this.element.find( "[autofocus]" );
  12233 		}
  12234 		if ( !hasFocus.length ) {
  12235 			hasFocus = this.element.find( ":tabbable" );
  12236 		}
  12237 		if ( !hasFocus.length ) {
  12238 			hasFocus = this.uiDialogButtonPane.find( ":tabbable" );
  12239 		}
  12240 		if ( !hasFocus.length ) {
  12241 			hasFocus = this.uiDialogTitlebarClose.filter( ":tabbable" );
  12242 		}
  12243 		if ( !hasFocus.length ) {
  12244 			hasFocus = this.uiDialog;
  12245 		}
  12246 		hasFocus.eq( 0 ).trigger( "focus" );
  12247 	},
  12248 
  12249 	_keepFocus: function( event ) {
  12250 		function checkFocus() {
  12251 			var activeElement = $.ui.safeActiveElement( this.document[ 0 ] ),
  12252 				isActive = this.uiDialog[ 0 ] === activeElement ||
  12253 					$.contains( this.uiDialog[ 0 ], activeElement );
  12254 			if ( !isActive ) {
  12255 				this._focusTabbable();
  12256 			}
  12257 		}
  12258 		event.preventDefault();
  12259 		checkFocus.call( this );
  12260 
  12261 		// support: IE
  12262 		// IE <= 8 doesn't prevent moving focus even with event.preventDefault()
  12263 		// so we check again later
  12264 		this._delay( checkFocus );
  12265 	},
  12266 
  12267 	_createWrapper: function() {
  12268 		this.uiDialog = $( "<div>" )
  12269 			.hide()
  12270 			.attr( {
  12271 
  12272 				// Setting tabIndex makes the div focusable
  12273 				tabIndex: -1,
  12274 				role: "dialog"
  12275 			} )
  12276 			.appendTo( this._appendTo() );
  12277 
  12278 		this._addClass( this.uiDialog, "ui-dialog", "ui-widget ui-widget-content ui-front" );
  12279 		this._on( this.uiDialog, {
  12280 			keydown: function( event ) {
  12281 				if ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
  12282 						event.keyCode === $.ui.keyCode.ESCAPE ) {
  12283 					event.preventDefault();
  12284 					this.close( event );
  12285 					return;
  12286 				}
  12287 
  12288 				// Prevent tabbing out of dialogs
  12289 				if ( event.keyCode !== $.ui.keyCode.TAB || event.isDefaultPrevented() ) {
  12290 					return;
  12291 				}
  12292 				var tabbables = this.uiDialog.find( ":tabbable" ),
  12293 					first = tabbables.filter( ":first" ),
  12294 					last = tabbables.filter( ":last" );
  12295 
  12296 				if ( ( event.target === last[ 0 ] || event.target === this.uiDialog[ 0 ] ) &&
  12297 						!event.shiftKey ) {
  12298 					this._delay( function() {
  12299 						first.trigger( "focus" );
  12300 					} );
  12301 					event.preventDefault();
  12302 				} else if ( ( event.target === first[ 0 ] ||
  12303 						event.target === this.uiDialog[ 0 ] ) && event.shiftKey ) {
  12304 					this._delay( function() {
  12305 						last.trigger( "focus" );
  12306 					} );
  12307 					event.preventDefault();
  12308 				}
  12309 			},
  12310 			mousedown: function( event ) {
  12311 				if ( this._moveToTop( event ) ) {
  12312 					this._focusTabbable();
  12313 				}
  12314 			}
  12315 		} );
  12316 
  12317 		// We assume that any existing aria-describedby attribute means
  12318 		// that the dialog content is marked up properly
  12319 		// otherwise we brute force the content as the description
  12320 		if ( !this.element.find( "[aria-describedby]" ).length ) {
  12321 			this.uiDialog.attr( {
  12322 				"aria-describedby": this.element.uniqueId().attr( "id" )
  12323 			} );
  12324 		}
  12325 	},
  12326 
  12327 	_createTitlebar: function() {
  12328 		var uiDialogTitle;
  12329 
  12330 		this.uiDialogTitlebar = $( "<div>" );
  12331 		this._addClass( this.uiDialogTitlebar,
  12332 			"ui-dialog-titlebar", "ui-widget-header ui-helper-clearfix" );
  12333 		this._on( this.uiDialogTitlebar, {
  12334 			mousedown: function( event ) {
  12335 
  12336 				// Don't prevent click on close button (#8838)
  12337 				// Focusing a dialog that is partially scrolled out of view
  12338 				// causes the browser to scroll it into view, preventing the click event
  12339 				if ( !$( event.target ).closest( ".ui-dialog-titlebar-close" ) ) {
  12340 
  12341 					// Dialog isn't getting focus when dragging (#8063)
  12342 					this.uiDialog.trigger( "focus" );
  12343 				}
  12344 			}
  12345 		} );
  12346 
  12347 		// Support: IE
  12348 		// Use type="button" to prevent enter keypresses in textboxes from closing the
  12349 		// dialog in IE (#9312)
  12350 		this.uiDialogTitlebarClose = $( "<button type='button'></button>" )
  12351 			.button( {
  12352 				label: $( "<a>" ).text( this.options.closeText ).html(),
  12353 				icon: "ui-icon-closethick",
  12354 				showLabel: false
  12355 			} )
  12356 			.appendTo( this.uiDialogTitlebar );
  12357 
  12358 		this._addClass( this.uiDialogTitlebarClose, "ui-dialog-titlebar-close" );
  12359 		this._on( this.uiDialogTitlebarClose, {
  12360 			click: function( event ) {
  12361 				event.preventDefault();
  12362 				this.close( event );
  12363 			}
  12364 		} );
  12365 
  12366 		uiDialogTitle = $( "<span>" ).uniqueId().prependTo( this.uiDialogTitlebar );
  12367 		this._addClass( uiDialogTitle, "ui-dialog-title" );
  12368 		this._title( uiDialogTitle );
  12369 
  12370 		this.uiDialogTitlebar.prependTo( this.uiDialog );
  12371 
  12372 		this.uiDialog.attr( {
  12373 			"aria-labelledby": uiDialogTitle.attr( "id" )
  12374 		} );
  12375 	},
  12376 
  12377 	_title: function( title ) {
  12378 		if ( this.options.title ) {
  12379 			title.text( this.options.title );
  12380 		} else {
  12381 			title.html( "&#160;" );
  12382 		}
  12383 	},
  12384 
  12385 	_createButtonPane: function() {
  12386 		this.uiDialogButtonPane = $( "<div>" );
  12387 		this._addClass( this.uiDialogButtonPane, "ui-dialog-buttonpane",
  12388 			"ui-widget-content ui-helper-clearfix" );
  12389 
  12390 		this.uiButtonSet = $( "<div>" )
  12391 			.appendTo( this.uiDialogButtonPane );
  12392 		this._addClass( this.uiButtonSet, "ui-dialog-buttonset" );
  12393 
  12394 		this._createButtons();
  12395 	},
  12396 
  12397 	_createButtons: function() {
  12398 		var that = this,
  12399 			buttons = this.options.buttons;
  12400 
  12401 		// If we already have a button pane, remove it
  12402 		this.uiDialogButtonPane.remove();
  12403 		this.uiButtonSet.empty();
  12404 
  12405 		if ( $.isEmptyObject( buttons ) || ( $.isArray( buttons ) && !buttons.length ) ) {
  12406 			this._removeClass( this.uiDialog, "ui-dialog-buttons" );
  12407 			return;
  12408 		}
  12409 
  12410 		$.each( buttons, function( name, props ) {
  12411 			var click, buttonOptions;
  12412 			props = $.isFunction( props ) ?
  12413 				{ click: props, text: name } :
  12414 				props;
  12415 
  12416 			// Default to a non-submitting button
  12417 			props = $.extend( { type: "button" }, props );
  12418 
  12419 			// Change the context for the click callback to be the main element
  12420 			click = props.click;
  12421 			buttonOptions = {
  12422 				icon: props.icon,
  12423 				iconPosition: props.iconPosition,
  12424 				showLabel: props.showLabel,
  12425 
  12426 				// Deprecated options
  12427 				icons: props.icons,
  12428 				text: props.text
  12429 			};
  12430 
  12431 			delete props.click;
  12432 			delete props.icon;
  12433 			delete props.iconPosition;
  12434 			delete props.showLabel;
  12435 
  12436 			// Deprecated options
  12437 			delete props.icons;
  12438 			if ( typeof props.text === "boolean" ) {
  12439 				delete props.text;
  12440 			}
  12441 
  12442 			$( "<button></button>", props )
  12443 				.button( buttonOptions )
  12444 				.appendTo( that.uiButtonSet )
  12445 				.on( "click", function() {
  12446 					click.apply( that.element[ 0 ], arguments );
  12447 				} );
  12448 		} );
  12449 		this._addClass( this.uiDialog, "ui-dialog-buttons" );
  12450 		this.uiDialogButtonPane.appendTo( this.uiDialog );
  12451 	},
  12452 
  12453 	_makeDraggable: function() {
  12454 		var that = this,
  12455 			options = this.options;
  12456 
  12457 		function filteredUi( ui ) {
  12458 			return {
  12459 				position: ui.position,
  12460 				offset: ui.offset
  12461 			};
  12462 		}
  12463 
  12464 		this.uiDialog.draggable( {
  12465 			cancel: ".ui-dialog-content, .ui-dialog-titlebar-close",
  12466 			handle: ".ui-dialog-titlebar",
  12467 			containment: "document",
  12468 			start: function( event, ui ) {
  12469 				that._addClass( $( this ), "ui-dialog-dragging" );
  12470 				that._blockFrames();
  12471 				that._trigger( "dragStart", event, filteredUi( ui ) );
  12472 			},
  12473 			drag: function( event, ui ) {
  12474 				that._trigger( "drag", event, filteredUi( ui ) );
  12475 			},
  12476 			stop: function( event, ui ) {
  12477 				var left = ui.offset.left - that.document.scrollLeft(),
  12478 					top = ui.offset.top - that.document.scrollTop();
  12479 
  12480 				options.position = {
  12481 					my: "left top",
  12482 					at: "left" + ( left >= 0 ? "+" : "" ) + left + " " +
  12483 						"top" + ( top >= 0 ? "+" : "" ) + top,
  12484 					of: that.window
  12485 				};
  12486 				that._removeClass( $( this ), "ui-dialog-dragging" );
  12487 				that._unblockFrames();
  12488 				that._trigger( "dragStop", event, filteredUi( ui ) );
  12489 			}
  12490 		} );
  12491 	},
  12492 
  12493 	_makeResizable: function() {
  12494 		var that = this,
  12495 			options = this.options,
  12496 			handles = options.resizable,
  12497 
  12498 			// .ui-resizable has position: relative defined in the stylesheet
  12499 			// but dialogs have to use absolute or fixed positioning
  12500 			position = this.uiDialog.css( "position" ),
  12501 			resizeHandles = typeof handles === "string" ?
  12502 				handles :
  12503 				"n,e,s,w,se,sw,ne,nw";
  12504 
  12505 		function filteredUi( ui ) {
  12506 			return {
  12507 				originalPosition: ui.originalPosition,
  12508 				originalSize: ui.originalSize,
  12509 				position: ui.position,
  12510 				size: ui.size
  12511 			};
  12512 		}
  12513 
  12514 		this.uiDialog.resizable( {
  12515 			cancel: ".ui-dialog-content",
  12516 			containment: "document",
  12517 			alsoResize: this.element,
  12518 			maxWidth: options.maxWidth,
  12519 			maxHeight: options.maxHeight,
  12520 			minWidth: options.minWidth,
  12521 			minHeight: this._minHeight(),
  12522 			handles: resizeHandles,
  12523 			start: function( event, ui ) {
  12524 				that._addClass( $( this ), "ui-dialog-resizing" );
  12525 				that._blockFrames();
  12526 				that._trigger( "resizeStart", event, filteredUi( ui ) );
  12527 			},
  12528 			resize: function( event, ui ) {
  12529 				that._trigger( "resize", event, filteredUi( ui ) );
  12530 			},
  12531 			stop: function( event, ui ) {
  12532 				var offset = that.uiDialog.offset(),
  12533 					left = offset.left - that.document.scrollLeft(),
  12534 					top = offset.top - that.document.scrollTop();
  12535 
  12536 				options.height = that.uiDialog.height();
  12537 				options.width = that.uiDialog.width();
  12538 				options.position = {
  12539 					my: "left top",
  12540 					at: "left" + ( left >= 0 ? "+" : "" ) + left + " " +
  12541 						"top" + ( top >= 0 ? "+" : "" ) + top,
  12542 					of: that.window
  12543 				};
  12544 				that._removeClass( $( this ), "ui-dialog-resizing" );
  12545 				that._unblockFrames();
  12546 				that._trigger( "resizeStop", event, filteredUi( ui ) );
  12547 			}
  12548 		} )
  12549 			.css( "position", position );
  12550 	},
  12551 
  12552 	_trackFocus: function() {
  12553 		this._on( this.widget(), {
  12554 			focusin: function( event ) {
  12555 				this._makeFocusTarget();
  12556 				this._focusedElement = $( event.target );
  12557 			}
  12558 		} );
  12559 	},
  12560 
  12561 	_makeFocusTarget: function() {
  12562 		this._untrackInstance();
  12563 		this._trackingInstances().unshift( this );
  12564 	},
  12565 
  12566 	_untrackInstance: function() {
  12567 		var instances = this._trackingInstances(),
  12568 			exists = $.inArray( this, instances );
  12569 		if ( exists !== -1 ) {
  12570 			instances.splice( exists, 1 );
  12571 		}
  12572 	},
  12573 
  12574 	_trackingInstances: function() {
  12575 		var instances = this.document.data( "ui-dialog-instances" );
  12576 		if ( !instances ) {
  12577 			instances = [];
  12578 			this.document.data( "ui-dialog-instances", instances );
  12579 		}
  12580 		return instances;
  12581 	},
  12582 
  12583 	_minHeight: function() {
  12584 		var options = this.options;
  12585 
  12586 		return options.height === "auto" ?
  12587 			options.minHeight :
  12588 			Math.min( options.minHeight, options.height );
  12589 	},
  12590 
  12591 	_position: function() {
  12592 
  12593 		// Need to show the dialog to get the actual offset in the position plugin
  12594 		var isVisible = this.uiDialog.is( ":visible" );
  12595 		if ( !isVisible ) {
  12596 			this.uiDialog.show();
  12597 		}
  12598 		this.uiDialog.position( this.options.position );
  12599 		if ( !isVisible ) {
  12600 			this.uiDialog.hide();
  12601 		}
  12602 	},
  12603 
  12604 	_setOptions: function( options ) {
  12605 		var that = this,
  12606 			resize = false,
  12607 			resizableOptions = {};
  12608 
  12609 		$.each( options, function( key, value ) {
  12610 			that._setOption( key, value );
  12611 
  12612 			if ( key in that.sizeRelatedOptions ) {
  12613 				resize = true;
  12614 			}
  12615 			if ( key in that.resizableRelatedOptions ) {
  12616 				resizableOptions[ key ] = value;
  12617 			}
  12618 		} );
  12619 
  12620 		if ( resize ) {
  12621 			this._size();
  12622 			this._position();
  12623 		}
  12624 		if ( this.uiDialog.is( ":data(ui-resizable)" ) ) {
  12625 			this.uiDialog.resizable( "option", resizableOptions );
  12626 		}
  12627 	},
  12628 
  12629 	_setOption: function( key, value ) {
  12630 		var isDraggable, isResizable,
  12631 			uiDialog = this.uiDialog;
  12632 
  12633 		if ( key === "disabled" ) {
  12634 			return;
  12635 		}
  12636 
  12637 		this._super( key, value );
  12638 
  12639 		if ( key === "appendTo" ) {
  12640 			this.uiDialog.appendTo( this._appendTo() );
  12641 		}
  12642 
  12643 		if ( key === "buttons" ) {
  12644 			this._createButtons();
  12645 		}
  12646 
  12647 		if ( key === "closeText" ) {
  12648 			this.uiDialogTitlebarClose.button( {
  12649 
  12650 				// Ensure that we always pass a string
  12651 				label: $( "<a>" ).text( "" + this.options.closeText ).html()
  12652 			} );
  12653 		}
  12654 
  12655 		if ( key === "draggable" ) {
  12656 			isDraggable = uiDialog.is( ":data(ui-draggable)" );
  12657 			if ( isDraggable && !value ) {
  12658 				uiDialog.draggable( "destroy" );
  12659 			}
  12660 
  12661 			if ( !isDraggable && value ) {
  12662 				this._makeDraggable();
  12663 			}
  12664 		}
  12665 
  12666 		if ( key === "position" ) {
  12667 			this._position();
  12668 		}
  12669 
  12670 		if ( key === "resizable" ) {
  12671 
  12672 			// currently resizable, becoming non-resizable
  12673 			isResizable = uiDialog.is( ":data(ui-resizable)" );
  12674 			if ( isResizable && !value ) {
  12675 				uiDialog.resizable( "destroy" );
  12676 			}
  12677 
  12678 			// Currently resizable, changing handles
  12679 			if ( isResizable && typeof value === "string" ) {
  12680 				uiDialog.resizable( "option", "handles", value );
  12681 			}
  12682 
  12683 			// Currently non-resizable, becoming resizable
  12684 			if ( !isResizable && value !== false ) {
  12685 				this._makeResizable();
  12686 			}
  12687 		}
  12688 
  12689 		if ( key === "title" ) {
  12690 			this._title( this.uiDialogTitlebar.find( ".ui-dialog-title" ) );
  12691 		}
  12692 	},
  12693 
  12694 	_size: function() {
  12695 
  12696 		// If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
  12697 		// divs will both have width and height set, so we need to reset them
  12698 		var nonContentHeight, minContentHeight, maxContentHeight,
  12699 			options = this.options;
  12700 
  12701 		// Reset content sizing
  12702 		this.element.show().css( {
  12703 			width: "auto",
  12704 			minHeight: 0,
  12705 			maxHeight: "none",
  12706 			height: 0
  12707 		} );
  12708 
  12709 		if ( options.minWidth > options.width ) {
  12710 			options.width = options.minWidth;
  12711 		}
  12712 
  12713 		// Reset wrapper sizing
  12714 		// determine the height of all the non-content elements
  12715 		nonContentHeight = this.uiDialog.css( {
  12716 			height: "auto",
  12717 			width: options.width
  12718 		} )
  12719 			.outerHeight();
  12720 		minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
  12721 		maxContentHeight = typeof options.maxHeight === "number" ?
  12722 			Math.max( 0, options.maxHeight - nonContentHeight ) :
  12723 			"none";
  12724 
  12725 		if ( options.height === "auto" ) {
  12726 			this.element.css( {
  12727 				minHeight: minContentHeight,
  12728 				maxHeight: maxContentHeight,
  12729 				height: "auto"
  12730 			} );
  12731 		} else {
  12732 			this.element.height( Math.max( 0, options.height - nonContentHeight ) );
  12733 		}
  12734 
  12735 		if ( this.uiDialog.is( ":data(ui-resizable)" ) ) {
  12736 			this.uiDialog.resizable( "option", "minHeight", this._minHeight() );
  12737 		}
  12738 	},
  12739 
  12740 	_blockFrames: function() {
  12741 		this.iframeBlocks = this.document.find( "iframe" ).map( function() {
  12742 			var iframe = $( this );
  12743 
  12744 			return $( "<div>" )
  12745 				.css( {
  12746 					position: "absolute",
  12747 					width: iframe.outerWidth(),
  12748 					height: iframe.outerHeight()
  12749 				} )
  12750 				.appendTo( iframe.parent() )
  12751 				.offset( iframe.offset() )[ 0 ];
  12752 		} );
  12753 	},
  12754 
  12755 	_unblockFrames: function() {
  12756 		if ( this.iframeBlocks ) {
  12757 			this.iframeBlocks.remove();
  12758 			delete this.iframeBlocks;
  12759 		}
  12760 	},
  12761 
  12762 	_allowInteraction: function( event ) {
  12763 		if ( $( event.target ).closest( ".ui-dialog" ).length ) {
  12764 			return true;
  12765 		}
  12766 
  12767 		// TODO: Remove hack when datepicker implements
  12768 		// the .ui-front logic (#8989)
  12769 		return !!$( event.target ).closest( ".ui-datepicker" ).length;
  12770 	},
  12771 
  12772 	_createOverlay: function() {
  12773 		if ( !this.options.modal ) {
  12774 			return;
  12775 		}
  12776 
  12777 		// We use a delay in case the overlay is created from an
  12778 		// event that we're going to be cancelling (#2804)
  12779 		var isOpening = true;
  12780 		this._delay( function() {
  12781 			isOpening = false;
  12782 		} );
  12783 
  12784 		if ( !this.document.data( "ui-dialog-overlays" ) ) {
  12785 
  12786 			// Prevent use of anchors and inputs
  12787 			// Using _on() for an event handler shared across many instances is
  12788 			// safe because the dialogs stack and must be closed in reverse order
  12789 			this._on( this.document, {
  12790 				focusin: function( event ) {
  12791 					if ( isOpening ) {
  12792 						return;
  12793 					}
  12794 
  12795 					if ( !this._allowInteraction( event ) ) {
  12796 						event.preventDefault();
  12797 						this._trackingInstances()[ 0 ]._focusTabbable();
  12798 					}
  12799 				}
  12800 			} );
  12801 		}
  12802 
  12803 		this.overlay = $( "<div>" )
  12804 			.appendTo( this._appendTo() );
  12805 
  12806 		this._addClass( this.overlay, null, "ui-widget-overlay ui-front" );
  12807 		this._on( this.overlay, {
  12808 			mousedown: "_keepFocus"
  12809 		} );
  12810 		this.document.data( "ui-dialog-overlays",
  12811 			( this.document.data( "ui-dialog-overlays" ) || 0 ) + 1 );
  12812 	},
  12813 
  12814 	_destroyOverlay: function() {
  12815 		if ( !this.options.modal ) {
  12816 			return;
  12817 		}
  12818 
  12819 		if ( this.overlay ) {
  12820 			var overlays = this.document.data( "ui-dialog-overlays" ) - 1;
  12821 
  12822 			if ( !overlays ) {
  12823 				this._off( this.document, "focusin" );
  12824 				this.document.removeData( "ui-dialog-overlays" );
  12825 			} else {
  12826 				this.document.data( "ui-dialog-overlays", overlays );
  12827 			}
  12828 
  12829 			this.overlay.remove();
  12830 			this.overlay = null;
  12831 		}
  12832 	}
  12833 } );
  12834 
  12835 // DEPRECATED
  12836 // TODO: switch return back to widget declaration at top of file when this is removed
  12837 if ( $.uiBackCompat !== false ) {
  12838 
  12839 	// Backcompat for dialogClass option
  12840 	$.widget( "ui.dialog", $.ui.dialog, {
  12841 		options: {
  12842 			dialogClass: ""
  12843 		},
  12844 		_createWrapper: function() {
  12845 			this._super();
  12846 			this.uiDialog.addClass( this.options.dialogClass );
  12847 		},
  12848 		_setOption: function( key, value ) {
  12849 			if ( key === "dialogClass" ) {
  12850 				this.uiDialog
  12851 					.removeClass( this.options.dialogClass )
  12852 					.addClass( value );
  12853 			}
  12854 			this._superApply( arguments );
  12855 		}
  12856 	} );
  12857 }
  12858 
  12859 var widgetsDialog = $.ui.dialog;
  12860 
  12861 
  12862 /*!
  12863  * jQuery UI Droppable 1.12.1
  12864  * http://jqueryui.com
  12865  *
  12866  * Copyright jQuery Foundation and other contributors
  12867  * Released under the MIT license.
  12868  * http://jquery.org/license
  12869  */
  12870 
  12871 //>>label: Droppable
  12872 //>>group: Interactions
  12873 //>>description: Enables drop targets for draggable elements.
  12874 //>>docs: http://api.jqueryui.com/droppable/
  12875 //>>demos: http://jqueryui.com/droppable/
  12876 
  12877 
  12878 
  12879 $.widget( "ui.droppable", {
  12880 	version: "1.12.1",
  12881 	widgetEventPrefix: "drop",
  12882 	options: {
  12883 		accept: "*",
  12884 		addClasses: true,
  12885 		greedy: false,
  12886 		scope: "default",
  12887 		tolerance: "intersect",
  12888 
  12889 		// Callbacks
  12890 		activate: null,
  12891 		deactivate: null,
  12892 		drop: null,
  12893 		out: null,
  12894 		over: null
  12895 	},
  12896 	_create: function() {
  12897 
  12898 		var proportions,
  12899 			o = this.options,
  12900 			accept = o.accept;
  12901 
  12902 		this.isover = false;
  12903 		this.isout = true;
  12904 
  12905 		this.accept = $.isFunction( accept ) ? accept : function( d ) {
  12906 			return d.is( accept );
  12907 		};
  12908 
  12909 		this.proportions = function( /* valueToWrite */ ) {
  12910 			if ( arguments.length ) {
  12911 
  12912 				// Store the droppable's proportions
  12913 				proportions = arguments[ 0 ];
  12914 			} else {
  12915 
  12916 				// Retrieve or derive the droppable's proportions
  12917 				return proportions ?
  12918 					proportions :
  12919 					proportions = {
  12920 						width: this.element[ 0 ].offsetWidth,
  12921 						height: this.element[ 0 ].offsetHeight
  12922 					};
  12923 			}
  12924 		};
  12925 
  12926 		this._addToManager( o.scope );
  12927 
  12928 		o.addClasses && this._addClass( "ui-droppable" );
  12929 
  12930 	},
  12931 
  12932 	_addToManager: function( scope ) {
  12933 
  12934 		// Add the reference and positions to the manager
  12935 		$.ui.ddmanager.droppables[ scope ] = $.ui.ddmanager.droppables[ scope ] || [];
  12936 		$.ui.ddmanager.droppables[ scope ].push( this );
  12937 	},
  12938 
  12939 	_splice: function( drop ) {
  12940 		var i = 0;
  12941 		for ( ; i < drop.length; i++ ) {
  12942 			if ( drop[ i ] === this ) {
  12943 				drop.splice( i, 1 );
  12944 			}
  12945 		}
  12946 	},
  12947 
  12948 	_destroy: function() {
  12949 		var drop = $.ui.ddmanager.droppables[ this.options.scope ];
  12950 
  12951 		this._splice( drop );
  12952 	},
  12953 
  12954 	_setOption: function( key, value ) {
  12955 
  12956 		if ( key === "accept" ) {
  12957 			this.accept = $.isFunction( value ) ? value : function( d ) {
  12958 				return d.is( value );
  12959 			};
  12960 		} else if ( key === "scope" ) {
  12961 			var drop = $.ui.ddmanager.droppables[ this.options.scope ];
  12962 
  12963 			this._splice( drop );
  12964 			this._addToManager( value );
  12965 		}
  12966 
  12967 		this._super( key, value );
  12968 	},
  12969 
  12970 	_activate: function( event ) {
  12971 		var draggable = $.ui.ddmanager.current;
  12972 
  12973 		this._addActiveClass();
  12974 		if ( draggable ) {
  12975 			this._trigger( "activate", event, this.ui( draggable ) );
  12976 		}
  12977 	},
  12978 
  12979 	_deactivate: function( event ) {
  12980 		var draggable = $.ui.ddmanager.current;
  12981 
  12982 		this._removeActiveClass();
  12983 		if ( draggable ) {
  12984 			this._trigger( "deactivate", event, this.ui( draggable ) );
  12985 		}
  12986 	},
  12987 
  12988 	_over: function( event ) {
  12989 
  12990 		var draggable = $.ui.ddmanager.current;
  12991 
  12992 		// Bail if draggable and droppable are same element
  12993 		if ( !draggable || ( draggable.currentItem ||
  12994 				draggable.element )[ 0 ] === this.element[ 0 ] ) {
  12995 			return;
  12996 		}
  12997 
  12998 		if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem ||
  12999 				draggable.element ) ) ) {
  13000 			this._addHoverClass();
  13001 			this._trigger( "over", event, this.ui( draggable ) );
  13002 		}
  13003 
  13004 	},
  13005 
  13006 	_out: function( event ) {
  13007 
  13008 		var draggable = $.ui.ddmanager.current;
  13009 
  13010 		// Bail if draggable and droppable are same element
  13011 		if ( !draggable || ( draggable.currentItem ||
  13012 				draggable.element )[ 0 ] === this.element[ 0 ] ) {
  13013 			return;
  13014 		}
  13015 
  13016 		if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem ||
  13017 				draggable.element ) ) ) {
  13018 			this._removeHoverClass();
  13019 			this._trigger( "out", event, this.ui( draggable ) );
  13020 		}
  13021 
  13022 	},
  13023 
  13024 	_drop: function( event, custom ) {
  13025 
  13026 		var draggable = custom || $.ui.ddmanager.current,
  13027 			childrenIntersection = false;
  13028 
  13029 		// Bail if draggable and droppable are same element
  13030 		if ( !draggable || ( draggable.currentItem ||
  13031 				draggable.element )[ 0 ] === this.element[ 0 ] ) {
  13032 			return false;
  13033 		}
  13034 
  13035 		this.element
  13036 			.find( ":data(ui-droppable)" )
  13037 			.not( ".ui-draggable-dragging" )
  13038 			.each( function() {
  13039 				var inst = $( this ).droppable( "instance" );
  13040 				if (
  13041 					inst.options.greedy &&
  13042 					!inst.options.disabled &&
  13043 					inst.options.scope === draggable.options.scope &&
  13044 					inst.accept.call(
  13045 						inst.element[ 0 ], ( draggable.currentItem || draggable.element )
  13046 					) &&
  13047 					intersect(
  13048 						draggable,
  13049 						$.extend( inst, { offset: inst.element.offset() } ),
  13050 						inst.options.tolerance, event
  13051 					)
  13052 				) {
  13053 					childrenIntersection = true;
  13054 					return false; }
  13055 			} );
  13056 		if ( childrenIntersection ) {
  13057 			return false;
  13058 		}
  13059 
  13060 		if ( this.accept.call( this.element[ 0 ],
  13061 				( draggable.currentItem || draggable.element ) ) ) {
  13062 			this._removeActiveClass();
  13063 			this._removeHoverClass();
  13064 
  13065 			this._trigger( "drop", event, this.ui( draggable ) );
  13066 			return this.element;
  13067 		}
  13068 
  13069 		return false;
  13070 
  13071 	},
  13072 
  13073 	ui: function( c ) {
  13074 		return {
  13075 			draggable: ( c.currentItem || c.element ),
  13076 			helper: c.helper,
  13077 			position: c.position,
  13078 			offset: c.positionAbs
  13079 		};
  13080 	},
  13081 
  13082 	// Extension points just to make backcompat sane and avoid duplicating logic
  13083 	// TODO: Remove in 1.13 along with call to it below
  13084 	_addHoverClass: function() {
  13085 		this._addClass( "ui-droppable-hover" );
  13086 	},
  13087 
  13088 	_removeHoverClass: function() {
  13089 		this._removeClass( "ui-droppable-hover" );
  13090 	},
  13091 
  13092 	_addActiveClass: function() {
  13093 		this._addClass( "ui-droppable-active" );
  13094 	},
  13095 
  13096 	_removeActiveClass: function() {
  13097 		this._removeClass( "ui-droppable-active" );
  13098 	}
  13099 } );
  13100 
  13101 var intersect = $.ui.intersect = ( function() {
  13102 	function isOverAxis( x, reference, size ) {
  13103 		return ( x >= reference ) && ( x < ( reference + size ) );
  13104 	}
  13105 
  13106 	return function( draggable, droppable, toleranceMode, event ) {
  13107 
  13108 		if ( !droppable.offset ) {
  13109 			return false;
  13110 		}
  13111 
  13112 		var x1 = ( draggable.positionAbs ||
  13113 				draggable.position.absolute ).left + draggable.margins.left,
  13114 			y1 = ( draggable.positionAbs ||
  13115 				draggable.position.absolute ).top + draggable.margins.top,
  13116 			x2 = x1 + draggable.helperProportions.width,
  13117 			y2 = y1 + draggable.helperProportions.height,
  13118 			l = droppable.offset.left,
  13119 			t = droppable.offset.top,
  13120 			r = l + droppable.proportions().width,
  13121 			b = t + droppable.proportions().height;
  13122 
  13123 		switch ( toleranceMode ) {
  13124 		case "fit":
  13125 			return ( l <= x1 && x2 <= r && t <= y1 && y2 <= b );
  13126 		case "intersect":
  13127 			return ( l < x1 + ( draggable.helperProportions.width / 2 ) && // Right Half
  13128 				x2 - ( draggable.helperProportions.width / 2 ) < r && // Left Half
  13129 				t < y1 + ( draggable.helperProportions.height / 2 ) && // Bottom Half
  13130 				y2 - ( draggable.helperProportions.height / 2 ) < b ); // Top Half
  13131 		case "pointer":
  13132 			return isOverAxis( event.pageY, t, droppable.proportions().height ) &&
  13133 				isOverAxis( event.pageX, l, droppable.proportions().width );
  13134 		case "touch":
  13135 			return (
  13136 				( y1 >= t && y1 <= b ) || // Top edge touching
  13137 				( y2 >= t && y2 <= b ) || // Bottom edge touching
  13138 				( y1 < t && y2 > b ) // Surrounded vertically
  13139 			) && (
  13140 				( x1 >= l && x1 <= r ) || // Left edge touching
  13141 				( x2 >= l && x2 <= r ) || // Right edge touching
  13142 				( x1 < l && x2 > r ) // Surrounded horizontally
  13143 			);
  13144 		default:
  13145 			return false;
  13146 		}
  13147 	};
  13148 } )();
  13149 
  13150 /*
  13151 	This manager tracks offsets of draggables and droppables
  13152 */
  13153 $.ui.ddmanager = {
  13154 	current: null,
  13155 	droppables: { "default": [] },
  13156 	prepareOffsets: function( t, event ) {
  13157 
  13158 		var i, j,
  13159 			m = $.ui.ddmanager.droppables[ t.options.scope ] || [],
  13160 			type = event ? event.type : null, // workaround for #2317
  13161 			list = ( t.currentItem || t.element ).find( ":data(ui-droppable)" ).addBack();
  13162 
  13163 		droppablesLoop: for ( i = 0; i < m.length; i++ ) {
  13164 
  13165 			// No disabled and non-accepted
  13166 			if ( m[ i ].options.disabled || ( t && !m[ i ].accept.call( m[ i ].element[ 0 ],
  13167 					( t.currentItem || t.element ) ) ) ) {
  13168 				continue;
  13169 			}
  13170 
  13171 			// Filter out elements in the current dragged item
  13172 			for ( j = 0; j < list.length; j++ ) {
  13173 				if ( list[ j ] === m[ i ].element[ 0 ] ) {
  13174 					m[ i ].proportions().height = 0;
  13175 					continue droppablesLoop;
  13176 				}
  13177 			}
  13178 
  13179 			m[ i ].visible = m[ i ].element.css( "display" ) !== "none";
  13180 			if ( !m[ i ].visible ) {
  13181 				continue;
  13182 			}
  13183 
  13184 			// Activate the droppable if used directly from draggables
  13185 			if ( type === "mousedown" ) {
  13186 				m[ i ]._activate.call( m[ i ], event );
  13187 			}
  13188 
  13189 			m[ i ].offset = m[ i ].element.offset();
  13190 			m[ i ].proportions( {
  13191 				width: m[ i ].element[ 0 ].offsetWidth,
  13192 				height: m[ i ].element[ 0 ].offsetHeight
  13193 			} );
  13194 
  13195 		}
  13196 
  13197 	},
  13198 	drop: function( draggable, event ) {
  13199 
  13200 		var dropped = false;
  13201 
  13202 		// Create a copy of the droppables in case the list changes during the drop (#9116)
  13203 		$.each( ( $.ui.ddmanager.droppables[ draggable.options.scope ] || [] ).slice(), function() {
  13204 
  13205 			if ( !this.options ) {
  13206 				return;
  13207 			}
  13208 			if ( !this.options.disabled && this.visible &&
  13209 					intersect( draggable, this, this.options.tolerance, event ) ) {
  13210 				dropped = this._drop.call( this, event ) || dropped;
  13211 			}
  13212 
  13213 			if ( !this.options.disabled && this.visible && this.accept.call( this.element[ 0 ],
  13214 					( draggable.currentItem || draggable.element ) ) ) {
  13215 				this.isout = true;
  13216 				this.isover = false;
  13217 				this._deactivate.call( this, event );
  13218 			}
  13219 
  13220 		} );
  13221 		return dropped;
  13222 
  13223 	},
  13224 	dragStart: function( draggable, event ) {
  13225 
  13226 		// Listen for scrolling so that if the dragging causes scrolling the position of the
  13227 		// droppables can be recalculated (see #5003)
  13228 		draggable.element.parentsUntil( "body" ).on( "scroll.droppable", function() {
  13229 			if ( !draggable.options.refreshPositions ) {
  13230 				$.ui.ddmanager.prepareOffsets( draggable, event );
  13231 			}
  13232 		} );
  13233 	},
  13234 	drag: function( draggable, event ) {
  13235 
  13236 		// If you have a highly dynamic page, you might try this option. It renders positions
  13237 		// every time you move the mouse.
  13238 		if ( draggable.options.refreshPositions ) {
  13239 			$.ui.ddmanager.prepareOffsets( draggable, event );
  13240 		}
  13241 
  13242 		// Run through all droppables and check their positions based on specific tolerance options
  13243 		$.each( $.ui.ddmanager.droppables[ draggable.options.scope ] || [], function() {
  13244 
  13245 			if ( this.options.disabled || this.greedyChild || !this.visible ) {
  13246 				return;
  13247 			}
  13248 
  13249 			var parentInstance, scope, parent,
  13250 				intersects = intersect( draggable, this, this.options.tolerance, event ),
  13251 				c = !intersects && this.isover ?
  13252 					"isout" :
  13253 					( intersects && !this.isover ? "isover" : null );
  13254 			if ( !c ) {
  13255 				return;
  13256 			}
  13257 
  13258 			if ( this.options.greedy ) {
  13259 
  13260 				// find droppable parents with same scope
  13261 				scope = this.options.scope;
  13262 				parent = this.element.parents( ":data(ui-droppable)" ).filter( function() {
  13263 					return $( this ).droppable( "instance" ).options.scope === scope;
  13264 				} );
  13265 
  13266 				if ( parent.length ) {
  13267 					parentInstance = $( parent[ 0 ] ).droppable( "instance" );
  13268 					parentInstance.greedyChild = ( c === "isover" );
  13269 				}
  13270 			}
  13271 
  13272 			// We just moved into a greedy child
  13273 			if ( parentInstance && c === "isover" ) {
  13274 				parentInstance.isover = false;
  13275 				parentInstance.isout = true;
  13276 				parentInstance._out.call( parentInstance, event );
  13277 			}
  13278 
  13279 			this[ c ] = true;
  13280 			this[ c === "isout" ? "isover" : "isout" ] = false;
  13281 			this[ c === "isover" ? "_over" : "_out" ].call( this, event );
  13282 
  13283 			// We just moved out of a greedy child
  13284 			if ( parentInstance && c === "isout" ) {
  13285 				parentInstance.isout = false;
  13286 				parentInstance.isover = true;
  13287 				parentInstance._over.call( parentInstance, event );
  13288 			}
  13289 		} );
  13290 
  13291 	},
  13292 	dragStop: function( draggable, event ) {
  13293 		draggable.element.parentsUntil( "body" ).off( "scroll.droppable" );
  13294 
  13295 		// Call prepareOffsets one final time since IE does not fire return scroll events when
  13296 		// overflow was caused by drag (see #5003)
  13297 		if ( !draggable.options.refreshPositions ) {
  13298 			$.ui.ddmanager.prepareOffsets( draggable, event );
  13299 		}
  13300 	}
  13301 };
  13302 
  13303 // DEPRECATED
  13304 // TODO: switch return back to widget declaration at top of file when this is removed
  13305 if ( $.uiBackCompat !== false ) {
  13306 
  13307 	// Backcompat for activeClass and hoverClass options
  13308 	$.widget( "ui.droppable", $.ui.droppable, {
  13309 		options: {
  13310 			hoverClass: false,
  13311 			activeClass: false
  13312 		},
  13313 		_addActiveClass: function() {
  13314 			this._super();
  13315 			if ( this.options.activeClass ) {
  13316 				this.element.addClass( this.options.activeClass );
  13317 			}
  13318 		},
  13319 		_removeActiveClass: function() {
  13320 			this._super();
  13321 			if ( this.options.activeClass ) {
  13322 				this.element.removeClass( this.options.activeClass );
  13323 			}
  13324 		},
  13325 		_addHoverClass: function() {
  13326 			this._super();
  13327 			if ( this.options.hoverClass ) {
  13328 				this.element.addClass( this.options.hoverClass );
  13329 			}
  13330 		},
  13331 		_removeHoverClass: function() {
  13332 			this._super();
  13333 			if ( this.options.hoverClass ) {
  13334 				this.element.removeClass( this.options.hoverClass );
  13335 			}
  13336 		}
  13337 	} );
  13338 }
  13339 
  13340 var widgetsDroppable = $.ui.droppable;
  13341 
  13342 
  13343 /*!
  13344  * jQuery UI Progressbar 1.12.1
  13345  * http://jqueryui.com
  13346  *
  13347  * Copyright jQuery Foundation and other contributors
  13348  * Released under the MIT license.
  13349  * http://jquery.org/license
  13350  */
  13351 
  13352 //>>label: Progressbar
  13353 //>>group: Widgets
  13354 // jscs:disable maximumLineLength
  13355 //>>description: Displays a status indicator for loading state, standard percentage, and other progress indicators.
  13356 // jscs:enable maximumLineLength
  13357 //>>docs: http://api.jqueryui.com/progressbar/
  13358 //>>demos: http://jqueryui.com/progressbar/
  13359 //>>css.structure: ../../themes/base/core.css
  13360 //>>css.structure: ../../themes/base/progressbar.css
  13361 //>>css.theme: ../../themes/base/theme.css
  13362 
  13363 
  13364 
  13365 var widgetsProgressbar = $.widget( "ui.progressbar", {
  13366 	version: "1.12.1",
  13367 	options: {
  13368 		classes: {
  13369 			"ui-progressbar": "ui-corner-all",
  13370 			"ui-progressbar-value": "ui-corner-left",
  13371 			"ui-progressbar-complete": "ui-corner-right"
  13372 		},
  13373 		max: 100,
  13374 		value: 0,
  13375 
  13376 		change: null,
  13377 		complete: null
  13378 	},
  13379 
  13380 	min: 0,
  13381 
  13382 	_create: function() {
  13383 
  13384 		// Constrain initial value
  13385 		this.oldValue = this.options.value = this._constrainedValue();
  13386 
  13387 		this.element.attr( {
  13388 
  13389 			// Only set static values; aria-valuenow and aria-valuemax are
  13390 			// set inside _refreshValue()
  13391 			role: "progressbar",
  13392 			"aria-valuemin": this.min
  13393 		} );
  13394 		this._addClass( "ui-progressbar", "ui-widget ui-widget-content" );
  13395 
  13396 		this.valueDiv = $( "<div>" ).appendTo( this.element );
  13397 		this._addClass( this.valueDiv, "ui-progressbar-value", "ui-widget-header" );
  13398 		this._refreshValue();
  13399 	},
  13400 
  13401 	_destroy: function() {
  13402 		this.element.removeAttr( "role aria-valuemin aria-valuemax aria-valuenow" );
  13403 
  13404 		this.valueDiv.remove();
  13405 	},
  13406 
  13407 	value: function( newValue ) {
  13408 		if ( newValue === undefined ) {
  13409 			return this.options.value;
  13410 		}
  13411 
  13412 		this.options.value = this._constrainedValue( newValue );
  13413 		this._refreshValue();
  13414 	},
  13415 
  13416 	_constrainedValue: function( newValue ) {
  13417 		if ( newValue === undefined ) {
  13418 			newValue = this.options.value;
  13419 		}
  13420 
  13421 		this.indeterminate = newValue === false;
  13422 
  13423 		// Sanitize value
  13424 		if ( typeof newValue !== "number" ) {
  13425 			newValue = 0;
  13426 		}
  13427 
  13428 		return this.indeterminate ? false :
  13429 			Math.min( this.options.max, Math.max( this.min, newValue ) );
  13430 	},
  13431 
  13432 	_setOptions: function( options ) {
  13433 
  13434 		// Ensure "value" option is set after other values (like max)
  13435 		var value = options.value;
  13436 		delete options.value;
  13437 
  13438 		this._super( options );
  13439 
  13440 		this.options.value = this._constrainedValue( value );
  13441 		this._refreshValue();
  13442 	},
  13443 
  13444 	_setOption: function( key, value ) {
  13445 		if ( key === "max" ) {
  13446 
  13447 			// Don't allow a max less than min
  13448 			value = Math.max( this.min, value );
  13449 		}
  13450 		this._super( key, value );
  13451 	},
  13452 
  13453 	_setOptionDisabled: function( value ) {
  13454 		this._super( value );
  13455 
  13456 		this.element.attr( "aria-disabled", value );
  13457 		this._toggleClass( null, "ui-state-disabled", !!value );
  13458 	},
  13459 
  13460 	_percentage: function() {
  13461 		return this.indeterminate ?
  13462 			100 :
  13463 			100 * ( this.options.value - this.min ) / ( this.options.max - this.min );
  13464 	},
  13465 
  13466 	_refreshValue: function() {
  13467 		var value = this.options.value,
  13468 			percentage = this._percentage();
  13469 
  13470 		this.valueDiv
  13471 			.toggle( this.indeterminate || value > this.min )
  13472 			.width( percentage.toFixed( 0 ) + "%" );
  13473 
  13474 		this
  13475 			._toggleClass( this.valueDiv, "ui-progressbar-complete", null,
  13476 				value === this.options.max )
  13477 			._toggleClass( "ui-progressbar-indeterminate", null, this.indeterminate );
  13478 
  13479 		if ( this.indeterminate ) {
  13480 			this.element.removeAttr( "aria-valuenow" );
  13481 			if ( !this.overlayDiv ) {
  13482 				this.overlayDiv = $( "<div>" ).appendTo( this.valueDiv );
  13483 				this._addClass( this.overlayDiv, "ui-progressbar-overlay" );
  13484 			}
  13485 		} else {
  13486 			this.element.attr( {
  13487 				"aria-valuemax": this.options.max,
  13488 				"aria-valuenow": value
  13489 			} );
  13490 			if ( this.overlayDiv ) {
  13491 				this.overlayDiv.remove();
  13492 				this.overlayDiv = null;
  13493 			}
  13494 		}
  13495 
  13496 		if ( this.oldValue !== value ) {
  13497 			this.oldValue = value;
  13498 			this._trigger( "change" );
  13499 		}
  13500 		if ( value === this.options.max ) {
  13501 			this._trigger( "complete" );
  13502 		}
  13503 	}
  13504 } );
  13505 
  13506 
  13507 /*!
  13508  * jQuery UI Selectable 1.12.1
  13509  * http://jqueryui.com
  13510  *
  13511  * Copyright jQuery Foundation and other contributors
  13512  * Released under the MIT license.
  13513  * http://jquery.org/license
  13514  */
  13515 
  13516 //>>label: Selectable
  13517 //>>group: Interactions
  13518 //>>description: Allows groups of elements to be selected with the mouse.
  13519 //>>docs: http://api.jqueryui.com/selectable/
  13520 //>>demos: http://jqueryui.com/selectable/
  13521 //>>css.structure: ../../themes/base/selectable.css
  13522 
  13523 
  13524 
  13525 var widgetsSelectable = $.widget( "ui.selectable", $.ui.mouse, {
  13526 	version: "1.12.1",
  13527 	options: {
  13528 		appendTo: "body",
  13529 		autoRefresh: true,
  13530 		distance: 0,
  13531 		filter: "*",
  13532 		tolerance: "touch",
  13533 
  13534 		// Callbacks
  13535 		selected: null,
  13536 		selecting: null,
  13537 		start: null,
  13538 		stop: null,
  13539 		unselected: null,
  13540 		unselecting: null
  13541 	},
  13542 	_create: function() {
  13543 		var that = this;
  13544 
  13545 		this._addClass( "ui-selectable" );
  13546 
  13547 		this.dragged = false;
  13548 
  13549 		// Cache selectee children based on filter
  13550 		this.refresh = function() {
  13551 			that.elementPos = $( that.element[ 0 ] ).offset();
  13552 			that.selectees = $( that.options.filter, that.element[ 0 ] );
  13553 			that._addClass( that.selectees, "ui-selectee" );
  13554 			that.selectees.each( function() {
  13555 				var $this = $( this ),
  13556 					selecteeOffset = $this.offset(),
  13557 					pos = {
  13558 						left: selecteeOffset.left - that.elementPos.left,
  13559 						top: selecteeOffset.top - that.elementPos.top
  13560 					};
  13561 				$.data( this, "selectable-item", {
  13562 					element: this,
  13563 					$element: $this,
  13564 					left: pos.left,
  13565 					top: pos.top,
  13566 					right: pos.left + $this.outerWidth(),
  13567 					bottom: pos.top + $this.outerHeight(),
  13568 					startselected: false,
  13569 					selected: $this.hasClass( "ui-selected" ),
  13570 					selecting: $this.hasClass( "ui-selecting" ),
  13571 					unselecting: $this.hasClass( "ui-unselecting" )
  13572 				} );
  13573 			} );
  13574 		};
  13575 		this.refresh();
  13576 
  13577 		this._mouseInit();
  13578 
  13579 		this.helper = $( "<div>" );
  13580 		this._addClass( this.helper, "ui-selectable-helper" );
  13581 	},
  13582 
  13583 	_destroy: function() {
  13584 		this.selectees.removeData( "selectable-item" );
  13585 		this._mouseDestroy();
  13586 	},
  13587 
  13588 	_mouseStart: function( event ) {
  13589 		var that = this,
  13590 			options = this.options;
  13591 
  13592 		this.opos = [ event.pageX, event.pageY ];
  13593 		this.elementPos = $( this.element[ 0 ] ).offset();
  13594 
  13595 		if ( this.options.disabled ) {
  13596 			return;
  13597 		}
  13598 
  13599 		this.selectees = $( options.filter, this.element[ 0 ] );
  13600 
  13601 		this._trigger( "start", event );
  13602 
  13603 		$( options.appendTo ).append( this.helper );
  13604 
  13605 		// position helper (lasso)
  13606 		this.helper.css( {
  13607 			"left": event.pageX,
  13608 			"top": event.pageY,
  13609 			"width": 0,
  13610 			"height": 0
  13611 		} );
  13612 
  13613 		if ( options.autoRefresh ) {
  13614 			this.refresh();
  13615 		}
  13616 
  13617 		this.selectees.filter( ".ui-selected" ).each( function() {
  13618 			var selectee = $.data( this, "selectable-item" );
  13619 			selectee.startselected = true;
  13620 			if ( !event.metaKey && !event.ctrlKey ) {
  13621 				that._removeClass( selectee.$element, "ui-selected" );
  13622 				selectee.selected = false;
  13623 				that._addClass( selectee.$element, "ui-unselecting" );
  13624 				selectee.unselecting = true;
  13625 
  13626 				// selectable UNSELECTING callback
  13627 				that._trigger( "unselecting", event, {
  13628 					unselecting: selectee.element
  13629 				} );
  13630 			}
  13631 		} );
  13632 
  13633 		$( event.target ).parents().addBack().each( function() {
  13634 			var doSelect,
  13635 				selectee = $.data( this, "selectable-item" );
  13636 			if ( selectee ) {
  13637 				doSelect = ( !event.metaKey && !event.ctrlKey ) ||
  13638 					!selectee.$element.hasClass( "ui-selected" );
  13639 				that._removeClass( selectee.$element, doSelect ? "ui-unselecting" : "ui-selected" )
  13640 					._addClass( selectee.$element, doSelect ? "ui-selecting" : "ui-unselecting" );
  13641 				selectee.unselecting = !doSelect;
  13642 				selectee.selecting = doSelect;
  13643 				selectee.selected = doSelect;
  13644 
  13645 				// selectable (UN)SELECTING callback
  13646 				if ( doSelect ) {
  13647 					that._trigger( "selecting", event, {
  13648 						selecting: selectee.element
  13649 					} );
  13650 				} else {
  13651 					that._trigger( "unselecting", event, {
  13652 						unselecting: selectee.element
  13653 					} );
  13654 				}
  13655 				return false;
  13656 			}
  13657 		} );
  13658 
  13659 	},
  13660 
  13661 	_mouseDrag: function( event ) {
  13662 
  13663 		this.dragged = true;
  13664 
  13665 		if ( this.options.disabled ) {
  13666 			return;
  13667 		}
  13668 
  13669 		var tmp,
  13670 			that = this,
  13671 			options = this.options,
  13672 			x1 = this.opos[ 0 ],
  13673 			y1 = this.opos[ 1 ],
  13674 			x2 = event.pageX,
  13675 			y2 = event.pageY;
  13676 
  13677 		if ( x1 > x2 ) { tmp = x2; x2 = x1; x1 = tmp; }
  13678 		if ( y1 > y2 ) { tmp = y2; y2 = y1; y1 = tmp; }
  13679 		this.helper.css( { left: x1, top: y1, width: x2 - x1, height: y2 - y1 } );
  13680 
  13681 		this.selectees.each( function() {
  13682 			var selectee = $.data( this, "selectable-item" ),
  13683 				hit = false,
  13684 				offset = {};
  13685 
  13686 			//prevent helper from being selected if appendTo: selectable
  13687 			if ( !selectee || selectee.element === that.element[ 0 ] ) {
  13688 				return;
  13689 			}
  13690 
  13691 			offset.left   = selectee.left   + that.elementPos.left;
  13692 			offset.right  = selectee.right  + that.elementPos.left;
  13693 			offset.top    = selectee.top    + that.elementPos.top;
  13694 			offset.bottom = selectee.bottom + that.elementPos.top;
  13695 
  13696 			if ( options.tolerance === "touch" ) {
  13697 				hit = ( !( offset.left > x2 || offset.right < x1 || offset.top > y2 ||
  13698                     offset.bottom < y1 ) );
  13699 			} else if ( options.tolerance === "fit" ) {
  13700 				hit = ( offset.left > x1 && offset.right < x2 && offset.top > y1 &&
  13701                     offset.bottom < y2 );
  13702 			}
  13703 
  13704 			if ( hit ) {
  13705 
  13706 				// SELECT
  13707 				if ( selectee.selected ) {
  13708 					that._removeClass( selectee.$element, "ui-selected" );
  13709 					selectee.selected = false;
  13710 				}
  13711 				if ( selectee.unselecting ) {
  13712 					that._removeClass( selectee.$element, "ui-unselecting" );
  13713 					selectee.unselecting = false;
  13714 				}
  13715 				if ( !selectee.selecting ) {
  13716 					that._addClass( selectee.$element, "ui-selecting" );
  13717 					selectee.selecting = true;
  13718 
  13719 					// selectable SELECTING callback
  13720 					that._trigger( "selecting", event, {
  13721 						selecting: selectee.element
  13722 					} );
  13723 				}
  13724 			} else {
  13725 
  13726 				// UNSELECT
  13727 				if ( selectee.selecting ) {
  13728 					if ( ( event.metaKey || event.ctrlKey ) && selectee.startselected ) {
  13729 						that._removeClass( selectee.$element, "ui-selecting" );
  13730 						selectee.selecting = false;
  13731 						that._addClass( selectee.$element, "ui-selected" );
  13732 						selectee.selected = true;
  13733 					} else {
  13734 						that._removeClass( selectee.$element, "ui-selecting" );
  13735 						selectee.selecting = false;
  13736 						if ( selectee.startselected ) {
  13737 							that._addClass( selectee.$element, "ui-unselecting" );
  13738 							selectee.unselecting = true;
  13739 						}
  13740 
  13741 						// selectable UNSELECTING callback
  13742 						that._trigger( "unselecting", event, {
  13743 							unselecting: selectee.element
  13744 						} );
  13745 					}
  13746 				}
  13747 				if ( selectee.selected ) {
  13748 					if ( !event.metaKey && !event.ctrlKey && !selectee.startselected ) {
  13749 						that._removeClass( selectee.$element, "ui-selected" );
  13750 						selectee.selected = false;
  13751 
  13752 						that._addClass( selectee.$element, "ui-unselecting" );
  13753 						selectee.unselecting = true;
  13754 
  13755 						// selectable UNSELECTING callback
  13756 						that._trigger( "unselecting", event, {
  13757 							unselecting: selectee.element
  13758 						} );
  13759 					}
  13760 				}
  13761 			}
  13762 		} );
  13763 
  13764 		return false;
  13765 	},
  13766 
  13767 	_mouseStop: function( event ) {
  13768 		var that = this;
  13769 
  13770 		this.dragged = false;
  13771 
  13772 		$( ".ui-unselecting", this.element[ 0 ] ).each( function() {
  13773 			var selectee = $.data( this, "selectable-item" );
  13774 			that._removeClass( selectee.$element, "ui-unselecting" );
  13775 			selectee.unselecting = false;
  13776 			selectee.startselected = false;
  13777 			that._trigger( "unselected", event, {
  13778 				unselected: selectee.element
  13779 			} );
  13780 		} );
  13781 		$( ".ui-selecting", this.element[ 0 ] ).each( function() {
  13782 			var selectee = $.data( this, "selectable-item" );
  13783 			that._removeClass( selectee.$element, "ui-selecting" )
  13784 				._addClass( selectee.$element, "ui-selected" );
  13785 			selectee.selecting = false;
  13786 			selectee.selected = true;
  13787 			selectee.startselected = true;
  13788 			that._trigger( "selected", event, {
  13789 				selected: selectee.element
  13790 			} );
  13791 		} );
  13792 		this._trigger( "stop", event );
  13793 
  13794 		this.helper.remove();
  13795 
  13796 		return false;
  13797 	}
  13798 
  13799 } );
  13800 
  13801 
  13802 /*!
  13803  * jQuery UI Selectmenu 1.12.1
  13804  * http://jqueryui.com
  13805  *
  13806  * Copyright jQuery Foundation and other contributors
  13807  * Released under the MIT license.
  13808  * http://jquery.org/license
  13809  */
  13810 
  13811 //>>label: Selectmenu
  13812 //>>group: Widgets
  13813 // jscs:disable maximumLineLength
  13814 //>>description: Duplicates and extends the functionality of a native HTML select element, allowing it to be customizable in behavior and appearance far beyond the limitations of a native select.
  13815 // jscs:enable maximumLineLength
  13816 //>>docs: http://api.jqueryui.com/selectmenu/
  13817 //>>demos: http://jqueryui.com/selectmenu/
  13818 //>>css.structure: ../../themes/base/core.css
  13819 //>>css.structure: ../../themes/base/selectmenu.css, ../../themes/base/button.css
  13820 //>>css.theme: ../../themes/base/theme.css
  13821 
  13822 
  13823 
  13824 var widgetsSelectmenu = $.widget( "ui.selectmenu", [ $.ui.formResetMixin, {
  13825 	version: "1.12.1",
  13826 	defaultElement: "<select>",
  13827 	options: {
  13828 		appendTo: null,
  13829 		classes: {
  13830 			"ui-selectmenu-button-open": "ui-corner-top",
  13831 			"ui-selectmenu-button-closed": "ui-corner-all"
  13832 		},
  13833 		disabled: null,
  13834 		icons: {
  13835 			button: "ui-icon-triangle-1-s"
  13836 		},
  13837 		position: {
  13838 			my: "left top",
  13839 			at: "left bottom",
  13840 			collision: "none"
  13841 		},
  13842 		width: false,
  13843 
  13844 		// Callbacks
  13845 		change: null,
  13846 		close: null,
  13847 		focus: null,
  13848 		open: null,
  13849 		select: null
  13850 	},
  13851 
  13852 	_create: function() {
  13853 		var selectmenuId = this.element.uniqueId().attr( "id" );
  13854 		this.ids = {
  13855 			element: selectmenuId,
  13856 			button: selectmenuId + "-button",
  13857 			menu: selectmenuId + "-menu"
  13858 		};
  13859 
  13860 		this._drawButton();
  13861 		this._drawMenu();
  13862 		this._bindFormResetHandler();
  13863 
  13864 		this._rendered = false;
  13865 		this.menuItems = $();
  13866 	},
  13867 
  13868 	_drawButton: function() {
  13869 		var icon,
  13870 			that = this,
  13871 			item = this._parseOption(
  13872 				this.element.find( "option:selected" ),
  13873 				this.element[ 0 ].selectedIndex
  13874 			);
  13875 
  13876 		// Associate existing label with the new button
  13877 		this.labels = this.element.labels().attr( "for", this.ids.button );
  13878 		this._on( this.labels, {
  13879 			click: function( event ) {
  13880 				this.button.focus();
  13881 				event.preventDefault();
  13882 			}
  13883 		} );
  13884 
  13885 		// Hide original select element
  13886 		this.element.hide();
  13887 
  13888 		// Create button
  13889 		this.button = $( "<span>", {
  13890 			tabindex: this.options.disabled ? -1 : 0,
  13891 			id: this.ids.button,
  13892 			role: "combobox",
  13893 			"aria-expanded": "false",
  13894 			"aria-autocomplete": "list",
  13895 			"aria-owns": this.ids.menu,
  13896 			"aria-haspopup": "true",
  13897 			title: this.element.attr( "title" )
  13898 		} )
  13899 			.insertAfter( this.element );
  13900 
  13901 		this._addClass( this.button, "ui-selectmenu-button ui-selectmenu-button-closed",
  13902 			"ui-button ui-widget" );
  13903 
  13904 		icon = $( "<span>" ).appendTo( this.button );
  13905 		this._addClass( icon, "ui-selectmenu-icon", "ui-icon " + this.options.icons.button );
  13906 		this.buttonItem = this._renderButtonItem( item )
  13907 			.appendTo( this.button );
  13908 
  13909 		if ( this.options.width !== false ) {
  13910 			this._resizeButton();
  13911 		}
  13912 
  13913 		this._on( this.button, this._buttonEvents );
  13914 		this.button.one( "focusin", function() {
  13915 
  13916 			// Delay rendering the menu items until the button receives focus.
  13917 			// The menu may have already been rendered via a programmatic open.
  13918 			if ( !that._rendered ) {
  13919 				that._refreshMenu();
  13920 			}
  13921 		} );
  13922 	},
  13923 
  13924 	_drawMenu: function() {
  13925 		var that = this;
  13926 
  13927 		// Create menu
  13928 		this.menu = $( "<ul>", {
  13929 			"aria-hidden": "true",
  13930 			"aria-labelledby": this.ids.button,
  13931 			id: this.ids.menu
  13932 		} );
  13933 
  13934 		// Wrap menu
  13935 		this.menuWrap = $( "<div>" ).append( this.menu );
  13936 		this._addClass( this.menuWrap, "ui-selectmenu-menu", "ui-front" );
  13937 		this.menuWrap.appendTo( this._appendTo() );
  13938 
  13939 		// Initialize menu widget
  13940 		this.menuInstance = this.menu
  13941 			.menu( {
  13942 				classes: {
  13943 					"ui-menu": "ui-corner-bottom"
  13944 				},
  13945 				role: "listbox",
  13946 				select: function( event, ui ) {
  13947 					event.preventDefault();
  13948 
  13949 					// Support: IE8
  13950 					// If the item was selected via a click, the text selection
  13951 					// will be destroyed in IE
  13952 					that._setSelection();
  13953 
  13954 					that._select( ui.item.data( "ui-selectmenu-item" ), event );
  13955 				},
  13956 				focus: function( event, ui ) {
  13957 					var item = ui.item.data( "ui-selectmenu-item" );
  13958 
  13959 					// Prevent inital focus from firing and check if its a newly focused item
  13960 					if ( that.focusIndex != null && item.index !== that.focusIndex ) {
  13961 						that._trigger( "focus", event, { item: item } );
  13962 						if ( !that.isOpen ) {
  13963 							that._select( item, event );
  13964 						}
  13965 					}
  13966 					that.focusIndex = item.index;
  13967 
  13968 					that.button.attr( "aria-activedescendant",
  13969 						that.menuItems.eq( item.index ).attr( "id" ) );
  13970 				}
  13971 			} )
  13972 			.menu( "instance" );
  13973 
  13974 		// Don't close the menu on mouseleave
  13975 		this.menuInstance._off( this.menu, "mouseleave" );
  13976 
  13977 		// Cancel the menu's collapseAll on document click
  13978 		this.menuInstance._closeOnDocumentClick = function() {
  13979 			return false;
  13980 		};
  13981 
  13982 		// Selects often contain empty items, but never contain dividers
  13983 		this.menuInstance._isDivider = function() {
  13984 			return false;
  13985 		};
  13986 	},
  13987 
  13988 	refresh: function() {
  13989 		this._refreshMenu();
  13990 		this.buttonItem.replaceWith(
  13991 			this.buttonItem = this._renderButtonItem(
  13992 
  13993 				// Fall back to an empty object in case there are no options
  13994 				this._getSelectedItem().data( "ui-selectmenu-item" ) || {}
  13995 			)
  13996 		);
  13997 		if ( this.options.width === null ) {
  13998 			this._resizeButton();
  13999 		}
  14000 	},
  14001 
  14002 	_refreshMenu: function() {
  14003 		var item,
  14004 			options = this.element.find( "option" );
  14005 
  14006 		this.menu.empty();
  14007 
  14008 		this._parseOptions( options );
  14009 		this._renderMenu( this.menu, this.items );
  14010 
  14011 		this.menuInstance.refresh();
  14012 		this.menuItems = this.menu.find( "li" )
  14013 			.not( ".ui-selectmenu-optgroup" )
  14014 				.find( ".ui-menu-item-wrapper" );
  14015 
  14016 		this._rendered = true;
  14017 
  14018 		if ( !options.length ) {
  14019 			return;
  14020 		}
  14021 
  14022 		item = this._getSelectedItem();
  14023 
  14024 		// Update the menu to have the correct item focused
  14025 		this.menuInstance.focus( null, item );
  14026 		this._setAria( item.data( "ui-selectmenu-item" ) );
  14027 
  14028 		// Set disabled state
  14029 		this._setOption( "disabled", this.element.prop( "disabled" ) );
  14030 	},
  14031 
  14032 	open: function( event ) {
  14033 		if ( this.options.disabled ) {
  14034 			return;
  14035 		}
  14036 
  14037 		// If this is the first time the menu is being opened, render the items
  14038 		if ( !this._rendered ) {
  14039 			this._refreshMenu();
  14040 		} else {
  14041 
  14042 			// Menu clears focus on close, reset focus to selected item
  14043 			this._removeClass( this.menu.find( ".ui-state-active" ), null, "ui-state-active" );
  14044 			this.menuInstance.focus( null, this._getSelectedItem() );
  14045 		}
  14046 
  14047 		// If there are no options, don't open the menu
  14048 		if ( !this.menuItems.length ) {
  14049 			return;
  14050 		}
  14051 
  14052 		this.isOpen = true;
  14053 		this._toggleAttr();
  14054 		this._resizeMenu();
  14055 		this._position();
  14056 
  14057 		this._on( this.document, this._documentClick );
  14058 
  14059 		this._trigger( "open", event );
  14060 	},
  14061 
  14062 	_position: function() {
  14063 		this.menuWrap.position( $.extend( { of: this.button }, this.options.position ) );
  14064 	},
  14065 
  14066 	close: function( event ) {
  14067 		if ( !this.isOpen ) {
  14068 			return;
  14069 		}
  14070 
  14071 		this.isOpen = false;
  14072 		this._toggleAttr();
  14073 
  14074 		this.range = null;
  14075 		this._off( this.document );
  14076 
  14077 		this._trigger( "close", event );
  14078 	},
  14079 
  14080 	widget: function() {
  14081 		return this.button;
  14082 	},
  14083 
  14084 	menuWidget: function() {
  14085 		return this.menu;
  14086 	},
  14087 
  14088 	_renderButtonItem: function( item ) {
  14089 		var buttonItem = $( "<span>" );
  14090 
  14091 		this._setText( buttonItem, item.label );
  14092 		this._addClass( buttonItem, "ui-selectmenu-text" );
  14093 
  14094 		return buttonItem;
  14095 	},
  14096 
  14097 	_renderMenu: function( ul, items ) {
  14098 		var that = this,
  14099 			currentOptgroup = "";
  14100 
  14101 		$.each( items, function( index, item ) {
  14102 			var li;
  14103 
  14104 			if ( item.optgroup !== currentOptgroup ) {
  14105 				li = $( "<li>", {
  14106 					text: item.optgroup
  14107 				} );
  14108 				that._addClass( li, "ui-selectmenu-optgroup", "ui-menu-divider" +
  14109 					( item.element.parent( "optgroup" ).prop( "disabled" ) ?
  14110 						" ui-state-disabled" :
  14111 						"" ) );
  14112 
  14113 				li.appendTo( ul );
  14114 
  14115 				currentOptgroup = item.optgroup;
  14116 			}
  14117 
  14118 			that._renderItemData( ul, item );
  14119 		} );
  14120 	},
  14121 
  14122 	_renderItemData: function( ul, item ) {
  14123 		return this._renderItem( ul, item ).data( "ui-selectmenu-item", item );
  14124 	},
  14125 
  14126 	_renderItem: function( ul, item ) {
  14127 		var li = $( "<li>" ),
  14128 			wrapper = $( "<div>", {
  14129 				title: item.element.attr( "title" )
  14130 			} );
  14131 
  14132 		if ( item.disabled ) {
  14133 			this._addClass( li, null, "ui-state-disabled" );
  14134 		}
  14135 		this._setText( wrapper, item.label );
  14136 
  14137 		return li.append( wrapper ).appendTo( ul );
  14138 	},
  14139 
  14140 	_setText: function( element, value ) {
  14141 		if ( value ) {
  14142 			element.text( value );
  14143 		} else {
  14144 			element.html( "&#160;" );
  14145 		}
  14146 	},
  14147 
  14148 	_move: function( direction, event ) {
  14149 		var item, next,
  14150 			filter = ".ui-menu-item";
  14151 
  14152 		if ( this.isOpen ) {
  14153 			item = this.menuItems.eq( this.focusIndex ).parent( "li" );
  14154 		} else {
  14155 			item = this.menuItems.eq( this.element[ 0 ].selectedIndex ).parent( "li" );
  14156 			filter += ":not(.ui-state-disabled)";
  14157 		}
  14158 
  14159 		if ( direction === "first" || direction === "last" ) {
  14160 			next = item[ direction === "first" ? "prevAll" : "nextAll" ]( filter ).eq( -1 );
  14161 		} else {
  14162 			next = item[ direction + "All" ]( filter ).eq( 0 );
  14163 		}
  14164 
  14165 		if ( next.length ) {
  14166 			this.menuInstance.focus( event, next );
  14167 		}
  14168 	},
  14169 
  14170 	_getSelectedItem: function() {
  14171 		return this.menuItems.eq( this.element[ 0 ].selectedIndex ).parent( "li" );
  14172 	},
  14173 
  14174 	_toggle: function( event ) {
  14175 		this[ this.isOpen ? "close" : "open" ]( event );
  14176 	},
  14177 
  14178 	_setSelection: function() {
  14179 		var selection;
  14180 
  14181 		if ( !this.range ) {
  14182 			return;
  14183 		}
  14184 
  14185 		if ( window.getSelection ) {
  14186 			selection = window.getSelection();
  14187 			selection.removeAllRanges();
  14188 			selection.addRange( this.range );
  14189 
  14190 		// Support: IE8
  14191 		} else {
  14192 			this.range.select();
  14193 		}
  14194 
  14195 		// Support: IE
  14196 		// Setting the text selection kills the button focus in IE, but
  14197 		// restoring the focus doesn't kill the selection.
  14198 		this.button.focus();
  14199 	},
  14200 
  14201 	_documentClick: {
  14202 		mousedown: function( event ) {
  14203 			if ( !this.isOpen ) {
  14204 				return;
  14205 			}
  14206 
  14207 			if ( !$( event.target ).closest( ".ui-selectmenu-menu, #" +
  14208 					$.ui.escapeSelector( this.ids.button ) ).length ) {
  14209 				this.close( event );
  14210 			}
  14211 		}
  14212 	},
  14213 
  14214 	_buttonEvents: {
  14215 
  14216 		// Prevent text selection from being reset when interacting with the selectmenu (#10144)
  14217 		mousedown: function() {
  14218 			var selection;
  14219 
  14220 			if ( window.getSelection ) {
  14221 				selection = window.getSelection();
  14222 				if ( selection.rangeCount ) {
  14223 					this.range = selection.getRangeAt( 0 );
  14224 				}
  14225 
  14226 			// Support: IE8
  14227 			} else {
  14228 				this.range = document.selection.createRange();
  14229 			}
  14230 		},
  14231 
  14232 		click: function( event ) {
  14233 			this._setSelection();
  14234 			this._toggle( event );
  14235 		},
  14236 
  14237 		keydown: function( event ) {
  14238 			var preventDefault = true;
  14239 			switch ( event.keyCode ) {
  14240 			case $.ui.keyCode.TAB:
  14241 			case $.ui.keyCode.ESCAPE:
  14242 				this.close( event );
  14243 				preventDefault = false;
  14244 				break;
  14245 			case $.ui.keyCode.ENTER:
  14246 				if ( this.isOpen ) {
  14247 					this._selectFocusedItem( event );
  14248 				}
  14249 				break;
  14250 			case $.ui.keyCode.UP:
  14251 				if ( event.altKey ) {
  14252 					this._toggle( event );
  14253 				} else {
  14254 					this._move( "prev", event );
  14255 				}
  14256 				break;
  14257 			case $.ui.keyCode.DOWN:
  14258 				if ( event.altKey ) {
  14259 					this._toggle( event );
  14260 				} else {
  14261 					this._move( "next", event );
  14262 				}
  14263 				break;
  14264 			case $.ui.keyCode.SPACE:
  14265 				if ( this.isOpen ) {
  14266 					this._selectFocusedItem( event );
  14267 				} else {
  14268 					this._toggle( event );
  14269 				}
  14270 				break;
  14271 			case $.ui.keyCode.LEFT:
  14272 				this._move( "prev", event );
  14273 				break;
  14274 			case $.ui.keyCode.RIGHT:
  14275 				this._move( "next", event );
  14276 				break;
  14277 			case $.ui.keyCode.HOME:
  14278 			case $.ui.keyCode.PAGE_UP:
  14279 				this._move( "first", event );
  14280 				break;
  14281 			case $.ui.keyCode.END:
  14282 			case $.ui.keyCode.PAGE_DOWN:
  14283 				this._move( "last", event );
  14284 				break;
  14285 			default:
  14286 				this.menu.trigger( event );
  14287 				preventDefault = false;
  14288 			}
  14289 
  14290 			if ( preventDefault ) {
  14291 				event.preventDefault();
  14292 			}
  14293 		}
  14294 	},
  14295 
  14296 	_selectFocusedItem: function( event ) {
  14297 		var item = this.menuItems.eq( this.focusIndex ).parent( "li" );
  14298 		if ( !item.hasClass( "ui-state-disabled" ) ) {
  14299 			this._select( item.data( "ui-selectmenu-item" ), event );
  14300 		}
  14301 	},
  14302 
  14303 	_select: function( item, event ) {
  14304 		var oldIndex = this.element[ 0 ].selectedIndex;
  14305 
  14306 		// Change native select element
  14307 		this.element[ 0 ].selectedIndex = item.index;
  14308 		this.buttonItem.replaceWith( this.buttonItem = this._renderButtonItem( item ) );
  14309 		this._setAria( item );
  14310 		this._trigger( "select", event, { item: item } );
  14311 
  14312 		if ( item.index !== oldIndex ) {
  14313 			this._trigger( "change", event, { item: item } );
  14314 		}
  14315 
  14316 		this.close( event );
  14317 	},
  14318 
  14319 	_setAria: function( item ) {
  14320 		var id = this.menuItems.eq( item.index ).attr( "id" );
  14321 
  14322 		this.button.attr( {
  14323 			"aria-labelledby": id,
  14324 			"aria-activedescendant": id
  14325 		} );
  14326 		this.menu.attr( "aria-activedescendant", id );
  14327 	},
  14328 
  14329 	_setOption: function( key, value ) {
  14330 		if ( key === "icons" ) {
  14331 			var icon = this.button.find( "span.ui-icon" );
  14332 			this._removeClass( icon, null, this.options.icons.button )
  14333 				._addClass( icon, null, value.button );
  14334 		}
  14335 
  14336 		this._super( key, value );
  14337 
  14338 		if ( key === "appendTo" ) {
  14339 			this.menuWrap.appendTo( this._appendTo() );
  14340 		}
  14341 
  14342 		if ( key === "width" ) {
  14343 			this._resizeButton();
  14344 		}
  14345 	},
  14346 
  14347 	_setOptionDisabled: function( value ) {
  14348 		this._super( value );
  14349 
  14350 		this.menuInstance.option( "disabled", value );
  14351 		this.button.attr( "aria-disabled", value );
  14352 		this._toggleClass( this.button, null, "ui-state-disabled", value );
  14353 
  14354 		this.element.prop( "disabled", value );
  14355 		if ( value ) {
  14356 			this.button.attr( "tabindex", -1 );
  14357 			this.close();
  14358 		} else {
  14359 			this.button.attr( "tabindex", 0 );
  14360 		}
  14361 	},
  14362 
  14363 	_appendTo: function() {
  14364 		var element = this.options.appendTo;
  14365 
  14366 		if ( element ) {
  14367 			element = element.jquery || element.nodeType ?
  14368 				$( element ) :
  14369 				this.document.find( element ).eq( 0 );
  14370 		}
  14371 
  14372 		if ( !element || !element[ 0 ] ) {
  14373 			element = this.element.closest( ".ui-front, dialog" );
  14374 		}
  14375 
  14376 		if ( !element.length ) {
  14377 			element = this.document[ 0 ].body;
  14378 		}
  14379 
  14380 		return element;
  14381 	},
  14382 
  14383 	_toggleAttr: function() {
  14384 		this.button.attr( "aria-expanded", this.isOpen );
  14385 
  14386 		// We can't use two _toggleClass() calls here, because we need to make sure
  14387 		// we always remove classes first and add them second, otherwise if both classes have the
  14388 		// same theme class, it will be removed after we add it.
  14389 		this._removeClass( this.button, "ui-selectmenu-button-" +
  14390 			( this.isOpen ? "closed" : "open" ) )
  14391 			._addClass( this.button, "ui-selectmenu-button-" +
  14392 				( this.isOpen ? "open" : "closed" ) )
  14393 			._toggleClass( this.menuWrap, "ui-selectmenu-open", null, this.isOpen );
  14394 
  14395 		this.menu.attr( "aria-hidden", !this.isOpen );
  14396 	},
  14397 
  14398 	_resizeButton: function() {
  14399 		var width = this.options.width;
  14400 
  14401 		// For `width: false`, just remove inline style and stop
  14402 		if ( width === false ) {
  14403 			this.button.css( "width", "" );
  14404 			return;
  14405 		}
  14406 
  14407 		// For `width: null`, match the width of the original element
  14408 		if ( width === null ) {
  14409 			width = this.element.show().outerWidth();
  14410 			this.element.hide();
  14411 		}
  14412 
  14413 		this.button.outerWidth( width );
  14414 	},
  14415 
  14416 	_resizeMenu: function() {
  14417 		this.menu.outerWidth( Math.max(
  14418 			this.button.outerWidth(),
  14419 
  14420 			// Support: IE10
  14421 			// IE10 wraps long text (possibly a rounding bug)
  14422 			// so we add 1px to avoid the wrapping
  14423 			this.menu.width( "" ).outerWidth() + 1
  14424 		) );
  14425 	},
  14426 
  14427 	_getCreateOptions: function() {
  14428 		var options = this._super();
  14429 
  14430 		options.disabled = this.element.prop( "disabled" );
  14431 
  14432 		return options;
  14433 	},
  14434 
  14435 	_parseOptions: function( options ) {
  14436 		var that = this,
  14437 			data = [];
  14438 		options.each( function( index, item ) {
  14439 			data.push( that._parseOption( $( item ), index ) );
  14440 		} );
  14441 		this.items = data;
  14442 	},
  14443 
  14444 	_parseOption: function( option, index ) {
  14445 		var optgroup = option.parent( "optgroup" );
  14446 
  14447 		return {
  14448 			element: option,
  14449 			index: index,
  14450 			value: option.val(),
  14451 			label: option.text(),
  14452 			optgroup: optgroup.attr( "label" ) || "",
  14453 			disabled: optgroup.prop( "disabled" ) || option.prop( "disabled" )
  14454 		};
  14455 	},
  14456 
  14457 	_destroy: function() {
  14458 		this._unbindFormResetHandler();
  14459 		this.menuWrap.remove();
  14460 		this.button.remove();
  14461 		this.element.show();
  14462 		this.element.removeUniqueId();
  14463 		this.labels.attr( "for", this.ids.element );
  14464 	}
  14465 } ] );
  14466 
  14467 
  14468 /*!
  14469  * jQuery UI Slider 1.12.1
  14470  * http://jqueryui.com
  14471  *
  14472  * Copyright jQuery Foundation and other contributors
  14473  * Released under the MIT license.
  14474  * http://jquery.org/license
  14475  */
  14476 
  14477 //>>label: Slider
  14478 //>>group: Widgets
  14479 //>>description: Displays a flexible slider with ranges and accessibility via keyboard.
  14480 //>>docs: http://api.jqueryui.com/slider/
  14481 //>>demos: http://jqueryui.com/slider/
  14482 //>>css.structure: ../../themes/base/core.css
  14483 //>>css.structure: ../../themes/base/slider.css
  14484 //>>css.theme: ../../themes/base/theme.css
  14485 
  14486 
  14487 
  14488 var widgetsSlider = $.widget( "ui.slider", $.ui.mouse, {
  14489 	version: "1.12.1",
  14490 	widgetEventPrefix: "slide",
  14491 
  14492 	options: {
  14493 		animate: false,
  14494 		classes: {
  14495 			"ui-slider": "ui-corner-all",
  14496 			"ui-slider-handle": "ui-corner-all",
  14497 
  14498 			// Note: ui-widget-header isn't the most fittingly semantic framework class for this
  14499 			// element, but worked best visually with a variety of themes
  14500 			"ui-slider-range": "ui-corner-all ui-widget-header"
  14501 		},
  14502 		distance: 0,
  14503 		max: 100,
  14504 		min: 0,
  14505 		orientation: "horizontal",
  14506 		range: false,
  14507 		step: 1,
  14508 		value: 0,
  14509 		values: null,
  14510 
  14511 		// Callbacks
  14512 		change: null,
  14513 		slide: null,
  14514 		start: null,
  14515 		stop: null
  14516 	},
  14517 
  14518 	// Number of pages in a slider
  14519 	// (how many times can you page up/down to go through the whole range)
  14520 	numPages: 5,
  14521 
  14522 	_create: function() {
  14523 		this._keySliding = false;
  14524 		this._mouseSliding = false;
  14525 		this._animateOff = true;
  14526 		this._handleIndex = null;
  14527 		this._detectOrientation();
  14528 		this._mouseInit();
  14529 		this._calculateNewMax();
  14530 
  14531 		this._addClass( "ui-slider ui-slider-" + this.orientation,
  14532 			"ui-widget ui-widget-content" );
  14533 
  14534 		this._refresh();
  14535 
  14536 		this._animateOff = false;
  14537 	},
  14538 
  14539 	_refresh: function() {
  14540 		this._createRange();
  14541 		this._createHandles();
  14542 		this._setupEvents();
  14543 		this._refreshValue();
  14544 	},
  14545 
  14546 	_createHandles: function() {
  14547 		var i, handleCount,
  14548 			options = this.options,
  14549 			existingHandles = this.element.find( ".ui-slider-handle" ),
  14550 			handle = "<span tabindex='0'></span>",
  14551 			handles = [];
  14552 
  14553 		handleCount = ( options.values && options.values.length ) || 1;
  14554 
  14555 		if ( existingHandles.length > handleCount ) {
  14556 			existingHandles.slice( handleCount ).remove();
  14557 			existingHandles = existingHandles.slice( 0, handleCount );
  14558 		}
  14559 
  14560 		for ( i = existingHandles.length; i < handleCount; i++ ) {
  14561 			handles.push( handle );
  14562 		}
  14563 
  14564 		this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) );
  14565 
  14566 		this._addClass( this.handles, "ui-slider-handle", "ui-state-default" );
  14567 
  14568 		this.handle = this.handles.eq( 0 );
  14569 
  14570 		this.handles.each( function( i ) {
  14571 			$( this )
  14572 				.data( "ui-slider-handle-index", i )
  14573 				.attr( "tabIndex", 0 );
  14574 		} );
  14575 	},
  14576 
  14577 	_createRange: function() {
  14578 		var options = this.options;
  14579 
  14580 		if ( options.range ) {
  14581 			if ( options.range === true ) {
  14582 				if ( !options.values ) {
  14583 					options.values = [ this._valueMin(), this._valueMin() ];
  14584 				} else if ( options.values.length && options.values.length !== 2 ) {
  14585 					options.values = [ options.values[ 0 ], options.values[ 0 ] ];
  14586 				} else if ( $.isArray( options.values ) ) {
  14587 					options.values = options.values.slice( 0 );
  14588 				}
  14589 			}
  14590 
  14591 			if ( !this.range || !this.range.length ) {
  14592 				this.range = $( "<div>" )
  14593 					.appendTo( this.element );
  14594 
  14595 				this._addClass( this.range, "ui-slider-range" );
  14596 			} else {
  14597 				this._removeClass( this.range, "ui-slider-range-min ui-slider-range-max" );
  14598 
  14599 				// Handle range switching from true to min/max
  14600 				this.range.css( {
  14601 					"left": "",
  14602 					"bottom": ""
  14603 				} );
  14604 			}
  14605 			if ( options.range === "min" || options.range === "max" ) {
  14606 				this._addClass( this.range, "ui-slider-range-" + options.range );
  14607 			}
  14608 		} else {
  14609 			if ( this.range ) {
  14610 				this.range.remove();
  14611 			}
  14612 			this.range = null;
  14613 		}
  14614 	},
  14615 
  14616 	_setupEvents: function() {
  14617 		this._off( this.handles );
  14618 		this._on( this.handles, this._handleEvents );
  14619 		this._hoverable( this.handles );
  14620 		this._focusable( this.handles );
  14621 	},
  14622 
  14623 	_destroy: function() {
  14624 		this.handles.remove();
  14625 		if ( this.range ) {
  14626 			this.range.remove();
  14627 		}
  14628 
  14629 		this._mouseDestroy();
  14630 	},
  14631 
  14632 	_mouseCapture: function( event ) {
  14633 		var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle,
  14634 			that = this,
  14635 			o = this.options;
  14636 
  14637 		if ( o.disabled ) {
  14638 			return false;
  14639 		}
  14640 
  14641 		this.elementSize = {
  14642 			width: this.element.outerWidth(),
  14643 			height: this.element.outerHeight()
  14644 		};
  14645 		this.elementOffset = this.element.offset();
  14646 
  14647 		position = { x: event.pageX, y: event.pageY };
  14648 		normValue = this._normValueFromMouse( position );
  14649 		distance = this._valueMax() - this._valueMin() + 1;
  14650 		this.handles.each( function( i ) {
  14651 			var thisDistance = Math.abs( normValue - that.values( i ) );
  14652 			if ( ( distance > thisDistance ) ||
  14653 				( distance === thisDistance &&
  14654 					( i === that._lastChangedValue || that.values( i ) === o.min ) ) ) {
  14655 				distance = thisDistance;
  14656 				closestHandle = $( this );
  14657 				index = i;
  14658 			}
  14659 		} );
  14660 
  14661 		allowed = this._start( event, index );
  14662 		if ( allowed === false ) {
  14663 			return false;
  14664 		}
  14665 		this._mouseSliding = true;
  14666 
  14667 		this._handleIndex = index;
  14668 
  14669 		this._addClass( closestHandle, null, "ui-state-active" );
  14670 		closestHandle.trigger( "focus" );
  14671 
  14672 		offset = closestHandle.offset();
  14673 		mouseOverHandle = !$( event.target ).parents().addBack().is( ".ui-slider-handle" );
  14674 		this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
  14675 			left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
  14676 			top: event.pageY - offset.top -
  14677 				( closestHandle.height() / 2 ) -
  14678 				( parseInt( closestHandle.css( "borderTopWidth" ), 10 ) || 0 ) -
  14679 				( parseInt( closestHandle.css( "borderBottomWidth" ), 10 ) || 0 ) +
  14680 				( parseInt( closestHandle.css( "marginTop" ), 10 ) || 0 )
  14681 		};
  14682 
  14683 		if ( !this.handles.hasClass( "ui-state-hover" ) ) {
  14684 			this._slide( event, index, normValue );
  14685 		}
  14686 		this._animateOff = true;
  14687 		return true;
  14688 	},
  14689 
  14690 	_mouseStart: function() {
  14691 		return true;
  14692 	},
  14693 
  14694 	_mouseDrag: function( event ) {
  14695 		var position = { x: event.pageX, y: event.pageY },
  14696 			normValue = this._normValueFromMouse( position );
  14697 
  14698 		this._slide( event, this._handleIndex, normValue );
  14699 
  14700 		return false;
  14701 	},
  14702 
  14703 	_mouseStop: function( event ) {
  14704 		this._removeClass( this.handles, null, "ui-state-active" );
  14705 		this._mouseSliding = false;
  14706 
  14707 		this._stop( event, this._handleIndex );
  14708 		this._change( event, this._handleIndex );
  14709 
  14710 		this._handleIndex = null;
  14711 		this._clickOffset = null;
  14712 		this._animateOff = false;
  14713 
  14714 		return false;
  14715 	},
  14716 
  14717 	_detectOrientation: function() {
  14718 		this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
  14719 	},
  14720 
  14721 	_normValueFromMouse: function( position ) {
  14722 		var pixelTotal,
  14723 			pixelMouse,
  14724 			percentMouse,
  14725 			valueTotal,
  14726 			valueMouse;
  14727 
  14728 		if ( this.orientation === "horizontal" ) {
  14729 			pixelTotal = this.elementSize.width;
  14730 			pixelMouse = position.x - this.elementOffset.left -
  14731 				( this._clickOffset ? this._clickOffset.left : 0 );
  14732 		} else {
  14733 			pixelTotal = this.elementSize.height;
  14734 			pixelMouse = position.y - this.elementOffset.top -
  14735 				( this._clickOffset ? this._clickOffset.top : 0 );
  14736 		}
  14737 
  14738 		percentMouse = ( pixelMouse / pixelTotal );
  14739 		if ( percentMouse > 1 ) {
  14740 			percentMouse = 1;
  14741 		}
  14742 		if ( percentMouse < 0 ) {
  14743 			percentMouse = 0;
  14744 		}
  14745 		if ( this.orientation === "vertical" ) {
  14746 			percentMouse = 1 - percentMouse;
  14747 		}
  14748 
  14749 		valueTotal = this._valueMax() - this._valueMin();
  14750 		valueMouse = this._valueMin() + percentMouse * valueTotal;
  14751 
  14752 		return this._trimAlignValue( valueMouse );
  14753 	},
  14754 
  14755 	_uiHash: function( index, value, values ) {
  14756 		var uiHash = {
  14757 			handle: this.handles[ index ],
  14758 			handleIndex: index,
  14759 			value: value !== undefined ? value : this.value()
  14760 		};
  14761 
  14762 		if ( this._hasMultipleValues() ) {
  14763 			uiHash.value = value !== undefined ? value : this.values( index );
  14764 			uiHash.values = values || this.values();
  14765 		}
  14766 
  14767 		return uiHash;
  14768 	},
  14769 
  14770 	_hasMultipleValues: function() {
  14771 		return this.options.values && this.options.values.length;
  14772 	},
  14773 
  14774 	_start: function( event, index ) {
  14775 		return this._trigger( "start", event, this._uiHash( index ) );
  14776 	},
  14777 
  14778 	_slide: function( event, index, newVal ) {
  14779 		var allowed, otherVal,
  14780 			currentValue = this.value(),
  14781 			newValues = this.values();
  14782 
  14783 		if ( this._hasMultipleValues() ) {
  14784 			otherVal = this.values( index ? 0 : 1 );
  14785 			currentValue = this.values( index );
  14786 
  14787 			if ( this.options.values.length === 2 && this.options.range === true ) {
  14788 				newVal =  index === 0 ? Math.min( otherVal, newVal ) : Math.max( otherVal, newVal );
  14789 			}
  14790 
  14791 			newValues[ index ] = newVal;
  14792 		}
  14793 
  14794 		if ( newVal === currentValue ) {
  14795 			return;
  14796 		}
  14797 
  14798 		allowed = this._trigger( "slide", event, this._uiHash( index, newVal, newValues ) );
  14799 
  14800 		// A slide can be canceled by returning false from the slide callback
  14801 		if ( allowed === false ) {
  14802 			return;
  14803 		}
  14804 
  14805 		if ( this._hasMultipleValues() ) {
  14806 			this.values( index, newVal );
  14807 		} else {
  14808 			this.value( newVal );
  14809 		}
  14810 	},
  14811 
  14812 	_stop: function( event, index ) {
  14813 		this._trigger( "stop", event, this._uiHash( index ) );
  14814 	},
  14815 
  14816 	_change: function( event, index ) {
  14817 		if ( !this._keySliding && !this._mouseSliding ) {
  14818 
  14819 			//store the last changed value index for reference when handles overlap
  14820 			this._lastChangedValue = index;
  14821 			this._trigger( "change", event, this._uiHash( index ) );
  14822 		}
  14823 	},
  14824 
  14825 	value: function( newValue ) {
  14826 		if ( arguments.length ) {
  14827 			this.options.value = this._trimAlignValue( newValue );
  14828 			this._refreshValue();
  14829 			this._change( null, 0 );
  14830 			return;
  14831 		}
  14832 
  14833 		return this._value();
  14834 	},
  14835 
  14836 	values: function( index, newValue ) {
  14837 		var vals,
  14838 			newValues,
  14839 			i;
  14840 
  14841 		if ( arguments.length > 1 ) {
  14842 			this.options.values[ index ] = this._trimAlignValue( newValue );
  14843 			this._refreshValue();
  14844 			this._change( null, index );
  14845 			return;
  14846 		}
  14847 
  14848 		if ( arguments.length ) {
  14849 			if ( $.isArray( arguments[ 0 ] ) ) {
  14850 				vals = this.options.values;
  14851 				newValues = arguments[ 0 ];
  14852 				for ( i = 0; i < vals.length; i += 1 ) {
  14853 					vals[ i ] = this._trimAlignValue( newValues[ i ] );
  14854 					this._change( null, i );
  14855 				}
  14856 				this._refreshValue();
  14857 			} else {
  14858 				if ( this._hasMultipleValues() ) {
  14859 					return this._values( index );
  14860 				} else {
  14861 					return this.value();
  14862 				}
  14863 			}
  14864 		} else {
  14865 			return this._values();
  14866 		}
  14867 	},
  14868 
  14869 	_setOption: function( key, value ) {
  14870 		var i,
  14871 			valsLength = 0;
  14872 
  14873 		if ( key === "range" && this.options.range === true ) {
  14874 			if ( value === "min" ) {
  14875 				this.options.value = this._values( 0 );
  14876 				this.options.values = null;
  14877 			} else if ( value === "max" ) {
  14878 				this.options.value = this._values( this.options.values.length - 1 );
  14879 				this.options.values = null;
  14880 			}
  14881 		}
  14882 
  14883 		if ( $.isArray( this.options.values ) ) {
  14884 			valsLength = this.options.values.length;
  14885 		}
  14886 
  14887 		this._super( key, value );
  14888 
  14889 		switch ( key ) {
  14890 			case "orientation":
  14891 				this._detectOrientation();
  14892 				this._removeClass( "ui-slider-horizontal ui-slider-vertical" )
  14893 					._addClass( "ui-slider-" + this.orientation );
  14894 				this._refreshValue();
  14895 				if ( this.options.range ) {
  14896 					this._refreshRange( value );
  14897 				}
  14898 
  14899 				// Reset positioning from previous orientation
  14900 				this.handles.css( value === "horizontal" ? "bottom" : "left", "" );
  14901 				break;
  14902 			case "value":
  14903 				this._animateOff = true;
  14904 				this._refreshValue();
  14905 				this._change( null, 0 );
  14906 				this._animateOff = false;
  14907 				break;
  14908 			case "values":
  14909 				this._animateOff = true;
  14910 				this._refreshValue();
  14911 
  14912 				// Start from the last handle to prevent unreachable handles (#9046)
  14913 				for ( i = valsLength - 1; i >= 0; i-- ) {
  14914 					this._change( null, i );
  14915 				}
  14916 				this._animateOff = false;
  14917 				break;
  14918 			case "step":
  14919 			case "min":
  14920 			case "max":
  14921 				this._animateOff = true;
  14922 				this._calculateNewMax();
  14923 				this._refreshValue();
  14924 				this._animateOff = false;
  14925 				break;
  14926 			case "range":
  14927 				this._animateOff = true;
  14928 				this._refresh();
  14929 				this._animateOff = false;
  14930 				break;
  14931 		}
  14932 	},
  14933 
  14934 	_setOptionDisabled: function( value ) {
  14935 		this._super( value );
  14936 
  14937 		this._toggleClass( null, "ui-state-disabled", !!value );
  14938 	},
  14939 
  14940 	//internal value getter
  14941 	// _value() returns value trimmed by min and max, aligned by step
  14942 	_value: function() {
  14943 		var val = this.options.value;
  14944 		val = this._trimAlignValue( val );
  14945 
  14946 		return val;
  14947 	},
  14948 
  14949 	//internal values getter
  14950 	// _values() returns array of values trimmed by min and max, aligned by step
  14951 	// _values( index ) returns single value trimmed by min and max, aligned by step
  14952 	_values: function( index ) {
  14953 		var val,
  14954 			vals,
  14955 			i;
  14956 
  14957 		if ( arguments.length ) {
  14958 			val = this.options.values[ index ];
  14959 			val = this._trimAlignValue( val );
  14960 
  14961 			return val;
  14962 		} else if ( this._hasMultipleValues() ) {
  14963 
  14964 			// .slice() creates a copy of the array
  14965 			// this copy gets trimmed by min and max and then returned
  14966 			vals = this.options.values.slice();
  14967 			for ( i = 0; i < vals.length; i += 1 ) {
  14968 				vals[ i ] = this._trimAlignValue( vals[ i ] );
  14969 			}
  14970 
  14971 			return vals;
  14972 		} else {
  14973 			return [];
  14974 		}
  14975 	},
  14976 
  14977 	// Returns the step-aligned value that val is closest to, between (inclusive) min and max
  14978 	_trimAlignValue: function( val ) {
  14979 		if ( val <= this._valueMin() ) {
  14980 			return this._valueMin();
  14981 		}
  14982 		if ( val >= this._valueMax() ) {
  14983 			return this._valueMax();
  14984 		}
  14985 		var step = ( this.options.step > 0 ) ? this.options.step : 1,
  14986 			valModStep = ( val - this._valueMin() ) % step,
  14987 			alignValue = val - valModStep;
  14988 
  14989 		if ( Math.abs( valModStep ) * 2 >= step ) {
  14990 			alignValue += ( valModStep > 0 ) ? step : ( -step );
  14991 		}
  14992 
  14993 		// Since JavaScript has problems with large floats, round
  14994 		// the final value to 5 digits after the decimal point (see #4124)
  14995 		return parseFloat( alignValue.toFixed( 5 ) );
  14996 	},
  14997 
  14998 	_calculateNewMax: function() {
  14999 		var max = this.options.max,
  15000 			min = this._valueMin(),
  15001 			step = this.options.step,
  15002 			aboveMin = Math.round( ( max - min ) / step ) * step;
  15003 		max = aboveMin + min;
  15004 		if ( max > this.options.max ) {
  15005 
  15006 			//If max is not divisible by step, rounding off may increase its value
  15007 			max -= step;
  15008 		}
  15009 		this.max = parseFloat( max.toFixed( this._precision() ) );
  15010 	},
  15011 
  15012 	_precision: function() {
  15013 		var precision = this._precisionOf( this.options.step );
  15014 		if ( this.options.min !== null ) {
  15015 			precision = Math.max( precision, this._precisionOf( this.options.min ) );
  15016 		}
  15017 		return precision;
  15018 	},
  15019 
  15020 	_precisionOf: function( num ) {
  15021 		var str = num.toString(),
  15022 			decimal = str.indexOf( "." );
  15023 		return decimal === -1 ? 0 : str.length - decimal - 1;
  15024 	},
  15025 
  15026 	_valueMin: function() {
  15027 		return this.options.min;
  15028 	},
  15029 
  15030 	_valueMax: function() {
  15031 		return this.max;
  15032 	},
  15033 
  15034 	_refreshRange: function( orientation ) {
  15035 		if ( orientation === "vertical" ) {
  15036 			this.range.css( { "width": "", "left": "" } );
  15037 		}
  15038 		if ( orientation === "horizontal" ) {
  15039 			this.range.css( { "height": "", "bottom": "" } );
  15040 		}
  15041 	},
  15042 
  15043 	_refreshValue: function() {
  15044 		var lastValPercent, valPercent, value, valueMin, valueMax,
  15045 			oRange = this.options.range,
  15046 			o = this.options,
  15047 			that = this,
  15048 			animate = ( !this._animateOff ) ? o.animate : false,
  15049 			_set = {};
  15050 
  15051 		if ( this._hasMultipleValues() ) {
  15052 			this.handles.each( function( i ) {
  15053 				valPercent = ( that.values( i ) - that._valueMin() ) / ( that._valueMax() -
  15054 					that._valueMin() ) * 100;
  15055 				_set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
  15056 				$( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
  15057 				if ( that.options.range === true ) {
  15058 					if ( that.orientation === "horizontal" ) {
  15059 						if ( i === 0 ) {
  15060 							that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
  15061 								left: valPercent + "%"
  15062 							}, o.animate );
  15063 						}
  15064 						if ( i === 1 ) {
  15065 							that.range[ animate ? "animate" : "css" ]( {
  15066 								width: ( valPercent - lastValPercent ) + "%"
  15067 							}, {
  15068 								queue: false,
  15069 								duration: o.animate
  15070 							} );
  15071 						}
  15072 					} else {
  15073 						if ( i === 0 ) {
  15074 							that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
  15075 								bottom: ( valPercent ) + "%"
  15076 							}, o.animate );
  15077 						}
  15078 						if ( i === 1 ) {
  15079 							that.range[ animate ? "animate" : "css" ]( {
  15080 								height: ( valPercent - lastValPercent ) + "%"
  15081 							}, {
  15082 								queue: false,
  15083 								duration: o.animate
  15084 							} );
  15085 						}
  15086 					}
  15087 				}
  15088 				lastValPercent = valPercent;
  15089 			} );
  15090 		} else {
  15091 			value = this.value();
  15092 			valueMin = this._valueMin();
  15093 			valueMax = this._valueMax();
  15094 			valPercent = ( valueMax !== valueMin ) ?
  15095 					( value - valueMin ) / ( valueMax - valueMin ) * 100 :
  15096 					0;
  15097 			_set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
  15098 			this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
  15099 
  15100 			if ( oRange === "min" && this.orientation === "horizontal" ) {
  15101 				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
  15102 					width: valPercent + "%"
  15103 				}, o.animate );
  15104 			}
  15105 			if ( oRange === "max" && this.orientation === "horizontal" ) {
  15106 				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
  15107 					width: ( 100 - valPercent ) + "%"
  15108 				}, o.animate );
  15109 			}
  15110 			if ( oRange === "min" && this.orientation === "vertical" ) {
  15111 				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
  15112 					height: valPercent + "%"
  15113 				}, o.animate );
  15114 			}
  15115 			if ( oRange === "max" && this.orientation === "vertical" ) {
  15116 				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
  15117 					height: ( 100 - valPercent ) + "%"
  15118 				}, o.animate );
  15119 			}
  15120 		}
  15121 	},
  15122 
  15123 	_handleEvents: {
  15124 		keydown: function( event ) {
  15125 			var allowed, curVal, newVal, step,
  15126 				index = $( event.target ).data( "ui-slider-handle-index" );
  15127 
  15128 			switch ( event.keyCode ) {
  15129 				case $.ui.keyCode.HOME:
  15130 				case $.ui.keyCode.END:
  15131 				case $.ui.keyCode.PAGE_UP:
  15132 				case $.ui.keyCode.PAGE_DOWN:
  15133 				case $.ui.keyCode.UP:
  15134 				case $.ui.keyCode.RIGHT:
  15135 				case $.ui.keyCode.DOWN:
  15136 				case $.ui.keyCode.LEFT:
  15137 					event.preventDefault();
  15138 					if ( !this._keySliding ) {
  15139 						this._keySliding = true;
  15140 						this._addClass( $( event.target ), null, "ui-state-active" );
  15141 						allowed = this._start( event, index );
  15142 						if ( allowed === false ) {
  15143 							return;
  15144 						}
  15145 					}
  15146 					break;
  15147 			}
  15148 
  15149 			step = this.options.step;
  15150 			if ( this._hasMultipleValues() ) {
  15151 				curVal = newVal = this.values( index );
  15152 			} else {
  15153 				curVal = newVal = this.value();
  15154 			}
  15155 
  15156 			switch ( event.keyCode ) {
  15157 				case $.ui.keyCode.HOME:
  15158 					newVal = this._valueMin();
  15159 					break;
  15160 				case $.ui.keyCode.END:
  15161 					newVal = this._valueMax();
  15162 					break;
  15163 				case $.ui.keyCode.PAGE_UP:
  15164 					newVal = this._trimAlignValue(
  15165 						curVal + ( ( this._valueMax() - this._valueMin() ) / this.numPages )
  15166 					);
  15167 					break;
  15168 				case $.ui.keyCode.PAGE_DOWN:
  15169 					newVal = this._trimAlignValue(
  15170 						curVal - ( ( this._valueMax() - this._valueMin() ) / this.numPages ) );
  15171 					break;
  15172 				case $.ui.keyCode.UP:
  15173 				case $.ui.keyCode.RIGHT:
  15174 					if ( curVal === this._valueMax() ) {
  15175 						return;
  15176 					}
  15177 					newVal = this._trimAlignValue( curVal + step );
  15178 					break;
  15179 				case $.ui.keyCode.DOWN:
  15180 				case $.ui.keyCode.LEFT:
  15181 					if ( curVal === this._valueMin() ) {
  15182 						return;
  15183 					}
  15184 					newVal = this._trimAlignValue( curVal - step );
  15185 					break;
  15186 			}
  15187 
  15188 			this._slide( event, index, newVal );
  15189 		},
  15190 		keyup: function( event ) {
  15191 			var index = $( event.target ).data( "ui-slider-handle-index" );
  15192 
  15193 			if ( this._keySliding ) {
  15194 				this._keySliding = false;
  15195 				this._stop( event, index );
  15196 				this._change( event, index );
  15197 				this._removeClass( $( event.target ), null, "ui-state-active" );
  15198 			}
  15199 		}
  15200 	}
  15201 } );
  15202 
  15203 
  15204 /*!
  15205  * jQuery UI Sortable 1.12.1
  15206  * http://jqueryui.com
  15207  *
  15208  * Copyright jQuery Foundation and other contributors
  15209  * Released under the MIT license.
  15210  * http://jquery.org/license
  15211  */
  15212 
  15213 //>>label: Sortable
  15214 //>>group: Interactions
  15215 //>>description: Enables items in a list to be sorted using the mouse.
  15216 //>>docs: http://api.jqueryui.com/sortable/
  15217 //>>demos: http://jqueryui.com/sortable/
  15218 //>>css.structure: ../../themes/base/sortable.css
  15219 
  15220 
  15221 
  15222 var widgetsSortable = $.widget( "ui.sortable", $.ui.mouse, {
  15223 	version: "1.12.1",
  15224 	widgetEventPrefix: "sort",
  15225 	ready: false,
  15226 	options: {
  15227 		appendTo: "parent",
  15228 		axis: false,
  15229 		connectWith: false,
  15230 		containment: false,
  15231 		cursor: "auto",
  15232 		cursorAt: false,
  15233 		dropOnEmpty: true,
  15234 		forcePlaceholderSize: false,
  15235 		forceHelperSize: false,
  15236 		grid: false,
  15237 		handle: false,
  15238 		helper: "original",
  15239 		items: "> *",
  15240 		opacity: false,
  15241 		placeholder: false,
  15242 		revert: false,
  15243 		scroll: true,
  15244 		scrollSensitivity: 20,
  15245 		scrollSpeed: 20,
  15246 		scope: "default",
  15247 		tolerance: "intersect",
  15248 		zIndex: 1000,
  15249 
  15250 		// Callbacks
  15251 		activate: null,
  15252 		beforeStop: null,
  15253 		change: null,
  15254 		deactivate: null,
  15255 		out: null,
  15256 		over: null,
  15257 		receive: null,
  15258 		remove: null,
  15259 		sort: null,
  15260 		start: null,
  15261 		stop: null,
  15262 		update: null
  15263 	},
  15264 
  15265 	_isOverAxis: function( x, reference, size ) {
  15266 		return ( x >= reference ) && ( x < ( reference + size ) );
  15267 	},
  15268 
  15269 	_isFloating: function( item ) {
  15270 		return ( /left|right/ ).test( item.css( "float" ) ) ||
  15271 			( /inline|table-cell/ ).test( item.css( "display" ) );
  15272 	},
  15273 
  15274 	_create: function() {
  15275 		this.containerCache = {};
  15276 		this._addClass( "ui-sortable" );
  15277 
  15278 		//Get the items
  15279 		this.refresh();
  15280 
  15281 		//Let's determine the parent's offset
  15282 		this.offset = this.element.offset();
  15283 
  15284 		//Initialize mouse events for interaction
  15285 		this._mouseInit();
  15286 
  15287 		this._setHandleClassName();
  15288 
  15289 		//We're ready to go
  15290 		this.ready = true;
  15291 
  15292 	},
  15293 
  15294 	_setOption: function( key, value ) {
  15295 		this._super( key, value );
  15296 
  15297 		if ( key === "handle" ) {
  15298 			this._setHandleClassName();
  15299 		}
  15300 	},
  15301 
  15302 	_setHandleClassName: function() {
  15303 		var that = this;
  15304 		this._removeClass( this.element.find( ".ui-sortable-handle" ), "ui-sortable-handle" );
  15305 		$.each( this.items, function() {
  15306 			that._addClass(
  15307 				this.instance.options.handle ?
  15308 					this.item.find( this.instance.options.handle ) :
  15309 					this.item,
  15310 				"ui-sortable-handle"
  15311 			);
  15312 		} );
  15313 	},
  15314 
  15315 	_destroy: function() {
  15316 		this._mouseDestroy();
  15317 
  15318 		for ( var i = this.items.length - 1; i >= 0; i-- ) {
  15319 			this.items[ i ].item.removeData( this.widgetName + "-item" );
  15320 		}
  15321 
  15322 		return this;
  15323 	},
  15324 
  15325 	_mouseCapture: function( event, overrideHandle ) {
  15326 		var currentItem = null,
  15327 			validHandle = false,
  15328 			that = this;
  15329 
  15330 		if ( this.reverting ) {
  15331 			return false;
  15332 		}
  15333 
  15334 		if ( this.options.disabled || this.options.type === "static" ) {
  15335 			return false;
  15336 		}
  15337 
  15338 		//We have to refresh the items data once first
  15339 		this._refreshItems( event );
  15340 
  15341 		//Find out if the clicked node (or one of its parents) is a actual item in this.items
  15342 		$( event.target ).parents().each( function() {
  15343 			if ( $.data( this, that.widgetName + "-item" ) === that ) {
  15344 				currentItem = $( this );
  15345 				return false;
  15346 			}
  15347 		} );
  15348 		if ( $.data( event.target, that.widgetName + "-item" ) === that ) {
  15349 			currentItem = $( event.target );
  15350 		}
  15351 
  15352 		if ( !currentItem ) {
  15353 			return false;
  15354 		}
  15355 		if ( this.options.handle && !overrideHandle ) {
  15356 			$( this.options.handle, currentItem ).find( "*" ).addBack().each( function() {
  15357 				if ( this === event.target ) {
  15358 					validHandle = true;
  15359 				}
  15360 			} );
  15361 			if ( !validHandle ) {
  15362 				return false;
  15363 			}
  15364 		}
  15365 
  15366 		this.currentItem = currentItem;
  15367 		this._removeCurrentsFromItems();
  15368 		return true;
  15369 
  15370 	},
  15371 
  15372 	_mouseStart: function( event, overrideHandle, noActivation ) {
  15373 
  15374 		var i, body,
  15375 			o = this.options;
  15376 
  15377 		this.currentContainer = this;
  15378 
  15379 		//We only need to call refreshPositions, because the refreshItems call has been moved to
  15380 		// mouseCapture
  15381 		this.refreshPositions();
  15382 
  15383 		//Create and append the visible helper
  15384 		this.helper = this._createHelper( event );
  15385 
  15386 		//Cache the helper size
  15387 		this._cacheHelperProportions();
  15388 
  15389 		/*
  15390 		 * - Position generation -
  15391 		 * This block generates everything position related - it's the core of draggables.
  15392 		 */
  15393 
  15394 		//Cache the margins of the original element
  15395 		this._cacheMargins();
  15396 
  15397 		//Get the next scrolling parent
  15398 		this.scrollParent = this.helper.scrollParent();
  15399 
  15400 		//The element's absolute position on the page minus margins
  15401 		this.offset = this.currentItem.offset();
  15402 		this.offset = {
  15403 			top: this.offset.top - this.margins.top,
  15404 			left: this.offset.left - this.margins.left
  15405 		};
  15406 
  15407 		$.extend( this.offset, {
  15408 			click: { //Where the click happened, relative to the element
  15409 				left: event.pageX - this.offset.left,
  15410 				top: event.pageY - this.offset.top
  15411 			},
  15412 			parent: this._getParentOffset(),
  15413 
  15414 			// This is a relative to absolute position minus the actual position calculation -
  15415 			// only used for relative positioned helper
  15416 			relative: this._getRelativeOffset()
  15417 		} );
  15418 
  15419 		// Only after we got the offset, we can change the helper's position to absolute
  15420 		// TODO: Still need to figure out a way to make relative sorting possible
  15421 		this.helper.css( "position", "absolute" );
  15422 		this.cssPosition = this.helper.css( "position" );
  15423 
  15424 		//Generate the original position
  15425 		this.originalPosition = this._generatePosition( event );
  15426 		this.originalPageX = event.pageX;
  15427 		this.originalPageY = event.pageY;
  15428 
  15429 		//Adjust the mouse offset relative to the helper if "cursorAt" is supplied
  15430 		( o.cursorAt && this._adjustOffsetFromHelper( o.cursorAt ) );
  15431 
  15432 		//Cache the former DOM position
  15433 		this.domPosition = {
  15434 			prev: this.currentItem.prev()[ 0 ],
  15435 			parent: this.currentItem.parent()[ 0 ]
  15436 		};
  15437 
  15438 		// If the helper is not the original, hide the original so it's not playing any role during
  15439 		// the drag, won't cause anything bad this way
  15440 		if ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) {
  15441 			this.currentItem.hide();
  15442 		}
  15443 
  15444 		//Create the placeholder
  15445 		this._createPlaceholder();
  15446 
  15447 		//Set a containment if given in the options
  15448 		if ( o.containment ) {
  15449 			this._setContainment();
  15450 		}
  15451 
  15452 		if ( o.cursor && o.cursor !== "auto" ) { // cursor option
  15453 			body = this.document.find( "body" );
  15454 
  15455 			// Support: IE
  15456 			this.storedCursor = body.css( "cursor" );
  15457 			body.css( "cursor", o.cursor );
  15458 
  15459 			this.storedStylesheet =
  15460 				$( "<style>*{ cursor: " + o.cursor + " !important; }</style>" ).appendTo( body );
  15461 		}
  15462 
  15463 		if ( o.opacity ) { // opacity option
  15464 			if ( this.helper.css( "opacity" ) ) {
  15465 				this._storedOpacity = this.helper.css( "opacity" );
  15466 			}
  15467 			this.helper.css( "opacity", o.opacity );
  15468 		}
  15469 
  15470 		if ( o.zIndex ) { // zIndex option
  15471 			if ( this.helper.css( "zIndex" ) ) {
  15472 				this._storedZIndex = this.helper.css( "zIndex" );
  15473 			}
  15474 			this.helper.css( "zIndex", o.zIndex );
  15475 		}
  15476 
  15477 		//Prepare scrolling
  15478 		if ( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
  15479 				this.scrollParent[ 0 ].tagName !== "HTML" ) {
  15480 			this.overflowOffset = this.scrollParent.offset();
  15481 		}
  15482 
  15483 		//Call callbacks
  15484 		this._trigger( "start", event, this._uiHash() );
  15485 
  15486 		//Recache the helper size
  15487 		if ( !this._preserveHelperProportions ) {
  15488 			this._cacheHelperProportions();
  15489 		}
  15490 
  15491 		//Post "activate" events to possible containers
  15492 		if ( !noActivation ) {
  15493 			for ( i = this.containers.length - 1; i >= 0; i-- ) {
  15494 				this.containers[ i ]._trigger( "activate", event, this._uiHash( this ) );
  15495 			}
  15496 		}
  15497 
  15498 		//Prepare possible droppables
  15499 		if ( $.ui.ddmanager ) {
  15500 			$.ui.ddmanager.current = this;
  15501 		}
  15502 
  15503 		if ( $.ui.ddmanager && !o.dropBehaviour ) {
  15504 			$.ui.ddmanager.prepareOffsets( this, event );
  15505 		}
  15506 
  15507 		this.dragging = true;
  15508 
  15509 		this._addClass( this.helper, "ui-sortable-helper" );
  15510 
  15511 		// Execute the drag once - this causes the helper not to be visiblebefore getting its
  15512 		// correct position
  15513 		this._mouseDrag( event );
  15514 		return true;
  15515 
  15516 	},
  15517 
  15518 	_mouseDrag: function( event ) {
  15519 		var i, item, itemElement, intersection,
  15520 			o = this.options,
  15521 			scrolled = false;
  15522 
  15523 		//Compute the helpers position
  15524 		this.position = this._generatePosition( event );
  15525 		this.positionAbs = this._convertPositionTo( "absolute" );
  15526 
  15527 		if ( !this.lastPositionAbs ) {
  15528 			this.lastPositionAbs = this.positionAbs;
  15529 		}
  15530 
  15531 		//Do scrolling
  15532 		if ( this.options.scroll ) {
  15533 			if ( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
  15534 					this.scrollParent[ 0 ].tagName !== "HTML" ) {
  15535 
  15536 				if ( ( this.overflowOffset.top + this.scrollParent[ 0 ].offsetHeight ) -
  15537 						event.pageY < o.scrollSensitivity ) {
  15538 					this.scrollParent[ 0 ].scrollTop =
  15539 						scrolled = this.scrollParent[ 0 ].scrollTop + o.scrollSpeed;
  15540 				} else if ( event.pageY - this.overflowOffset.top < o.scrollSensitivity ) {
  15541 					this.scrollParent[ 0 ].scrollTop =
  15542 						scrolled = this.scrollParent[ 0 ].scrollTop - o.scrollSpeed;
  15543 				}
  15544 
  15545 				if ( ( this.overflowOffset.left + this.scrollParent[ 0 ].offsetWidth ) -
  15546 						event.pageX < o.scrollSensitivity ) {
  15547 					this.scrollParent[ 0 ].scrollLeft = scrolled =
  15548 						this.scrollParent[ 0 ].scrollLeft + o.scrollSpeed;
  15549 				} else if ( event.pageX - this.overflowOffset.left < o.scrollSensitivity ) {
  15550 					this.scrollParent[ 0 ].scrollLeft = scrolled =
  15551 						this.scrollParent[ 0 ].scrollLeft - o.scrollSpeed;
  15552 				}
  15553 
  15554 			} else {
  15555 
  15556 				if ( event.pageY - this.document.scrollTop() < o.scrollSensitivity ) {
  15557 					scrolled = this.document.scrollTop( this.document.scrollTop() - o.scrollSpeed );
  15558 				} else if ( this.window.height() - ( event.pageY - this.document.scrollTop() ) <
  15559 						o.scrollSensitivity ) {
  15560 					scrolled = this.document.scrollTop( this.document.scrollTop() + o.scrollSpeed );
  15561 				}
  15562 
  15563 				if ( event.pageX - this.document.scrollLeft() < o.scrollSensitivity ) {
  15564 					scrolled = this.document.scrollLeft(
  15565 						this.document.scrollLeft() - o.scrollSpeed
  15566 					);
  15567 				} else if ( this.window.width() - ( event.pageX - this.document.scrollLeft() ) <
  15568 						o.scrollSensitivity ) {
  15569 					scrolled = this.document.scrollLeft(
  15570 						this.document.scrollLeft() + o.scrollSpeed
  15571 					);
  15572 				}
  15573 
  15574 			}
  15575 
  15576 			if ( scrolled !== false && $.ui.ddmanager && !o.dropBehaviour ) {
  15577 				$.ui.ddmanager.prepareOffsets( this, event );
  15578 			}
  15579 		}
  15580 
  15581 		//Regenerate the absolute position used for position checks
  15582 		this.positionAbs = this._convertPositionTo( "absolute" );
  15583 
  15584 		//Set the helper position
  15585 		if ( !this.options.axis || this.options.axis !== "y" ) {
  15586 			this.helper[ 0 ].style.left = this.position.left + "px";
  15587 		}
  15588 		if ( !this.options.axis || this.options.axis !== "x" ) {
  15589 			this.helper[ 0 ].style.top = this.position.top + "px";
  15590 		}
  15591 
  15592 		//Rearrange
  15593 		for ( i = this.items.length - 1; i >= 0; i-- ) {
  15594 
  15595 			//Cache variables and intersection, continue if no intersection
  15596 			item = this.items[ i ];
  15597 			itemElement = item.item[ 0 ];
  15598 			intersection = this._intersectsWithPointer( item );
  15599 			if ( !intersection ) {
  15600 				continue;
  15601 			}
  15602 
  15603 			// Only put the placeholder inside the current Container, skip all
  15604 			// items from other containers. This works because when moving
  15605 			// an item from one container to another the
  15606 			// currentContainer is switched before the placeholder is moved.
  15607 			//
  15608 			// Without this, moving items in "sub-sortables" can cause
  15609 			// the placeholder to jitter between the outer and inner container.
  15610 			if ( item.instance !== this.currentContainer ) {
  15611 				continue;
  15612 			}
  15613 
  15614 			// Cannot intersect with itself
  15615 			// no useless actions that have been done before
  15616 			// no action if the item moved is the parent of the item checked
  15617 			if ( itemElement !== this.currentItem[ 0 ] &&
  15618 				this.placeholder[ intersection === 1 ? "next" : "prev" ]()[ 0 ] !== itemElement &&
  15619 				!$.contains( this.placeholder[ 0 ], itemElement ) &&
  15620 				( this.options.type === "semi-dynamic" ?
  15621 					!$.contains( this.element[ 0 ], itemElement ) :
  15622 					true
  15623 				)
  15624 			) {
  15625 
  15626 				this.direction = intersection === 1 ? "down" : "up";
  15627 
  15628 				if ( this.options.tolerance === "pointer" || this._intersectsWithSides( item ) ) {
  15629 					this._rearrange( event, item );
  15630 				} else {
  15631 					break;
  15632 				}
  15633 
  15634 				this._trigger( "change", event, this._uiHash() );
  15635 				break;
  15636 			}
  15637 		}
  15638 
  15639 		//Post events to containers
  15640 		this._contactContainers( event );
  15641 
  15642 		//Interconnect with droppables
  15643 		if ( $.ui.ddmanager ) {
  15644 			$.ui.ddmanager.drag( this, event );
  15645 		}
  15646 
  15647 		//Call callbacks
  15648 		this._trigger( "sort", event, this._uiHash() );
  15649 
  15650 		this.lastPositionAbs = this.positionAbs;
  15651 		return false;
  15652 
  15653 	},
  15654 
  15655 	_mouseStop: function( event, noPropagation ) {
  15656 
  15657 		if ( !event ) {
  15658 			return;
  15659 		}
  15660 
  15661 		//If we are using droppables, inform the manager about the drop
  15662 		if ( $.ui.ddmanager && !this.options.dropBehaviour ) {
  15663 			$.ui.ddmanager.drop( this, event );
  15664 		}
  15665 
  15666 		if ( this.options.revert ) {
  15667 			var that = this,
  15668 				cur = this.placeholder.offset(),
  15669 				axis = this.options.axis,
  15670 				animation = {};
  15671 
  15672 			if ( !axis || axis === "x" ) {
  15673 				animation.left = cur.left - this.offset.parent.left - this.margins.left +
  15674 					( this.offsetParent[ 0 ] === this.document[ 0 ].body ?
  15675 						0 :
  15676 						this.offsetParent[ 0 ].scrollLeft
  15677 					);
  15678 			}
  15679 			if ( !axis || axis === "y" ) {
  15680 				animation.top = cur.top - this.offset.parent.top - this.margins.top +
  15681 					( this.offsetParent[ 0 ] === this.document[ 0 ].body ?
  15682 						0 :
  15683 						this.offsetParent[ 0 ].scrollTop
  15684 					);
  15685 			}
  15686 			this.reverting = true;
  15687 			$( this.helper ).animate(
  15688 				animation,
  15689 				parseInt( this.options.revert, 10 ) || 500,
  15690 				function() {
  15691 					that._clear( event );
  15692 				}
  15693 			);
  15694 		} else {
  15695 			this._clear( event, noPropagation );
  15696 		}
  15697 
  15698 		return false;
  15699 
  15700 	},
  15701 
  15702 	cancel: function() {
  15703 
  15704 		if ( this.dragging ) {
  15705 
  15706 			this._mouseUp( new $.Event( "mouseup", { target: null } ) );
  15707 
  15708 			if ( this.options.helper === "original" ) {
  15709 				this.currentItem.css( this._storedCSS );
  15710 				this._removeClass( this.currentItem, "ui-sortable-helper" );
  15711 			} else {
  15712 				this.currentItem.show();
  15713 			}
  15714 
  15715 			//Post deactivating events to containers
  15716 			for ( var i = this.containers.length - 1; i >= 0; i-- ) {
  15717 				this.containers[ i ]._trigger( "deactivate", null, this._uiHash( this ) );
  15718 				if ( this.containers[ i ].containerCache.over ) {
  15719 					this.containers[ i ]._trigger( "out", null, this._uiHash( this ) );
  15720 					this.containers[ i ].containerCache.over = 0;
  15721 				}
  15722 			}
  15723 
  15724 		}
  15725 
  15726 		if ( this.placeholder ) {
  15727 
  15728 			//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately,
  15729 			// it unbinds ALL events from the original node!
  15730 			if ( this.placeholder[ 0 ].parentNode ) {
  15731 				this.placeholder[ 0 ].parentNode.removeChild( this.placeholder[ 0 ] );
  15732 			}
  15733 			if ( this.options.helper !== "original" && this.helper &&
  15734 					this.helper[ 0 ].parentNode ) {
  15735 				this.helper.remove();
  15736 			}
  15737 
  15738 			$.extend( this, {
  15739 				helper: null,
  15740 				dragging: false,
  15741 				reverting: false,
  15742 				_noFinalSort: null
  15743 			} );
  15744 
  15745 			if ( this.domPosition.prev ) {
  15746 				$( this.domPosition.prev ).after( this.currentItem );
  15747 			} else {
  15748 				$( this.domPosition.parent ).prepend( this.currentItem );
  15749 			}
  15750 		}
  15751 
  15752 		return this;
  15753 
  15754 	},
  15755 
  15756 	serialize: function( o ) {
  15757 
  15758 		var items = this._getItemsAsjQuery( o && o.connected ),
  15759 			str = [];
  15760 		o = o || {};
  15761 
  15762 		$( items ).each( function() {
  15763 			var res = ( $( o.item || this ).attr( o.attribute || "id" ) || "" )
  15764 				.match( o.expression || ( /(.+)[\-=_](.+)/ ) );
  15765 			if ( res ) {
  15766 				str.push(
  15767 					( o.key || res[ 1 ] + "[]" ) +
  15768 					"=" + ( o.key && o.expression ? res[ 1 ] : res[ 2 ] ) );
  15769 			}
  15770 		} );
  15771 
  15772 		if ( !str.length && o.key ) {
  15773 			str.push( o.key + "=" );
  15774 		}
  15775 
  15776 		return str.join( "&" );
  15777 
  15778 	},
  15779 
  15780 	toArray: function( o ) {
  15781 
  15782 		var items = this._getItemsAsjQuery( o && o.connected ),
  15783 			ret = [];
  15784 
  15785 		o = o || {};
  15786 
  15787 		items.each( function() {
  15788 			ret.push( $( o.item || this ).attr( o.attribute || "id" ) || "" );
  15789 		} );
  15790 		return ret;
  15791 
  15792 	},
  15793 
  15794 	/* Be careful with the following core functions */
  15795 	_intersectsWith: function( item ) {
  15796 
  15797 		var x1 = this.positionAbs.left,
  15798 			x2 = x1 + this.helperProportions.width,
  15799 			y1 = this.positionAbs.top,
  15800 			y2 = y1 + this.helperProportions.height,
  15801 			l = item.left,
  15802 			r = l + item.width,
  15803 			t = item.top,
  15804 			b = t + item.height,
  15805 			dyClick = this.offset.click.top,
  15806 			dxClick = this.offset.click.left,
  15807 			isOverElementHeight = ( this.options.axis === "x" ) || ( ( y1 + dyClick ) > t &&
  15808 				( y1 + dyClick ) < b ),
  15809 			isOverElementWidth = ( this.options.axis === "y" ) || ( ( x1 + dxClick ) > l &&
  15810 				( x1 + dxClick ) < r ),
  15811 			isOverElement = isOverElementHeight && isOverElementWidth;
  15812 
  15813 		if ( this.options.tolerance === "pointer" ||
  15814 			this.options.forcePointerForContainers ||
  15815 			( this.options.tolerance !== "pointer" &&
  15816 				this.helperProportions[ this.floating ? "width" : "height" ] >
  15817 				item[ this.floating ? "width" : "height" ] )
  15818 		) {
  15819 			return isOverElement;
  15820 		} else {
  15821 
  15822 			return ( l < x1 + ( this.helperProportions.width / 2 ) && // Right Half
  15823 				x2 - ( this.helperProportions.width / 2 ) < r && // Left Half
  15824 				t < y1 + ( this.helperProportions.height / 2 ) && // Bottom Half
  15825 				y2 - ( this.helperProportions.height / 2 ) < b ); // Top Half
  15826 
  15827 		}
  15828 	},
  15829 
  15830 	_intersectsWithPointer: function( item ) {
  15831 		var verticalDirection, horizontalDirection,
  15832 			isOverElementHeight = ( this.options.axis === "x" ) ||
  15833 				this._isOverAxis(
  15834 					this.positionAbs.top + this.offset.click.top, item.top, item.height ),
  15835 			isOverElementWidth = ( this.options.axis === "y" ) ||
  15836 				this._isOverAxis(
  15837 					this.positionAbs.left + this.offset.click.left, item.left, item.width ),
  15838 			isOverElement = isOverElementHeight && isOverElementWidth;
  15839 
  15840 		if ( !isOverElement ) {
  15841 			return false;
  15842 		}
  15843 
  15844 		verticalDirection = this._getDragVerticalDirection();
  15845 		horizontalDirection = this._getDragHorizontalDirection();
  15846 
  15847 		return this.floating ?
  15848 			( ( horizontalDirection === "right" || verticalDirection === "down" ) ? 2 : 1 )
  15849 			: ( verticalDirection && ( verticalDirection === "down" ? 2 : 1 ) );
  15850 
  15851 	},
  15852 
  15853 	_intersectsWithSides: function( item ) {
  15854 
  15855 		var isOverBottomHalf = this._isOverAxis( this.positionAbs.top +
  15856 				this.offset.click.top, item.top + ( item.height / 2 ), item.height ),
  15857 			isOverRightHalf = this._isOverAxis( this.positionAbs.left +
  15858 				this.offset.click.left, item.left + ( item.width / 2 ), item.width ),
  15859 			verticalDirection = this._getDragVerticalDirection(),
  15860 			horizontalDirection = this._getDragHorizontalDirection();
  15861 
  15862 		if ( this.floating && horizontalDirection ) {
  15863 			return ( ( horizontalDirection === "right" && isOverRightHalf ) ||
  15864 				( horizontalDirection === "left" && !isOverRightHalf ) );
  15865 		} else {
  15866 			return verticalDirection && ( ( verticalDirection === "down" && isOverBottomHalf ) ||
  15867 				( verticalDirection === "up" && !isOverBottomHalf ) );
  15868 		}
  15869 
  15870 	},
  15871 
  15872 	_getDragVerticalDirection: function() {
  15873 		var delta = this.positionAbs.top - this.lastPositionAbs.top;
  15874 		return delta !== 0 && ( delta > 0 ? "down" : "up" );
  15875 	},
  15876 
  15877 	_getDragHorizontalDirection: function() {
  15878 		var delta = this.positionAbs.left - this.lastPositionAbs.left;
  15879 		return delta !== 0 && ( delta > 0 ? "right" : "left" );
  15880 	},
  15881 
  15882 	refresh: function( event ) {
  15883 		this._refreshItems( event );
  15884 		this._setHandleClassName();
  15885 		this.refreshPositions();
  15886 		return this;
  15887 	},
  15888 
  15889 	_connectWith: function() {
  15890 		var options = this.options;
  15891 		return options.connectWith.constructor === String ?
  15892 			[ options.connectWith ] :
  15893 			options.connectWith;
  15894 	},
  15895 
  15896 	_getItemsAsjQuery: function( connected ) {
  15897 
  15898 		var i, j, cur, inst,
  15899 			items = [],
  15900 			queries = [],
  15901 			connectWith = this._connectWith();
  15902 
  15903 		if ( connectWith && connected ) {
  15904 			for ( i = connectWith.length - 1; i >= 0; i-- ) {
  15905 				cur = $( connectWith[ i ], this.document[ 0 ] );
  15906 				for ( j = cur.length - 1; j >= 0; j-- ) {
  15907 					inst = $.data( cur[ j ], this.widgetFullName );
  15908 					if ( inst && inst !== this && !inst.options.disabled ) {
  15909 						queries.push( [ $.isFunction( inst.options.items ) ?
  15910 							inst.options.items.call( inst.element ) :
  15911 							$( inst.options.items, inst.element )
  15912 								.not( ".ui-sortable-helper" )
  15913 								.not( ".ui-sortable-placeholder" ), inst ] );
  15914 					}
  15915 				}
  15916 			}
  15917 		}
  15918 
  15919 		queries.push( [ $.isFunction( this.options.items ) ?
  15920 			this.options.items
  15921 				.call( this.element, null, { options: this.options, item: this.currentItem } ) :
  15922 			$( this.options.items, this.element )
  15923 				.not( ".ui-sortable-helper" )
  15924 				.not( ".ui-sortable-placeholder" ), this ] );
  15925 
  15926 		function addItems() {
  15927 			items.push( this );
  15928 		}
  15929 		for ( i = queries.length - 1; i >= 0; i-- ) {
  15930 			queries[ i ][ 0 ].each( addItems );
  15931 		}
  15932 
  15933 		return $( items );
  15934 
  15935 	},
  15936 
  15937 	_removeCurrentsFromItems: function() {
  15938 
  15939 		var list = this.currentItem.find( ":data(" + this.widgetName + "-item)" );
  15940 
  15941 		this.items = $.grep( this.items, function( item ) {
  15942 			for ( var j = 0; j < list.length; j++ ) {
  15943 				if ( list[ j ] === item.item[ 0 ] ) {
  15944 					return false;
  15945 				}
  15946 			}
  15947 			return true;
  15948 		} );
  15949 
  15950 	},
  15951 
  15952 	_refreshItems: function( event ) {
  15953 
  15954 		this.items = [];
  15955 		this.containers = [ this ];
  15956 
  15957 		var i, j, cur, inst, targetData, _queries, item, queriesLength,
  15958 			items = this.items,
  15959 			queries = [ [ $.isFunction( this.options.items ) ?
  15960 				this.options.items.call( this.element[ 0 ], event, { item: this.currentItem } ) :
  15961 				$( this.options.items, this.element ), this ] ],
  15962 			connectWith = this._connectWith();
  15963 
  15964 		//Shouldn't be run the first time through due to massive slow-down
  15965 		if ( connectWith && this.ready ) {
  15966 			for ( i = connectWith.length - 1; i >= 0; i-- ) {
  15967 				cur = $( connectWith[ i ], this.document[ 0 ] );
  15968 				for ( j = cur.length - 1; j >= 0; j-- ) {
  15969 					inst = $.data( cur[ j ], this.widgetFullName );
  15970 					if ( inst && inst !== this && !inst.options.disabled ) {
  15971 						queries.push( [ $.isFunction( inst.options.items ) ?
  15972 							inst.options.items
  15973 								.call( inst.element[ 0 ], event, { item: this.currentItem } ) :
  15974 							$( inst.options.items, inst.element ), inst ] );
  15975 						this.containers.push( inst );
  15976 					}
  15977 				}
  15978 			}
  15979 		}
  15980 
  15981 		for ( i = queries.length - 1; i >= 0; i-- ) {
  15982 			targetData = queries[ i ][ 1 ];
  15983 			_queries = queries[ i ][ 0 ];
  15984 
  15985 			for ( j = 0, queriesLength = _queries.length; j < queriesLength; j++ ) {
  15986 				item = $( _queries[ j ] );
  15987 
  15988 				// Data for target checking (mouse manager)
  15989 				item.data( this.widgetName + "-item", targetData );
  15990 
  15991 				items.push( {
  15992 					item: item,
  15993 					instance: targetData,
  15994 					width: 0, height: 0,
  15995 					left: 0, top: 0
  15996 				} );
  15997 			}
  15998 		}
  15999 
  16000 	},
  16001 
  16002 	refreshPositions: function( fast ) {
  16003 
  16004 		// Determine whether items are being displayed horizontally
  16005 		this.floating = this.items.length ?
  16006 			this.options.axis === "x" || this._isFloating( this.items[ 0 ].item ) :
  16007 			false;
  16008 
  16009 		//This has to be redone because due to the item being moved out/into the offsetParent,
  16010 		// the offsetParent's position will change
  16011 		if ( this.offsetParent && this.helper ) {
  16012 			this.offset.parent = this._getParentOffset();
  16013 		}
  16014 
  16015 		var i, item, t, p;
  16016 
  16017 		for ( i = this.items.length - 1; i >= 0; i-- ) {
  16018 			item = this.items[ i ];
  16019 
  16020 			//We ignore calculating positions of all connected containers when we're not over them
  16021 			if ( item.instance !== this.currentContainer && this.currentContainer &&
  16022 					item.item[ 0 ] !== this.currentItem[ 0 ] ) {
  16023 				continue;
  16024 			}
  16025 
  16026 			t = this.options.toleranceElement ?
  16027 				$( this.options.toleranceElement, item.item ) :
  16028 				item.item;
  16029 
  16030 			if ( !fast ) {
  16031 				item.width = t.outerWidth();
  16032 				item.height = t.outerHeight();
  16033 			}
  16034 
  16035 			p = t.offset();
  16036 			item.left = p.left;
  16037 			item.top = p.top;
  16038 		}
  16039 
  16040 		if ( this.options.custom && this.options.custom.refreshContainers ) {
  16041 			this.options.custom.refreshContainers.call( this );
  16042 		} else {
  16043 			for ( i = this.containers.length - 1; i >= 0; i-- ) {
  16044 				p = this.containers[ i ].element.offset();
  16045 				this.containers[ i ].containerCache.left = p.left;
  16046 				this.containers[ i ].containerCache.top = p.top;
  16047 				this.containers[ i ].containerCache.width =
  16048 					this.containers[ i ].element.outerWidth();
  16049 				this.containers[ i ].containerCache.height =
  16050 					this.containers[ i ].element.outerHeight();
  16051 			}
  16052 		}
  16053 
  16054 		return this;
  16055 	},
  16056 
  16057 	_createPlaceholder: function( that ) {
  16058 		that = that || this;
  16059 		var className,
  16060 			o = that.options;
  16061 
  16062 		if ( !o.placeholder || o.placeholder.constructor === String ) {
  16063 			className = o.placeholder;
  16064 			o.placeholder = {
  16065 				element: function() {
  16066 
  16067 					var nodeName = that.currentItem[ 0 ].nodeName.toLowerCase(),
  16068 						element = $( "<" + nodeName + ">", that.document[ 0 ] );
  16069 
  16070 						that._addClass( element, "ui-sortable-placeholder",
  16071 								className || that.currentItem[ 0 ].className )
  16072 							._removeClass( element, "ui-sortable-helper" );
  16073 
  16074 					if ( nodeName === "tbody" ) {
  16075 						that._createTrPlaceholder(
  16076 							that.currentItem.find( "tr" ).eq( 0 ),
  16077 							$( "<tr>", that.document[ 0 ] ).appendTo( element )
  16078 						);
  16079 					} else if ( nodeName === "tr" ) {
  16080 						that._createTrPlaceholder( that.currentItem, element );
  16081 					} else if ( nodeName === "img" ) {
  16082 						element.attr( "src", that.currentItem.attr( "src" ) );
  16083 					}
  16084 
  16085 					if ( !className ) {
  16086 						element.css( "visibility", "hidden" );
  16087 					}
  16088 
  16089 					return element;
  16090 				},
  16091 				update: function( container, p ) {
  16092 
  16093 					// 1. If a className is set as 'placeholder option, we don't force sizes -
  16094 					// the class is responsible for that
  16095 					// 2. The option 'forcePlaceholderSize can be enabled to force it even if a
  16096 					// class name is specified
  16097 					if ( className && !o.forcePlaceholderSize ) {
  16098 						return;
  16099 					}
  16100 
  16101 					//If the element doesn't have a actual height by itself (without styles coming
  16102 					// from a stylesheet), it receives the inline height from the dragged item
  16103 					if ( !p.height() ) {
  16104 						p.height(
  16105 							that.currentItem.innerHeight() -
  16106 							parseInt( that.currentItem.css( "paddingTop" ) || 0, 10 ) -
  16107 							parseInt( that.currentItem.css( "paddingBottom" ) || 0, 10 ) );
  16108 					}
  16109 					if ( !p.width() ) {
  16110 						p.width(
  16111 							that.currentItem.innerWidth() -
  16112 							parseInt( that.currentItem.css( "paddingLeft" ) || 0, 10 ) -
  16113 							parseInt( that.currentItem.css( "paddingRight" ) || 0, 10 ) );
  16114 					}
  16115 				}
  16116 			};
  16117 		}
  16118 
  16119 		//Create the placeholder
  16120 		that.placeholder = $( o.placeholder.element.call( that.element, that.currentItem ) );
  16121 
  16122 		//Append it after the actual current item
  16123 		that.currentItem.after( that.placeholder );
  16124 
  16125 		//Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
  16126 		o.placeholder.update( that, that.placeholder );
  16127 
  16128 	},
  16129 
  16130 	_createTrPlaceholder: function( sourceTr, targetTr ) {
  16131 		var that = this;
  16132 
  16133 		sourceTr.children().each( function() {
  16134 			$( "<td>&#160;</td>", that.document[ 0 ] )
  16135 				.attr( "colspan", $( this ).attr( "colspan" ) || 1 )
  16136 				.appendTo( targetTr );
  16137 		} );
  16138 	},
  16139 
  16140 	_contactContainers: function( event ) {
  16141 		var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, cur, nearBottom,
  16142 			floating, axis,
  16143 			innermostContainer = null,
  16144 			innermostIndex = null;
  16145 
  16146 		// Get innermost container that intersects with item
  16147 		for ( i = this.containers.length - 1; i >= 0; i-- ) {
  16148 
  16149 			// Never consider a container that's located within the item itself
  16150 			if ( $.contains( this.currentItem[ 0 ], this.containers[ i ].element[ 0 ] ) ) {
  16151 				continue;
  16152 			}
  16153 
  16154 			if ( this._intersectsWith( this.containers[ i ].containerCache ) ) {
  16155 
  16156 				// If we've already found a container and it's more "inner" than this, then continue
  16157 				if ( innermostContainer &&
  16158 						$.contains(
  16159 							this.containers[ i ].element[ 0 ],
  16160 							innermostContainer.element[ 0 ] ) ) {
  16161 					continue;
  16162 				}
  16163 
  16164 				innermostContainer = this.containers[ i ];
  16165 				innermostIndex = i;
  16166 
  16167 			} else {
  16168 
  16169 				// container doesn't intersect. trigger "out" event if necessary
  16170 				if ( this.containers[ i ].containerCache.over ) {
  16171 					this.containers[ i ]._trigger( "out", event, this._uiHash( this ) );
  16172 					this.containers[ i ].containerCache.over = 0;
  16173 				}
  16174 			}
  16175 
  16176 		}
  16177 
  16178 		// If no intersecting containers found, return
  16179 		if ( !innermostContainer ) {
  16180 			return;
  16181 		}
  16182 
  16183 		// Move the item into the container if it's not there already
  16184 		if ( this.containers.length === 1 ) {
  16185 			if ( !this.containers[ innermostIndex ].containerCache.over ) {
  16186 				this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash( this ) );
  16187 				this.containers[ innermostIndex ].containerCache.over = 1;
  16188 			}
  16189 		} else {
  16190 
  16191 			// When entering a new container, we will find the item with the least distance and
  16192 			// append our item near it
  16193 			dist = 10000;
  16194 			itemWithLeastDistance = null;
  16195 			floating = innermostContainer.floating || this._isFloating( this.currentItem );
  16196 			posProperty = floating ? "left" : "top";
  16197 			sizeProperty = floating ? "width" : "height";
  16198 			axis = floating ? "pageX" : "pageY";
  16199 
  16200 			for ( j = this.items.length - 1; j >= 0; j-- ) {
  16201 				if ( !$.contains(
  16202 						this.containers[ innermostIndex ].element[ 0 ], this.items[ j ].item[ 0 ] )
  16203 				) {
  16204 					continue;
  16205 				}
  16206 				if ( this.items[ j ].item[ 0 ] === this.currentItem[ 0 ] ) {
  16207 					continue;
  16208 				}
  16209 
  16210 				cur = this.items[ j ].item.offset()[ posProperty ];
  16211 				nearBottom = false;
  16212 				if ( event[ axis ] - cur > this.items[ j ][ sizeProperty ] / 2 ) {
  16213 					nearBottom = true;
  16214 				}
  16215 
  16216 				if ( Math.abs( event[ axis ] - cur ) < dist ) {
  16217 					dist = Math.abs( event[ axis ] - cur );
  16218 					itemWithLeastDistance = this.items[ j ];
  16219 					this.direction = nearBottom ? "up" : "down";
  16220 				}
  16221 			}
  16222 
  16223 			//Check if dropOnEmpty is enabled
  16224 			if ( !itemWithLeastDistance && !this.options.dropOnEmpty ) {
  16225 				return;
  16226 			}
  16227 
  16228 			if ( this.currentContainer === this.containers[ innermostIndex ] ) {
  16229 				if ( !this.currentContainer.containerCache.over ) {
  16230 					this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash() );
  16231 					this.currentContainer.containerCache.over = 1;
  16232 				}
  16233 				return;
  16234 			}
  16235 
  16236 			itemWithLeastDistance ?
  16237 				this._rearrange( event, itemWithLeastDistance, null, true ) :
  16238 				this._rearrange( event, null, this.containers[ innermostIndex ].element, true );
  16239 			this._trigger( "change", event, this._uiHash() );
  16240 			this.containers[ innermostIndex ]._trigger( "change", event, this._uiHash( this ) );
  16241 			this.currentContainer = this.containers[ innermostIndex ];
  16242 
  16243 			//Update the placeholder
  16244 			this.options.placeholder.update( this.currentContainer, this.placeholder );
  16245 
  16246 			this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash( this ) );
  16247 			this.containers[ innermostIndex ].containerCache.over = 1;
  16248 		}
  16249 
  16250 	},
  16251 
  16252 	_createHelper: function( event ) {
  16253 
  16254 		var o = this.options,
  16255 			helper = $.isFunction( o.helper ) ?
  16256 				$( o.helper.apply( this.element[ 0 ], [ event, this.currentItem ] ) ) :
  16257 				( o.helper === "clone" ? this.currentItem.clone() : this.currentItem );
  16258 
  16259 		//Add the helper to the DOM if that didn't happen already
  16260 		if ( !helper.parents( "body" ).length ) {
  16261 			$( o.appendTo !== "parent" ?
  16262 				o.appendTo :
  16263 				this.currentItem[ 0 ].parentNode )[ 0 ].appendChild( helper[ 0 ] );
  16264 		}
  16265 
  16266 		if ( helper[ 0 ] === this.currentItem[ 0 ] ) {
  16267 			this._storedCSS = {
  16268 				width: this.currentItem[ 0 ].style.width,
  16269 				height: this.currentItem[ 0 ].style.height,
  16270 				position: this.currentItem.css( "position" ),
  16271 				top: this.currentItem.css( "top" ),
  16272 				left: this.currentItem.css( "left" )
  16273 			};
  16274 		}
  16275 
  16276 		if ( !helper[ 0 ].style.width || o.forceHelperSize ) {
  16277 			helper.width( this.currentItem.width() );
  16278 		}
  16279 		if ( !helper[ 0 ].style.height || o.forceHelperSize ) {
  16280 			helper.height( this.currentItem.height() );
  16281 		}
  16282 
  16283 		return helper;
  16284 
  16285 	},
  16286 
  16287 	_adjustOffsetFromHelper: function( obj ) {
  16288 		if ( typeof obj === "string" ) {
  16289 			obj = obj.split( " " );
  16290 		}
  16291 		if ( $.isArray( obj ) ) {
  16292 			obj = { left: +obj[ 0 ], top: +obj[ 1 ] || 0 };
  16293 		}
  16294 		if ( "left" in obj ) {
  16295 			this.offset.click.left = obj.left + this.margins.left;
  16296 		}
  16297 		if ( "right" in obj ) {
  16298 			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
  16299 		}
  16300 		if ( "top" in obj ) {
  16301 			this.offset.click.top = obj.top + this.margins.top;
  16302 		}
  16303 		if ( "bottom" in obj ) {
  16304 			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
  16305 		}
  16306 	},
  16307 
  16308 	_getParentOffset: function() {
  16309 
  16310 		//Get the offsetParent and cache its position
  16311 		this.offsetParent = this.helper.offsetParent();
  16312 		var po = this.offsetParent.offset();
  16313 
  16314 		// This is a special case where we need to modify a offset calculated on start, since the
  16315 		// following happened:
  16316 		// 1. The position of the helper is absolute, so it's position is calculated based on the
  16317 		// next positioned parent
  16318 		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't
  16319 		// the document, which means that the scroll is included in the initial calculation of the
  16320 		// offset of the parent, and never recalculated upon drag
  16321 		if ( this.cssPosition === "absolute" && this.scrollParent[ 0 ] !== this.document[ 0 ] &&
  16322 				$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) {
  16323 			po.left += this.scrollParent.scrollLeft();
  16324 			po.top += this.scrollParent.scrollTop();
  16325 		}
  16326 
  16327 		// This needs to be actually done for all browsers, since pageX/pageY includes this
  16328 		// information with an ugly IE fix
  16329 		if ( this.offsetParent[ 0 ] === this.document[ 0 ].body ||
  16330 				( this.offsetParent[ 0 ].tagName &&
  16331 				this.offsetParent[ 0 ].tagName.toLowerCase() === "html" && $.ui.ie ) ) {
  16332 			po = { top: 0, left: 0 };
  16333 		}
  16334 
  16335 		return {
  16336 			top: po.top + ( parseInt( this.offsetParent.css( "borderTopWidth" ), 10 ) || 0 ),
  16337 			left: po.left + ( parseInt( this.offsetParent.css( "borderLeftWidth" ), 10 ) || 0 )
  16338 		};
  16339 
  16340 	},
  16341 
  16342 	_getRelativeOffset: function() {
  16343 
  16344 		if ( this.cssPosition === "relative" ) {
  16345 			var p = this.currentItem.position();
  16346 			return {
  16347 				top: p.top - ( parseInt( this.helper.css( "top" ), 10 ) || 0 ) +
  16348 					this.scrollParent.scrollTop(),
  16349 				left: p.left - ( parseInt( this.helper.css( "left" ), 10 ) || 0 ) +
  16350 					this.scrollParent.scrollLeft()
  16351 			};
  16352 		} else {
  16353 			return { top: 0, left: 0 };
  16354 		}
  16355 
  16356 	},
  16357 
  16358 	_cacheMargins: function() {
  16359 		this.margins = {
  16360 			left: ( parseInt( this.currentItem.css( "marginLeft" ), 10 ) || 0 ),
  16361 			top: ( parseInt( this.currentItem.css( "marginTop" ), 10 ) || 0 )
  16362 		};
  16363 	},
  16364 
  16365 	_cacheHelperProportions: function() {
  16366 		this.helperProportions = {
  16367 			width: this.helper.outerWidth(),
  16368 			height: this.helper.outerHeight()
  16369 		};
  16370 	},
  16371 
  16372 	_setContainment: function() {
  16373 
  16374 		var ce, co, over,
  16375 			o = this.options;
  16376 		if ( o.containment === "parent" ) {
  16377 			o.containment = this.helper[ 0 ].parentNode;
  16378 		}
  16379 		if ( o.containment === "document" || o.containment === "window" ) {
  16380 			this.containment = [
  16381 				0 - this.offset.relative.left - this.offset.parent.left,
  16382 				0 - this.offset.relative.top - this.offset.parent.top,
  16383 				o.containment === "document" ?
  16384 					this.document.width() :
  16385 					this.window.width() - this.helperProportions.width - this.margins.left,
  16386 				( o.containment === "document" ?
  16387 					( this.document.height() || document.body.parentNode.scrollHeight ) :
  16388 					this.window.height() || this.document[ 0 ].body.parentNode.scrollHeight
  16389 				) - this.helperProportions.height - this.margins.top
  16390 			];
  16391 		}
  16392 
  16393 		if ( !( /^(document|window|parent)$/ ).test( o.containment ) ) {
  16394 			ce = $( o.containment )[ 0 ];
  16395 			co = $( o.containment ).offset();
  16396 			over = ( $( ce ).css( "overflow" ) !== "hidden" );
  16397 
  16398 			this.containment = [
  16399 				co.left + ( parseInt( $( ce ).css( "borderLeftWidth" ), 10 ) || 0 ) +
  16400 					( parseInt( $( ce ).css( "paddingLeft" ), 10 ) || 0 ) - this.margins.left,
  16401 				co.top + ( parseInt( $( ce ).css( "borderTopWidth" ), 10 ) || 0 ) +
  16402 					( parseInt( $( ce ).css( "paddingTop" ), 10 ) || 0 ) - this.margins.top,
  16403 				co.left + ( over ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) -
  16404 					( parseInt( $( ce ).css( "borderLeftWidth" ), 10 ) || 0 ) -
  16405 					( parseInt( $( ce ).css( "paddingRight" ), 10 ) || 0 ) -
  16406 					this.helperProportions.width - this.margins.left,
  16407 				co.top + ( over ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) -
  16408 					( parseInt( $( ce ).css( "borderTopWidth" ), 10 ) || 0 ) -
  16409 					( parseInt( $( ce ).css( "paddingBottom" ), 10 ) || 0 ) -
  16410 					this.helperProportions.height - this.margins.top
  16411 			];
  16412 		}
  16413 
  16414 	},
  16415 
  16416 	_convertPositionTo: function( d, pos ) {
  16417 
  16418 		if ( !pos ) {
  16419 			pos = this.position;
  16420 		}
  16421 		var mod = d === "absolute" ? 1 : -1,
  16422 			scroll = this.cssPosition === "absolute" &&
  16423 				!( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
  16424 				$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ?
  16425 					this.offsetParent :
  16426 					this.scrollParent,
  16427 			scrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName );
  16428 
  16429 		return {
  16430 			top: (
  16431 
  16432 				// The absolute mouse position
  16433 				pos.top	+
  16434 
  16435 				// Only for relative positioned nodes: Relative offset from element to offset parent
  16436 				this.offset.relative.top * mod +
  16437 
  16438 				// The offsetParent's offset without borders (offset + border)
  16439 				this.offset.parent.top * mod -
  16440 				( ( this.cssPosition === "fixed" ?
  16441 					-this.scrollParent.scrollTop() :
  16442 					( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod )
  16443 			),
  16444 			left: (
  16445 
  16446 				// The absolute mouse position
  16447 				pos.left +
  16448 
  16449 				// Only for relative positioned nodes: Relative offset from element to offset parent
  16450 				this.offset.relative.left * mod +
  16451 
  16452 				// The offsetParent's offset without borders (offset + border)
  16453 				this.offset.parent.left * mod	-
  16454 				( ( this.cssPosition === "fixed" ?
  16455 					-this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 :
  16456 					scroll.scrollLeft() ) * mod )
  16457 			)
  16458 		};
  16459 
  16460 	},
  16461 
  16462 	_generatePosition: function( event ) {
  16463 
  16464 		var top, left,
  16465 			o = this.options,
  16466 			pageX = event.pageX,
  16467 			pageY = event.pageY,
  16468 			scroll = this.cssPosition === "absolute" &&
  16469 				!( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
  16470 				$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ?
  16471 					this.offsetParent :
  16472 					this.scrollParent,
  16473 				scrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName );
  16474 
  16475 		// This is another very weird special case that only happens for relative elements:
  16476 		// 1. If the css position is relative
  16477 		// 2. and the scroll parent is the document or similar to the offset parent
  16478 		// we have to refresh the relative offset during the scroll so there are no jumps
  16479 		if ( this.cssPosition === "relative" && !( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
  16480 				this.scrollParent[ 0 ] !== this.offsetParent[ 0 ] ) ) {
  16481 			this.offset.relative = this._getRelativeOffset();
  16482 		}
  16483 
  16484 		/*
  16485 		 * - Position constraining -
  16486 		 * Constrain the position to a mix of grid, containment.
  16487 		 */
  16488 
  16489 		if ( this.originalPosition ) { //If we are not dragging yet, we won't check for options
  16490 
  16491 			if ( this.containment ) {
  16492 				if ( event.pageX - this.offset.click.left < this.containment[ 0 ] ) {
  16493 					pageX = this.containment[ 0 ] + this.offset.click.left;
  16494 				}
  16495 				if ( event.pageY - this.offset.click.top < this.containment[ 1 ] ) {
  16496 					pageY = this.containment[ 1 ] + this.offset.click.top;
  16497 				}
  16498 				if ( event.pageX - this.offset.click.left > this.containment[ 2 ] ) {
  16499 					pageX = this.containment[ 2 ] + this.offset.click.left;
  16500 				}
  16501 				if ( event.pageY - this.offset.click.top > this.containment[ 3 ] ) {
  16502 					pageY = this.containment[ 3 ] + this.offset.click.top;
  16503 				}
  16504 			}
  16505 
  16506 			if ( o.grid ) {
  16507 				top = this.originalPageY + Math.round( ( pageY - this.originalPageY ) /
  16508 					o.grid[ 1 ] ) * o.grid[ 1 ];
  16509 				pageY = this.containment ?
  16510 					( ( top - this.offset.click.top >= this.containment[ 1 ] &&
  16511 						top - this.offset.click.top <= this.containment[ 3 ] ) ?
  16512 							top :
  16513 							( ( top - this.offset.click.top >= this.containment[ 1 ] ) ?
  16514 								top - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) :
  16515 								top;
  16516 
  16517 				left = this.originalPageX + Math.round( ( pageX - this.originalPageX ) /
  16518 					o.grid[ 0 ] ) * o.grid[ 0 ];
  16519 				pageX = this.containment ?
  16520 					( ( left - this.offset.click.left >= this.containment[ 0 ] &&
  16521 						left - this.offset.click.left <= this.containment[ 2 ] ) ?
  16522 							left :
  16523 							( ( left - this.offset.click.left >= this.containment[ 0 ] ) ?
  16524 								left - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) :
  16525 								left;
  16526 			}
  16527 
  16528 		}
  16529 
  16530 		return {
  16531 			top: (
  16532 
  16533 				// The absolute mouse position
  16534 				pageY -
  16535 
  16536 				// Click offset (relative to the element)
  16537 				this.offset.click.top -
  16538 
  16539 				// Only for relative positioned nodes: Relative offset from element to offset parent
  16540 				this.offset.relative.top -
  16541 
  16542 				// The offsetParent's offset without borders (offset + border)
  16543 				this.offset.parent.top +
  16544 				( ( this.cssPosition === "fixed" ?
  16545 					-this.scrollParent.scrollTop() :
  16546 					( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) )
  16547 			),
  16548 			left: (
  16549 
  16550 				// The absolute mouse position
  16551 				pageX -
  16552 
  16553 				// Click offset (relative to the element)
  16554 				this.offset.click.left -
  16555 
  16556 				// Only for relative positioned nodes: Relative offset from element to offset parent
  16557 				this.offset.relative.left -
  16558 
  16559 				// The offsetParent's offset without borders (offset + border)
  16560 				this.offset.parent.left +
  16561 				( ( this.cssPosition === "fixed" ?
  16562 					-this.scrollParent.scrollLeft() :
  16563 					scrollIsRootNode ? 0 : scroll.scrollLeft() ) )
  16564 			)
  16565 		};
  16566 
  16567 	},
  16568 
  16569 	_rearrange: function( event, i, a, hardRefresh ) {
  16570 
  16571 		a ? a[ 0 ].appendChild( this.placeholder[ 0 ] ) :
  16572 			i.item[ 0 ].parentNode.insertBefore( this.placeholder[ 0 ],
  16573 				( this.direction === "down" ? i.item[ 0 ] : i.item[ 0 ].nextSibling ) );
  16574 
  16575 		//Various things done here to improve the performance:
  16576 		// 1. we create a setTimeout, that calls refreshPositions
  16577 		// 2. on the instance, we have a counter variable, that get's higher after every append
  16578 		// 3. on the local scope, we copy the counter variable, and check in the timeout,
  16579 		// if it's still the same
  16580 		// 4. this lets only the last addition to the timeout stack through
  16581 		this.counter = this.counter ? ++this.counter : 1;
  16582 		var counter = this.counter;
  16583 
  16584 		this._delay( function() {
  16585 			if ( counter === this.counter ) {
  16586 
  16587 				//Precompute after each DOM insertion, NOT on mousemove
  16588 				this.refreshPositions( !hardRefresh );
  16589 			}
  16590 		} );
  16591 
  16592 	},
  16593 
  16594 	_clear: function( event, noPropagation ) {
  16595 
  16596 		this.reverting = false;
  16597 
  16598 		// We delay all events that have to be triggered to after the point where the placeholder
  16599 		// has been removed and everything else normalized again
  16600 		var i,
  16601 			delayedTriggers = [];
  16602 
  16603 		// We first have to update the dom position of the actual currentItem
  16604 		// Note: don't do it if the current item is already removed (by a user), or it gets
  16605 		// reappended (see #4088)
  16606 		if ( !this._noFinalSort && this.currentItem.parent().length ) {
  16607 			this.placeholder.before( this.currentItem );
  16608 		}
  16609 		this._noFinalSort = null;
  16610 
  16611 		if ( this.helper[ 0 ] === this.currentItem[ 0 ] ) {
  16612 			for ( i in this._storedCSS ) {
  16613 				if ( this._storedCSS[ i ] === "auto" || this._storedCSS[ i ] === "static" ) {
  16614 					this._storedCSS[ i ] = "";
  16615 				}
  16616 			}
  16617 			this.currentItem.css( this._storedCSS );
  16618 			this._removeClass( this.currentItem, "ui-sortable-helper" );
  16619 		} else {
  16620 			this.currentItem.show();
  16621 		}
  16622 
  16623 		if ( this.fromOutside && !noPropagation ) {
  16624 			delayedTriggers.push( function( event ) {
  16625 				this._trigger( "receive", event, this._uiHash( this.fromOutside ) );
  16626 			} );
  16627 		}
  16628 		if ( ( this.fromOutside ||
  16629 				this.domPosition.prev !==
  16630 				this.currentItem.prev().not( ".ui-sortable-helper" )[ 0 ] ||
  16631 				this.domPosition.parent !== this.currentItem.parent()[ 0 ] ) && !noPropagation ) {
  16632 
  16633 			// Trigger update callback if the DOM position has changed
  16634 			delayedTriggers.push( function( event ) {
  16635 				this._trigger( "update", event, this._uiHash() );
  16636 			} );
  16637 		}
  16638 
  16639 		// Check if the items Container has Changed and trigger appropriate
  16640 		// events.
  16641 		if ( this !== this.currentContainer ) {
  16642 			if ( !noPropagation ) {
  16643 				delayedTriggers.push( function( event ) {
  16644 					this._trigger( "remove", event, this._uiHash() );
  16645 				} );
  16646 				delayedTriggers.push( ( function( c ) {
  16647 					return function( event ) {
  16648 						c._trigger( "receive", event, this._uiHash( this ) );
  16649 					};
  16650 				} ).call( this, this.currentContainer ) );
  16651 				delayedTriggers.push( ( function( c ) {
  16652 					return function( event ) {
  16653 						c._trigger( "update", event, this._uiHash( this ) );
  16654 					};
  16655 				} ).call( this, this.currentContainer ) );
  16656 			}
  16657 		}
  16658 
  16659 		//Post events to containers
  16660 		function delayEvent( type, instance, container ) {
  16661 			return function( event ) {
  16662 				container._trigger( type, event, instance._uiHash( instance ) );
  16663 			};
  16664 		}
  16665 		for ( i = this.containers.length - 1; i >= 0; i-- ) {
  16666 			if ( !noPropagation ) {
  16667 				delayedTriggers.push( delayEvent( "deactivate", this, this.containers[ i ] ) );
  16668 			}
  16669 			if ( this.containers[ i ].containerCache.over ) {
  16670 				delayedTriggers.push( delayEvent( "out", this, this.containers[ i ] ) );
  16671 				this.containers[ i ].containerCache.over = 0;
  16672 			}
  16673 		}
  16674 
  16675 		//Do what was originally in plugins
  16676 		if ( this.storedCursor ) {
  16677 			this.document.find( "body" ).css( "cursor", this.storedCursor );
  16678 			this.storedStylesheet.remove();
  16679 		}
  16680 		if ( this._storedOpacity ) {
  16681 			this.helper.css( "opacity", this._storedOpacity );
  16682 		}
  16683 		if ( this._storedZIndex ) {
  16684 			this.helper.css( "zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex );
  16685 		}
  16686 
  16687 		this.dragging = false;
  16688 
  16689 		if ( !noPropagation ) {
  16690 			this._trigger( "beforeStop", event, this._uiHash() );
  16691 		}
  16692 
  16693 		//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately,
  16694 		// it unbinds ALL events from the original node!
  16695 		this.placeholder[ 0 ].parentNode.removeChild( this.placeholder[ 0 ] );
  16696 
  16697 		if ( !this.cancelHelperRemoval ) {
  16698 			if ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) {
  16699 				this.helper.remove();
  16700 			}
  16701 			this.helper = null;
  16702 		}
  16703 
  16704 		if ( !noPropagation ) {
  16705 			for ( i = 0; i < delayedTriggers.length; i++ ) {
  16706 
  16707 				// Trigger all delayed events
  16708 				delayedTriggers[ i ].call( this, event );
  16709 			}
  16710 			this._trigger( "stop", event, this._uiHash() );
  16711 		}
  16712 
  16713 		this.fromOutside = false;
  16714 		return !this.cancelHelperRemoval;
  16715 
  16716 	},
  16717 
  16718 	_trigger: function() {
  16719 		if ( $.Widget.prototype._trigger.apply( this, arguments ) === false ) {
  16720 			this.cancel();
  16721 		}
  16722 	},
  16723 
  16724 	_uiHash: function( _inst ) {
  16725 		var inst = _inst || this;
  16726 		return {
  16727 			helper: inst.helper,
  16728 			placeholder: inst.placeholder || $( [] ),
  16729 			position: inst.position,
  16730 			originalPosition: inst.originalPosition,
  16731 			offset: inst.positionAbs,
  16732 			item: inst.currentItem,
  16733 			sender: _inst ? _inst.element : null
  16734 		};
  16735 	}
  16736 
  16737 } );
  16738 
  16739 
  16740 /*!
  16741  * jQuery UI Spinner 1.12.1
  16742  * http://jqueryui.com
  16743  *
  16744  * Copyright jQuery Foundation and other contributors
  16745  * Released under the MIT license.
  16746  * http://jquery.org/license
  16747  */
  16748 
  16749 //>>label: Spinner
  16750 //>>group: Widgets
  16751 //>>description: Displays buttons to easily input numbers via the keyboard or mouse.
  16752 //>>docs: http://api.jqueryui.com/spinner/
  16753 //>>demos: http://jqueryui.com/spinner/
  16754 //>>css.structure: ../../themes/base/core.css
  16755 //>>css.structure: ../../themes/base/spinner.css
  16756 //>>css.theme: ../../themes/base/theme.css
  16757 
  16758 
  16759 
  16760 function spinnerModifer( fn ) {
  16761 	return function() {
  16762 		var previous = this.element.val();
  16763 		fn.apply( this, arguments );
  16764 		this._refresh();
  16765 		if ( previous !== this.element.val() ) {
  16766 			this._trigger( "change" );
  16767 		}
  16768 	};
  16769 }
  16770 
  16771 $.widget( "ui.spinner", {
  16772 	version: "1.12.1",
  16773 	defaultElement: "<input>",
  16774 	widgetEventPrefix: "spin",
  16775 	options: {
  16776 		classes: {
  16777 			"ui-spinner": "ui-corner-all",
  16778 			"ui-spinner-down": "ui-corner-br",
  16779 			"ui-spinner-up": "ui-corner-tr"
  16780 		},
  16781 		culture: null,
  16782 		icons: {
  16783 			down: "ui-icon-triangle-1-s",
  16784 			up: "ui-icon-triangle-1-n"
  16785 		},
  16786 		incremental: true,
  16787 		max: null,
  16788 		min: null,
  16789 		numberFormat: null,
  16790 		page: 10,
  16791 		step: 1,
  16792 
  16793 		change: null,
  16794 		spin: null,
  16795 		start: null,
  16796 		stop: null
  16797 	},
  16798 
  16799 	_create: function() {
  16800 
  16801 		// handle string values that need to be parsed
  16802 		this._setOption( "max", this.options.max );
  16803 		this._setOption( "min", this.options.min );
  16804 		this._setOption( "step", this.options.step );
  16805 
  16806 		// Only format if there is a value, prevents the field from being marked
  16807 		// as invalid in Firefox, see #9573.
  16808 		if ( this.value() !== "" ) {
  16809 
  16810 			// Format the value, but don't constrain.
  16811 			this._value( this.element.val(), true );
  16812 		}
  16813 
  16814 		this._draw();
  16815 		this._on( this._events );
  16816 		this._refresh();
  16817 
  16818 		// Turning off autocomplete prevents the browser from remembering the
  16819 		// value when navigating through history, so we re-enable autocomplete
  16820 		// if the page is unloaded before the widget is destroyed. #7790
  16821 		this._on( this.window, {
  16822 			beforeunload: function() {
  16823 				this.element.removeAttr( "autocomplete" );
  16824 			}
  16825 		} );
  16826 	},
  16827 
  16828 	_getCreateOptions: function() {
  16829 		var options = this._super();
  16830 		var element = this.element;
  16831 
  16832 		$.each( [ "min", "max", "step" ], function( i, option ) {
  16833 			var value = element.attr( option );
  16834 			if ( value != null && value.length ) {
  16835 				options[ option ] = value;
  16836 			}
  16837 		} );
  16838 
  16839 		return options;
  16840 	},
  16841 
  16842 	_events: {
  16843 		keydown: function( event ) {
  16844 			if ( this._start( event ) && this._keydown( event ) ) {
  16845 				event.preventDefault();
  16846 			}
  16847 		},
  16848 		keyup: "_stop",
  16849 		focus: function() {
  16850 			this.previous = this.element.val();
  16851 		},
  16852 		blur: function( event ) {
  16853 			if ( this.cancelBlur ) {
  16854 				delete this.cancelBlur;
  16855 				return;
  16856 			}
  16857 
  16858 			this._stop();
  16859 			this._refresh();
  16860 			if ( this.previous !== this.element.val() ) {
  16861 				this._trigger( "change", event );
  16862 			}
  16863 		},
  16864 		mousewheel: function( event, delta ) {
  16865 			if ( !delta ) {
  16866 				return;
  16867 			}
  16868 			if ( !this.spinning && !this._start( event ) ) {
  16869 				return false;
  16870 			}
  16871 
  16872 			this._spin( ( delta > 0 ? 1 : -1 ) * this.options.step, event );
  16873 			clearTimeout( this.mousewheelTimer );
  16874 			this.mousewheelTimer = this._delay( function() {
  16875 				if ( this.spinning ) {
  16876 					this._stop( event );
  16877 				}
  16878 			}, 100 );
  16879 			event.preventDefault();
  16880 		},
  16881 		"mousedown .ui-spinner-button": function( event ) {
  16882 			var previous;
  16883 
  16884 			// We never want the buttons to have focus; whenever the user is
  16885 			// interacting with the spinner, the focus should be on the input.
  16886 			// If the input is focused then this.previous is properly set from
  16887 			// when the input first received focus. If the input is not focused
  16888 			// then we need to set this.previous based on the value before spinning.
  16889 			previous = this.element[ 0 ] === $.ui.safeActiveElement( this.document[ 0 ] ) ?
  16890 				this.previous : this.element.val();
  16891 			function checkFocus() {
  16892 				var isActive = this.element[ 0 ] === $.ui.safeActiveElement( this.document[ 0 ] );
  16893 				if ( !isActive ) {
  16894 					this.element.trigger( "focus" );
  16895 					this.previous = previous;
  16896 
  16897 					// support: IE
  16898 					// IE sets focus asynchronously, so we need to check if focus
  16899 					// moved off of the input because the user clicked on the button.
  16900 					this._delay( function() {
  16901 						this.previous = previous;
  16902 					} );
  16903 				}
  16904 			}
  16905 
  16906 			// Ensure focus is on (or stays on) the text field
  16907 			event.preventDefault();
  16908 			checkFocus.call( this );
  16909 
  16910 			// Support: IE
  16911 			// IE doesn't prevent moving focus even with event.preventDefault()
  16912 			// so we set a flag to know when we should ignore the blur event
  16913 			// and check (again) if focus moved off of the input.
  16914 			this.cancelBlur = true;
  16915 			this._delay( function() {
  16916 				delete this.cancelBlur;
  16917 				checkFocus.call( this );
  16918 			} );
  16919 
  16920 			if ( this._start( event ) === false ) {
  16921 				return;
  16922 			}
  16923 
  16924 			this._repeat( null, $( event.currentTarget )
  16925 				.hasClass( "ui-spinner-up" ) ? 1 : -1, event );
  16926 		},
  16927 		"mouseup .ui-spinner-button": "_stop",
  16928 		"mouseenter .ui-spinner-button": function( event ) {
  16929 
  16930 			// button will add ui-state-active if mouse was down while mouseleave and kept down
  16931 			if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) {
  16932 				return;
  16933 			}
  16934 
  16935 			if ( this._start( event ) === false ) {
  16936 				return false;
  16937 			}
  16938 			this._repeat( null, $( event.currentTarget )
  16939 				.hasClass( "ui-spinner-up" ) ? 1 : -1, event );
  16940 		},
  16941 
  16942 		// TODO: do we really want to consider this a stop?
  16943 		// shouldn't we just stop the repeater and wait until mouseup before
  16944 		// we trigger the stop event?
  16945 		"mouseleave .ui-spinner-button": "_stop"
  16946 	},
  16947 
  16948 	// Support mobile enhanced option and make backcompat more sane
  16949 	_enhance: function() {
  16950 		this.uiSpinner = this.element
  16951 			.attr( "autocomplete", "off" )
  16952 			.wrap( "<span>" )
  16953 			.parent()
  16954 
  16955 				// Add buttons
  16956 				.append(
  16957 					"<a></a><a></a>"
  16958 				);
  16959 	},
  16960 
  16961 	_draw: function() {
  16962 		this._enhance();
  16963 
  16964 		this._addClass( this.uiSpinner, "ui-spinner", "ui-widget ui-widget-content" );
  16965 		this._addClass( "ui-spinner-input" );
  16966 
  16967 		this.element.attr( "role", "spinbutton" );
  16968 
  16969 		// Button bindings
  16970 		this.buttons = this.uiSpinner.children( "a" )
  16971 			.attr( "tabIndex", -1 )
  16972 			.attr( "aria-hidden", true )
  16973 			.button( {
  16974 				classes: {
  16975 					"ui-button": ""
  16976 				}
  16977 			} );
  16978 
  16979 		// TODO: Right now button does not support classes this is already updated in button PR
  16980 		this._removeClass( this.buttons, "ui-corner-all" );
  16981 
  16982 		this._addClass( this.buttons.first(), "ui-spinner-button ui-spinner-up" );
  16983 		this._addClass( this.buttons.last(), "ui-spinner-button ui-spinner-down" );
  16984 		this.buttons.first().button( {
  16985 			"icon": this.options.icons.up,
  16986 			"showLabel": false
  16987 		} );
  16988 		this.buttons.last().button( {
  16989 			"icon": this.options.icons.down,
  16990 			"showLabel": false
  16991 		} );
  16992 
  16993 		// IE 6 doesn't understand height: 50% for the buttons
  16994 		// unless the wrapper has an explicit height
  16995 		if ( this.buttons.height() > Math.ceil( this.uiSpinner.height() * 0.5 ) &&
  16996 				this.uiSpinner.height() > 0 ) {
  16997 			this.uiSpinner.height( this.uiSpinner.height() );
  16998 		}
  16999 	},
  17000 
  17001 	_keydown: function( event ) {
  17002 		var options = this.options,
  17003 			keyCode = $.ui.keyCode;
  17004 
  17005 		switch ( event.keyCode ) {
  17006 		case keyCode.UP:
  17007 			this._repeat( null, 1, event );
  17008 			return true;
  17009 		case keyCode.DOWN:
  17010 			this._repeat( null, -1, event );
  17011 			return true;
  17012 		case keyCode.PAGE_UP:
  17013 			this._repeat( null, options.page, event );
  17014 			return true;
  17015 		case keyCode.PAGE_DOWN:
  17016 			this._repeat( null, -options.page, event );
  17017 			return true;
  17018 		}
  17019 
  17020 		return false;
  17021 	},
  17022 
  17023 	_start: function( event ) {
  17024 		if ( !this.spinning && this._trigger( "start", event ) === false ) {
  17025 			return false;
  17026 		}
  17027 
  17028 		if ( !this.counter ) {
  17029 			this.counter = 1;
  17030 		}
  17031 		this.spinning = true;
  17032 		return true;
  17033 	},
  17034 
  17035 	_repeat: function( i, steps, event ) {
  17036 		i = i || 500;
  17037 
  17038 		clearTimeout( this.timer );
  17039 		this.timer = this._delay( function() {
  17040 			this._repeat( 40, steps, event );
  17041 		}, i );
  17042 
  17043 		this._spin( steps * this.options.step, event );
  17044 	},
  17045 
  17046 	_spin: function( step, event ) {
  17047 		var value = this.value() || 0;
  17048 
  17049 		if ( !this.counter ) {
  17050 			this.counter = 1;
  17051 		}
  17052 
  17053 		value = this._adjustValue( value + step * this._increment( this.counter ) );
  17054 
  17055 		if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false ) {
  17056 			this._value( value );
  17057 			this.counter++;
  17058 		}
  17059 	},
  17060 
  17061 	_increment: function( i ) {
  17062 		var incremental = this.options.incremental;
  17063 
  17064 		if ( incremental ) {
  17065 			return $.isFunction( incremental ) ?
  17066 				incremental( i ) :
  17067 				Math.floor( i * i * i / 50000 - i * i / 500 + 17 * i / 200 + 1 );
  17068 		}
  17069 
  17070 		return 1;
  17071 	},
  17072 
  17073 	_precision: function() {
  17074 		var precision = this._precisionOf( this.options.step );
  17075 		if ( this.options.min !== null ) {
  17076 			precision = Math.max( precision, this._precisionOf( this.options.min ) );
  17077 		}
  17078 		return precision;
  17079 	},
  17080 
  17081 	_precisionOf: function( num ) {
  17082 		var str = num.toString(),
  17083 			decimal = str.indexOf( "." );
  17084 		return decimal === -1 ? 0 : str.length - decimal - 1;
  17085 	},
  17086 
  17087 	_adjustValue: function( value ) {
  17088 		var base, aboveMin,
  17089 			options = this.options;
  17090 
  17091 		// Make sure we're at a valid step
  17092 		// - find out where we are relative to the base (min or 0)
  17093 		base = options.min !== null ? options.min : 0;
  17094 		aboveMin = value - base;
  17095 
  17096 		// - round to the nearest step
  17097 		aboveMin = Math.round( aboveMin / options.step ) * options.step;
  17098 
  17099 		// - rounding is based on 0, so adjust back to our base
  17100 		value = base + aboveMin;
  17101 
  17102 		// Fix precision from bad JS floating point math
  17103 		value = parseFloat( value.toFixed( this._precision() ) );
  17104 
  17105 		// Clamp the value
  17106 		if ( options.max !== null && value > options.max ) {
  17107 			return options.max;
  17108 		}
  17109 		if ( options.min !== null && value < options.min ) {
  17110 			return options.min;
  17111 		}
  17112 
  17113 		return value;
  17114 	},
  17115 
  17116 	_stop: function( event ) {
  17117 		if ( !this.spinning ) {
  17118 			return;
  17119 		}
  17120 
  17121 		clearTimeout( this.timer );
  17122 		clearTimeout( this.mousewheelTimer );
  17123 		this.counter = 0;
  17124 		this.spinning = false;
  17125 		this._trigger( "stop", event );
  17126 	},
  17127 
  17128 	_setOption: function( key, value ) {
  17129 		var prevValue, first, last;
  17130 
  17131 		if ( key === "culture" || key === "numberFormat" ) {
  17132 			prevValue = this._parse( this.element.val() );
  17133 			this.options[ key ] = value;
  17134 			this.element.val( this._format( prevValue ) );
  17135 			return;
  17136 		}
  17137 
  17138 		if ( key === "max" || key === "min" || key === "step" ) {
  17139 			if ( typeof value === "string" ) {
  17140 				value = this._parse( value );
  17141 			}
  17142 		}
  17143 		if ( key === "icons" ) {
  17144 			first = this.buttons.first().find( ".ui-icon" );
  17145 			this._removeClass( first, null, this.options.icons.up );
  17146 			this._addClass( first, null, value.up );
  17147 			last = this.buttons.last().find( ".ui-icon" );
  17148 			this._removeClass( last, null, this.options.icons.down );
  17149 			this._addClass( last, null, value.down );
  17150 		}
  17151 
  17152 		this._super( key, value );
  17153 	},
  17154 
  17155 	_setOptionDisabled: function( value ) {
  17156 		this._super( value );
  17157 
  17158 		this._toggleClass( this.uiSpinner, null, "ui-state-disabled", !!value );
  17159 		this.element.prop( "disabled", !!value );
  17160 		this.buttons.button( value ? "disable" : "enable" );
  17161 	},
  17162 
  17163 	_setOptions: spinnerModifer( function( options ) {
  17164 		this._super( options );
  17165 	} ),
  17166 
  17167 	_parse: function( val ) {
  17168 		if ( typeof val === "string" && val !== "" ) {
  17169 			val = window.Globalize && this.options.numberFormat ?
  17170 				Globalize.parseFloat( val, 10, this.options.culture ) : +val;
  17171 		}
  17172 		return val === "" || isNaN( val ) ? null : val;
  17173 	},
  17174 
  17175 	_format: function( value ) {
  17176 		if ( value === "" ) {
  17177 			return "";
  17178 		}
  17179 		return window.Globalize && this.options.numberFormat ?
  17180 			Globalize.format( value, this.options.numberFormat, this.options.culture ) :
  17181 			value;
  17182 	},
  17183 
  17184 	_refresh: function() {
  17185 		this.element.attr( {
  17186 			"aria-valuemin": this.options.min,
  17187 			"aria-valuemax": this.options.max,
  17188 
  17189 			// TODO: what should we do with values that can't be parsed?
  17190 			"aria-valuenow": this._parse( this.element.val() )
  17191 		} );
  17192 	},
  17193 
  17194 	isValid: function() {
  17195 		var value = this.value();
  17196 
  17197 		// Null is invalid
  17198 		if ( value === null ) {
  17199 			return false;
  17200 		}
  17201 
  17202 		// If value gets adjusted, it's invalid
  17203 		return value === this._adjustValue( value );
  17204 	},
  17205 
  17206 	// Update the value without triggering change
  17207 	_value: function( value, allowAny ) {
  17208 		var parsed;
  17209 		if ( value !== "" ) {
  17210 			parsed = this._parse( value );
  17211 			if ( parsed !== null ) {
  17212 				if ( !allowAny ) {
  17213 					parsed = this._adjustValue( parsed );
  17214 				}
  17215 				value = this._format( parsed );
  17216 			}
  17217 		}
  17218 		this.element.val( value );
  17219 		this._refresh();
  17220 	},
  17221 
  17222 	_destroy: function() {
  17223 		this.element
  17224 			.prop( "disabled", false )
  17225 			.removeAttr( "autocomplete role aria-valuemin aria-valuemax aria-valuenow" );
  17226 
  17227 		this.uiSpinner.replaceWith( this.element );
  17228 	},
  17229 
  17230 	stepUp: spinnerModifer( function( steps ) {
  17231 		this._stepUp( steps );
  17232 	} ),
  17233 	_stepUp: function( steps ) {
  17234 		if ( this._start() ) {
  17235 			this._spin( ( steps || 1 ) * this.options.step );
  17236 			this._stop();
  17237 		}
  17238 	},
  17239 
  17240 	stepDown: spinnerModifer( function( steps ) {
  17241 		this._stepDown( steps );
  17242 	} ),
  17243 	_stepDown: function( steps ) {
  17244 		if ( this._start() ) {
  17245 			this._spin( ( steps || 1 ) * -this.options.step );
  17246 			this._stop();
  17247 		}
  17248 	},
  17249 
  17250 	pageUp: spinnerModifer( function( pages ) {
  17251 		this._stepUp( ( pages || 1 ) * this.options.page );
  17252 	} ),
  17253 
  17254 	pageDown: spinnerModifer( function( pages ) {
  17255 		this._stepDown( ( pages || 1 ) * this.options.page );
  17256 	} ),
  17257 
  17258 	value: function( newVal ) {
  17259 		if ( !arguments.length ) {
  17260 			return this._parse( this.element.val() );
  17261 		}
  17262 		spinnerModifer( this._value ).call( this, newVal );
  17263 	},
  17264 
  17265 	widget: function() {
  17266 		return this.uiSpinner;
  17267 	}
  17268 } );
  17269 
  17270 // DEPRECATED
  17271 // TODO: switch return back to widget declaration at top of file when this is removed
  17272 if ( $.uiBackCompat !== false ) {
  17273 
  17274 	// Backcompat for spinner html extension points
  17275 	$.widget( "ui.spinner", $.ui.spinner, {
  17276 		_enhance: function() {
  17277 			this.uiSpinner = this.element
  17278 				.attr( "autocomplete", "off" )
  17279 				.wrap( this._uiSpinnerHtml() )
  17280 				.parent()
  17281 
  17282 					// Add buttons
  17283 					.append( this._buttonHtml() );
  17284 		},
  17285 		_uiSpinnerHtml: function() {
  17286 			return "<span>";
  17287 		},
  17288 
  17289 		_buttonHtml: function() {
  17290 			return "<a></a><a></a>";
  17291 		}
  17292 	} );
  17293 }
  17294 
  17295 var widgetsSpinner = $.ui.spinner;
  17296 
  17297 
  17298 /*!
  17299  * jQuery UI Tabs 1.12.1
  17300  * http://jqueryui.com
  17301  *
  17302  * Copyright jQuery Foundation and other contributors
  17303  * Released under the MIT license.
  17304  * http://jquery.org/license
  17305  */
  17306 
  17307 //>>label: Tabs
  17308 //>>group: Widgets
  17309 //>>description: Transforms a set of container elements into a tab structure.
  17310 //>>docs: http://api.jqueryui.com/tabs/
  17311 //>>demos: http://jqueryui.com/tabs/
  17312 //>>css.structure: ../../themes/base/core.css
  17313 //>>css.structure: ../../themes/base/tabs.css
  17314 //>>css.theme: ../../themes/base/theme.css
  17315 
  17316 
  17317 
  17318 $.widget( "ui.tabs", {
  17319 	version: "1.12.1",
  17320 	delay: 300,
  17321 	options: {
  17322 		active: null,
  17323 		classes: {
  17324 			"ui-tabs": "ui-corner-all",
  17325 			"ui-tabs-nav": "ui-corner-all",
  17326 			"ui-tabs-panel": "ui-corner-bottom",
  17327 			"ui-tabs-tab": "ui-corner-top"
  17328 		},
  17329 		collapsible: false,
  17330 		event: "click",
  17331 		heightStyle: "content",
  17332 		hide: null,
  17333 		show: null,
  17334 
  17335 		// Callbacks
  17336 		activate: null,
  17337 		beforeActivate: null,
  17338 		beforeLoad: null,
  17339 		load: null
  17340 	},
  17341 
  17342 	_isLocal: ( function() {
  17343 		var rhash = /#.*$/;
  17344 
  17345 		return function( anchor ) {
  17346 			var anchorUrl, locationUrl;
  17347 
  17348 			anchorUrl = anchor.href.replace( rhash, "" );
  17349 			locationUrl = location.href.replace( rhash, "" );
  17350 
  17351 			// Decoding may throw an error if the URL isn't UTF-8 (#9518)
  17352 			try {
  17353 				anchorUrl = decodeURIComponent( anchorUrl );
  17354 			} catch ( error ) {}
  17355 			try {
  17356 				locationUrl = decodeURIComponent( locationUrl );
  17357 			} catch ( error ) {}
  17358 
  17359 			return anchor.hash.length > 1 && anchorUrl === locationUrl;
  17360 		};
  17361 	} )(),
  17362 
  17363 	_create: function() {
  17364 		var that = this,
  17365 			options = this.options;
  17366 
  17367 		this.running = false;
  17368 
  17369 		this._addClass( "ui-tabs", "ui-widget ui-widget-content" );
  17370 		this._toggleClass( "ui-tabs-collapsible", null, options.collapsible );
  17371 
  17372 		this._processTabs();
  17373 		options.active = this._initialActive();
  17374 
  17375 		// Take disabling tabs via class attribute from HTML
  17376 		// into account and update option properly.
  17377 		if ( $.isArray( options.disabled ) ) {
  17378 			options.disabled = $.unique( options.disabled.concat(
  17379 				$.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) {
  17380 					return that.tabs.index( li );
  17381 				} )
  17382 			) ).sort();
  17383 		}
  17384 
  17385 		// Check for length avoids error when initializing empty list
  17386 		if ( this.options.active !== false && this.anchors.length ) {
  17387 			this.active = this._findActive( options.active );
  17388 		} else {
  17389 			this.active = $();
  17390 		}
  17391 
  17392 		this._refresh();
  17393 
  17394 		if ( this.active.length ) {
  17395 			this.load( options.active );
  17396 		}
  17397 	},
  17398 
  17399 	_initialActive: function() {
  17400 		var active = this.options.active,
  17401 			collapsible = this.options.collapsible,
  17402 			locationHash = location.hash.substring( 1 );
  17403 
  17404 		if ( active === null ) {
  17405 
  17406 			// check the fragment identifier in the URL
  17407 			if ( locationHash ) {
  17408 				this.tabs.each( function( i, tab ) {
  17409 					if ( $( tab ).attr( "aria-controls" ) === locationHash ) {
  17410 						active = i;
  17411 						return false;
  17412 					}
  17413 				} );
  17414 			}
  17415 
  17416 			// Check for a tab marked active via a class
  17417 			if ( active === null ) {
  17418 				active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) );
  17419 			}
  17420 
  17421 			// No active tab, set to false
  17422 			if ( active === null || active === -1 ) {
  17423 				active = this.tabs.length ? 0 : false;
  17424 			}
  17425 		}
  17426 
  17427 		// Handle numbers: negative, out of range
  17428 		if ( active !== false ) {
  17429 			active = this.tabs.index( this.tabs.eq( active ) );
  17430 			if ( active === -1 ) {
  17431 				active = collapsible ? false : 0;
  17432 			}
  17433 		}
  17434 
  17435 		// Don't allow collapsible: false and active: false
  17436 		if ( !collapsible && active === false && this.anchors.length ) {
  17437 			active = 0;
  17438 		}
  17439 
  17440 		return active;
  17441 	},
  17442 
  17443 	_getCreateEventData: function() {
  17444 		return {
  17445 			tab: this.active,
  17446 			panel: !this.active.length ? $() : this._getPanelForTab( this.active )
  17447 		};
  17448 	},
  17449 
  17450 	_tabKeydown: function( event ) {
  17451 		var focusedTab = $( $.ui.safeActiveElement( this.document[ 0 ] ) ).closest( "li" ),
  17452 			selectedIndex = this.tabs.index( focusedTab ),
  17453 			goingForward = true;
  17454 
  17455 		if ( this._handlePageNav( event ) ) {
  17456 			return;
  17457 		}
  17458 
  17459 		switch ( event.keyCode ) {
  17460 		case $.ui.keyCode.RIGHT:
  17461 		case $.ui.keyCode.DOWN:
  17462 			selectedIndex++;
  17463 			break;
  17464 		case $.ui.keyCode.UP:
  17465 		case $.ui.keyCode.LEFT:
  17466 			goingForward = false;
  17467 			selectedIndex--;
  17468 			break;
  17469 		case $.ui.keyCode.END:
  17470 			selectedIndex = this.anchors.length - 1;
  17471 			break;
  17472 		case $.ui.keyCode.HOME:
  17473 			selectedIndex = 0;
  17474 			break;
  17475 		case $.ui.keyCode.SPACE:
  17476 
  17477 			// Activate only, no collapsing
  17478 			event.preventDefault();
  17479 			clearTimeout( this.activating );
  17480 			this._activate( selectedIndex );
  17481 			return;
  17482 		case $.ui.keyCode.ENTER:
  17483 
  17484 			// Toggle (cancel delayed activation, allow collapsing)
  17485 			event.preventDefault();
  17486 			clearTimeout( this.activating );
  17487 
  17488 			// Determine if we should collapse or activate
  17489 			this._activate( selectedIndex === this.options.active ? false : selectedIndex );
  17490 			return;
  17491 		default:
  17492 			return;
  17493 		}
  17494 
  17495 		// Focus the appropriate tab, based on which key was pressed
  17496 		event.preventDefault();
  17497 		clearTimeout( this.activating );
  17498 		selectedIndex = this._focusNextTab( selectedIndex, goingForward );
  17499 
  17500 		// Navigating with control/command key will prevent automatic activation
  17501 		if ( !event.ctrlKey && !event.metaKey ) {
  17502 
  17503 			// Update aria-selected immediately so that AT think the tab is already selected.
  17504 			// Otherwise AT may confuse the user by stating that they need to activate the tab,
  17505 			// but the tab will already be activated by the time the announcement finishes.
  17506 			focusedTab.attr( "aria-selected", "false" );
  17507 			this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" );
  17508 
  17509 			this.activating = this._delay( function() {
  17510 				this.option( "active", selectedIndex );
  17511 			}, this.delay );
  17512 		}
  17513 	},
  17514 
  17515 	_panelKeydown: function( event ) {
  17516 		if ( this._handlePageNav( event ) ) {
  17517 			return;
  17518 		}
  17519 
  17520 		// Ctrl+up moves focus to the current tab
  17521 		if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) {
  17522 			event.preventDefault();
  17523 			this.active.trigger( "focus" );
  17524 		}
  17525 	},
  17526 
  17527 	// Alt+page up/down moves focus to the previous/next tab (and activates)
  17528 	_handlePageNav: function( event ) {
  17529 		if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) {
  17530 			this._activate( this._focusNextTab( this.options.active - 1, false ) );
  17531 			return true;
  17532 		}
  17533 		if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) {
  17534 			this._activate( this._focusNextTab( this.options.active + 1, true ) );
  17535 			return true;
  17536 		}
  17537 	},
  17538 
  17539 	_findNextTab: function( index, goingForward ) {
  17540 		var lastTabIndex = this.tabs.length - 1;
  17541 
  17542 		function constrain() {
  17543 			if ( index > lastTabIndex ) {
  17544 				index = 0;
  17545 			}
  17546 			if ( index < 0 ) {
  17547 				index = lastTabIndex;
  17548 			}
  17549 			return index;
  17550 		}
  17551 
  17552 		while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) {
  17553 			index = goingForward ? index + 1 : index - 1;
  17554 		}
  17555 
  17556 		return index;
  17557 	},
  17558 
  17559 	_focusNextTab: function( index, goingForward ) {
  17560 		index = this._findNextTab( index, goingForward );
  17561 		this.tabs.eq( index ).trigger( "focus" );
  17562 		return index;
  17563 	},
  17564 
  17565 	_setOption: function( key, value ) {
  17566 		if ( key === "active" ) {
  17567 
  17568 			// _activate() will handle invalid values and update this.options
  17569 			this._activate( value );
  17570 			return;
  17571 		}
  17572 
  17573 		this._super( key, value );
  17574 
  17575 		if ( key === "collapsible" ) {
  17576 			this._toggleClass( "ui-tabs-collapsible", null, value );
  17577 
  17578 			// Setting collapsible: false while collapsed; open first panel
  17579 			if ( !value && this.options.active === false ) {
  17580 				this._activate( 0 );
  17581 			}
  17582 		}
  17583 
  17584 		if ( key === "event" ) {
  17585 			this._setupEvents( value );
  17586 		}
  17587 
  17588 		if ( key === "heightStyle" ) {
  17589 			this._setupHeightStyle( value );
  17590 		}
  17591 	},
  17592 
  17593 	_sanitizeSelector: function( hash ) {
  17594 		return hash ? hash.replace( /[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&" ) : "";
  17595 	},
  17596 
  17597 	refresh: function() {
  17598 		var options = this.options,
  17599 			lis = this.tablist.children( ":has(a[href])" );
  17600 
  17601 		// Get disabled tabs from class attribute from HTML
  17602 		// this will get converted to a boolean if needed in _refresh()
  17603 		options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) {
  17604 			return lis.index( tab );
  17605 		} );
  17606 
  17607 		this._processTabs();
  17608 
  17609 		// Was collapsed or no tabs
  17610 		if ( options.active === false || !this.anchors.length ) {
  17611 			options.active = false;
  17612 			this.active = $();
  17613 
  17614 		// was active, but active tab is gone
  17615 		} else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) {
  17616 
  17617 			// all remaining tabs are disabled
  17618 			if ( this.tabs.length === options.disabled.length ) {
  17619 				options.active = false;
  17620 				this.active = $();
  17621 
  17622 			// activate previous tab
  17623 			} else {
  17624 				this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) );
  17625 			}
  17626 
  17627 		// was active, active tab still exists
  17628 		} else {
  17629 
  17630 			// make sure active index is correct
  17631 			options.active = this.tabs.index( this.active );
  17632 		}
  17633 
  17634 		this._refresh();
  17635 	},
  17636 
  17637 	_refresh: function() {
  17638 		this._setOptionDisabled( this.options.disabled );
  17639 		this._setupEvents( this.options.event );
  17640 		this._setupHeightStyle( this.options.heightStyle );
  17641 
  17642 		this.tabs.not( this.active ).attr( {
  17643 			"aria-selected": "false",
  17644 			"aria-expanded": "false",
  17645 			tabIndex: -1
  17646 		} );
  17647 		this.panels.not( this._getPanelForTab( this.active ) )
  17648 			.hide()
  17649 			.attr( {
  17650 				"aria-hidden": "true"
  17651 			} );
  17652 
  17653 		// Make sure one tab is in the tab order
  17654 		if ( !this.active.length ) {
  17655 			this.tabs.eq( 0 ).attr( "tabIndex", 0 );
  17656 		} else {
  17657 			this.active
  17658 				.attr( {
  17659 					"aria-selected": "true",
  17660 					"aria-expanded": "true",
  17661 					tabIndex: 0
  17662 				} );
  17663 			this._addClass( this.active, "ui-tabs-active", "ui-state-active" );
  17664 			this._getPanelForTab( this.active )
  17665 				.show()
  17666 				.attr( {
  17667 					"aria-hidden": "false"
  17668 				} );
  17669 		}
  17670 	},
  17671 
  17672 	_processTabs: function() {
  17673 		var that = this,
  17674 			prevTabs = this.tabs,
  17675 			prevAnchors = this.anchors,
  17676 			prevPanels = this.panels;
  17677 
  17678 		this.tablist = this._getList().attr( "role", "tablist" );
  17679 		this._addClass( this.tablist, "ui-tabs-nav",
  17680 			"ui-helper-reset ui-helper-clearfix ui-widget-header" );
  17681 
  17682 		// Prevent users from focusing disabled tabs via click
  17683 		this.tablist
  17684 			.on( "mousedown" + this.eventNamespace, "> li", function( event ) {
  17685 				if ( $( this ).is( ".ui-state-disabled" ) ) {
  17686 					event.preventDefault();
  17687 				}
  17688 			} )
  17689 
  17690 			// Support: IE <9
  17691 			// Preventing the default action in mousedown doesn't prevent IE
  17692 			// from focusing the element, so if the anchor gets focused, blur.
  17693 			// We don't have to worry about focusing the previously focused
  17694 			// element since clicking on a non-focusable element should focus
  17695 			// the body anyway.
  17696 			.on( "focus" + this.eventNamespace, ".ui-tabs-anchor", function() {
  17697 				if ( $( this ).closest( "li" ).is( ".ui-state-disabled" ) ) {
  17698 					this.blur();
  17699 				}
  17700 			} );
  17701 
  17702 		this.tabs = this.tablist.find( "> li:has(a[href])" )
  17703 			.attr( {
  17704 				role: "tab",
  17705 				tabIndex: -1
  17706 			} );
  17707 		this._addClass( this.tabs, "ui-tabs-tab", "ui-state-default" );
  17708 
  17709 		this.anchors = this.tabs.map( function() {
  17710 			return $( "a", this )[ 0 ];
  17711 		} )
  17712 			.attr( {
  17713 				role: "presentation",
  17714 				tabIndex: -1
  17715 			} );
  17716 		this._addClass( this.anchors, "ui-tabs-anchor" );
  17717 
  17718 		this.panels = $();
  17719 
  17720 		this.anchors.each( function( i, anchor ) {
  17721 			var selector, panel, panelId,
  17722 				anchorId = $( anchor ).uniqueId().attr( "id" ),
  17723 				tab = $( anchor ).closest( "li" ),
  17724 				originalAriaControls = tab.attr( "aria-controls" );
  17725 
  17726 			// Inline tab
  17727 			if ( that._isLocal( anchor ) ) {
  17728 				selector = anchor.hash;
  17729 				panelId = selector.substring( 1 );
  17730 				panel = that.element.find( that._sanitizeSelector( selector ) );
  17731 
  17732 			// remote tab
  17733 			} else {
  17734 
  17735 				// If the tab doesn't already have aria-controls,
  17736 				// generate an id by using a throw-away element
  17737 				panelId = tab.attr( "aria-controls" ) || $( {} ).uniqueId()[ 0 ].id;
  17738 				selector = "#" + panelId;
  17739 				panel = that.element.find( selector );
  17740 				if ( !panel.length ) {
  17741 					panel = that._createPanel( panelId );
  17742 					panel.insertAfter( that.panels[ i - 1 ] || that.tablist );
  17743 				}
  17744 				panel.attr( "aria-live", "polite" );
  17745 			}
  17746 
  17747 			if ( panel.length ) {
  17748 				that.panels = that.panels.add( panel );
  17749 			}
  17750 			if ( originalAriaControls ) {
  17751 				tab.data( "ui-tabs-aria-controls", originalAriaControls );
  17752 			}
  17753 			tab.attr( {
  17754 				"aria-controls": panelId,
  17755 				"aria-labelledby": anchorId
  17756 			} );
  17757 			panel.attr( "aria-labelledby", anchorId );
  17758 		} );
  17759 
  17760 		this.panels.attr( "role", "tabpanel" );
  17761 		this._addClass( this.panels, "ui-tabs-panel", "ui-widget-content" );
  17762 
  17763 		// Avoid memory leaks (#10056)
  17764 		if ( prevTabs ) {
  17765 			this._off( prevTabs.not( this.tabs ) );
  17766 			this._off( prevAnchors.not( this.anchors ) );
  17767 			this._off( prevPanels.not( this.panels ) );
  17768 		}
  17769 	},
  17770 
  17771 	// Allow overriding how to find the list for rare usage scenarios (#7715)
  17772 	_getList: function() {
  17773 		return this.tablist || this.element.find( "ol, ul" ).eq( 0 );
  17774 	},
  17775 
  17776 	_createPanel: function( id ) {
  17777 		return $( "<div>" )
  17778 			.attr( "id", id )
  17779 			.data( "ui-tabs-destroy", true );
  17780 	},
  17781 
  17782 	_setOptionDisabled: function( disabled ) {
  17783 		var currentItem, li, i;
  17784 
  17785 		if ( $.isArray( disabled ) ) {
  17786 			if ( !disabled.length ) {
  17787 				disabled = false;
  17788 			} else if ( disabled.length === this.anchors.length ) {
  17789 				disabled = true;
  17790 			}
  17791 		}
  17792 
  17793 		// Disable tabs
  17794 		for ( i = 0; ( li = this.tabs[ i ] ); i++ ) {
  17795 			currentItem = $( li );
  17796 			if ( disabled === true || $.inArray( i, disabled ) !== -1 ) {
  17797 				currentItem.attr( "aria-disabled", "true" );
  17798 				this._addClass( currentItem, null, "ui-state-disabled" );
  17799 			} else {
  17800 				currentItem.removeAttr( "aria-disabled" );
  17801 				this._removeClass( currentItem, null, "ui-state-disabled" );
  17802 			}
  17803 		}
  17804 
  17805 		this.options.disabled = disabled;
  17806 
  17807 		this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null,
  17808 			disabled === true );
  17809 	},
  17810 
  17811 	_setupEvents: function( event ) {
  17812 		var events = {};
  17813 		if ( event ) {
  17814 			$.each( event.split( " " ), function( index, eventName ) {
  17815 				events[ eventName ] = "_eventHandler";
  17816 			} );
  17817 		}
  17818 
  17819 		this._off( this.anchors.add( this.tabs ).add( this.panels ) );
  17820 
  17821 		// Always prevent the default action, even when disabled
  17822 		this._on( true, this.anchors, {
  17823 			click: function( event ) {
  17824 				event.preventDefault();
  17825 			}
  17826 		} );
  17827 		this._on( this.anchors, events );
  17828 		this._on( this.tabs, { keydown: "_tabKeydown" } );
  17829 		this._on( this.panels, { keydown: "_panelKeydown" } );
  17830 
  17831 		this._focusable( this.tabs );
  17832 		this._hoverable( this.tabs );
  17833 	},
  17834 
  17835 	_setupHeightStyle: function( heightStyle ) {
  17836 		var maxHeight,
  17837 			parent = this.element.parent();
  17838 
  17839 		if ( heightStyle === "fill" ) {
  17840 			maxHeight = parent.height();
  17841 			maxHeight -= this.element.outerHeight() - this.element.height();
  17842 
  17843 			this.element.siblings( ":visible" ).each( function() {
  17844 				var elem = $( this ),
  17845 					position = elem.css( "position" );
  17846 
  17847 				if ( position === "absolute" || position === "fixed" ) {
  17848 					return;
  17849 				}
  17850 				maxHeight -= elem.outerHeight( true );
  17851 			} );
  17852 
  17853 			this.element.children().not( this.panels ).each( function() {
  17854 				maxHeight -= $( this ).outerHeight( true );
  17855 			} );
  17856 
  17857 			this.panels.each( function() {
  17858 				$( this ).height( Math.max( 0, maxHeight -
  17859 					$( this ).innerHeight() + $( this ).height() ) );
  17860 			} )
  17861 				.css( "overflow", "auto" );
  17862 		} else if ( heightStyle === "auto" ) {
  17863 			maxHeight = 0;
  17864 			this.panels.each( function() {
  17865 				maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
  17866 			} ).height( maxHeight );
  17867 		}
  17868 	},
  17869 
  17870 	_eventHandler: function( event ) {
  17871 		var options = this.options,
  17872 			active = this.active,
  17873 			anchor = $( event.currentTarget ),
  17874 			tab = anchor.closest( "li" ),
  17875 			clickedIsActive = tab[ 0 ] === active[ 0 ],
  17876 			collapsing = clickedIsActive && options.collapsible,
  17877 			toShow = collapsing ? $() : this._getPanelForTab( tab ),
  17878 			toHide = !active.length ? $() : this._getPanelForTab( active ),
  17879 			eventData = {
  17880 				oldTab: active,
  17881 				oldPanel: toHide,
  17882 				newTab: collapsing ? $() : tab,
  17883 				newPanel: toShow
  17884 			};
  17885 
  17886 		event.preventDefault();
  17887 
  17888 		if ( tab.hasClass( "ui-state-disabled" ) ||
  17889 
  17890 				// tab is already loading
  17891 				tab.hasClass( "ui-tabs-loading" ) ||
  17892 
  17893 				// can't switch durning an animation
  17894 				this.running ||
  17895 
  17896 				// click on active header, but not collapsible
  17897 				( clickedIsActive && !options.collapsible ) ||
  17898 
  17899 				// allow canceling activation
  17900 				( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
  17901 			return;
  17902 		}
  17903 
  17904 		options.active = collapsing ? false : this.tabs.index( tab );
  17905 
  17906 		this.active = clickedIsActive ? $() : tab;
  17907 		if ( this.xhr ) {
  17908 			this.xhr.abort();
  17909 		}
  17910 
  17911 		if ( !toHide.length && !toShow.length ) {
  17912 			$.error( "jQuery UI Tabs: Mismatching fragment identifier." );
  17913 		}
  17914 
  17915 		if ( toShow.length ) {
  17916 			this.load( this.tabs.index( tab ), event );
  17917 		}
  17918 		this._toggle( event, eventData );
  17919 	},
  17920 
  17921 	// Handles show/hide for selecting tabs
  17922 	_toggle: function( event, eventData ) {
  17923 		var that = this,
  17924 			toShow = eventData.newPanel,
  17925 			toHide = eventData.oldPanel;
  17926 
  17927 		this.running = true;
  17928 
  17929 		function complete() {
  17930 			that.running = false;
  17931 			that._trigger( "activate", event, eventData );
  17932 		}
  17933 
  17934 		function show() {
  17935 			that._addClass( eventData.newTab.closest( "li" ), "ui-tabs-active", "ui-state-active" );
  17936 
  17937 			if ( toShow.length && that.options.show ) {
  17938 				that._show( toShow, that.options.show, complete );
  17939 			} else {
  17940 				toShow.show();
  17941 				complete();
  17942 			}
  17943 		}
  17944 
  17945 		// Start out by hiding, then showing, then completing
  17946 		if ( toHide.length && this.options.hide ) {
  17947 			this._hide( toHide, this.options.hide, function() {
  17948 				that._removeClass( eventData.oldTab.closest( "li" ),
  17949 					"ui-tabs-active", "ui-state-active" );
  17950 				show();
  17951 			} );
  17952 		} else {
  17953 			this._removeClass( eventData.oldTab.closest( "li" ),
  17954 				"ui-tabs-active", "ui-state-active" );
  17955 			toHide.hide();
  17956 			show();
  17957 		}
  17958 
  17959 		toHide.attr( "aria-hidden", "true" );
  17960 		eventData.oldTab.attr( {
  17961 			"aria-selected": "false",
  17962 			"aria-expanded": "false"
  17963 		} );
  17964 
  17965 		// If we're switching tabs, remove the old tab from the tab order.
  17966 		// If we're opening from collapsed state, remove the previous tab from the tab order.
  17967 		// If we're collapsing, then keep the collapsing tab in the tab order.
  17968 		if ( toShow.length && toHide.length ) {
  17969 			eventData.oldTab.attr( "tabIndex", -1 );
  17970 		} else if ( toShow.length ) {
  17971 			this.tabs.filter( function() {
  17972 				return $( this ).attr( "tabIndex" ) === 0;
  17973 			} )
  17974 				.attr( "tabIndex", -1 );
  17975 		}
  17976 
  17977 		toShow.attr( "aria-hidden", "false" );
  17978 		eventData.newTab.attr( {
  17979 			"aria-selected": "true",
  17980 			"aria-expanded": "true",
  17981 			tabIndex: 0
  17982 		} );
  17983 	},
  17984 
  17985 	_activate: function( index ) {
  17986 		var anchor,
  17987 			active = this._findActive( index );
  17988 
  17989 		// Trying to activate the already active panel
  17990 		if ( active[ 0 ] === this.active[ 0 ] ) {
  17991 			return;
  17992 		}
  17993 
  17994 		// Trying to collapse, simulate a click on the current active header
  17995 		if ( !active.length ) {
  17996 			active = this.active;
  17997 		}
  17998 
  17999 		anchor = active.find( ".ui-tabs-anchor" )[ 0 ];
  18000 		this._eventHandler( {
  18001 			target: anchor,
  18002 			currentTarget: anchor,
  18003 			preventDefault: $.noop
  18004 		} );
  18005 	},
  18006 
  18007 	_findActive: function( index ) {
  18008 		return index === false ? $() : this.tabs.eq( index );
  18009 	},
  18010 
  18011 	_getIndex: function( index ) {
  18012 
  18013 		// meta-function to give users option to provide a href string instead of a numerical index.
  18014 		if ( typeof index === "string" ) {
  18015 			index = this.anchors.index( this.anchors.filter( "[href$='" +
  18016 				$.ui.escapeSelector( index ) + "']" ) );
  18017 		}
  18018 
  18019 		return index;
  18020 	},
  18021 
  18022 	_destroy: function() {
  18023 		if ( this.xhr ) {
  18024 			this.xhr.abort();
  18025 		}
  18026 
  18027 		this.tablist
  18028 			.removeAttr( "role" )
  18029 			.off( this.eventNamespace );
  18030 
  18031 		this.anchors
  18032 			.removeAttr( "role tabIndex" )
  18033 			.removeUniqueId();
  18034 
  18035 		this.tabs.add( this.panels ).each( function() {
  18036 			if ( $.data( this, "ui-tabs-destroy" ) ) {
  18037 				$( this ).remove();
  18038 			} else {
  18039 				$( this ).removeAttr( "role tabIndex " +
  18040 					"aria-live aria-busy aria-selected aria-labelledby aria-hidden aria-expanded" );
  18041 			}
  18042 		} );
  18043 
  18044 		this.tabs.each( function() {
  18045 			var li = $( this ),
  18046 				prev = li.data( "ui-tabs-aria-controls" );
  18047 			if ( prev ) {
  18048 				li
  18049 					.attr( "aria-controls", prev )
  18050 					.removeData( "ui-tabs-aria-controls" );
  18051 			} else {
  18052 				li.removeAttr( "aria-controls" );
  18053 			}
  18054 		} );
  18055 
  18056 		this.panels.show();
  18057 
  18058 		if ( this.options.heightStyle !== "content" ) {
  18059 			this.panels.css( "height", "" );
  18060 		}
  18061 	},
  18062 
  18063 	enable: function( index ) {
  18064 		var disabled = this.options.disabled;
  18065 		if ( disabled === false ) {
  18066 			return;
  18067 		}
  18068 
  18069 		if ( index === undefined ) {
  18070 			disabled = false;
  18071 		} else {
  18072 			index = this._getIndex( index );
  18073 			if ( $.isArray( disabled ) ) {
  18074 				disabled = $.map( disabled, function( num ) {
  18075 					return num !== index ? num : null;
  18076 				} );
  18077 			} else {
  18078 				disabled = $.map( this.tabs, function( li, num ) {
  18079 					return num !== index ? num : null;
  18080 				} );
  18081 			}
  18082 		}
  18083 		this._setOptionDisabled( disabled );
  18084 	},
  18085 
  18086 	disable: function( index ) {
  18087 		var disabled = this.options.disabled;
  18088 		if ( disabled === true ) {
  18089 			return;
  18090 		}
  18091 
  18092 		if ( index === undefined ) {
  18093 			disabled = true;
  18094 		} else {
  18095 			index = this._getIndex( index );
  18096 			if ( $.inArray( index, disabled ) !== -1 ) {
  18097 				return;
  18098 			}
  18099 			if ( $.isArray( disabled ) ) {
  18100 				disabled = $.merge( [ index ], disabled ).sort();
  18101 			} else {
  18102 				disabled = [ index ];
  18103 			}
  18104 		}
  18105 		this._setOptionDisabled( disabled );
  18106 	},
  18107 
  18108 	load: function( index, event ) {
  18109 		index = this._getIndex( index );
  18110 		var that = this,
  18111 			tab = this.tabs.eq( index ),
  18112 			anchor = tab.find( ".ui-tabs-anchor" ),
  18113 			panel = this._getPanelForTab( tab ),
  18114 			eventData = {
  18115 				tab: tab,
  18116 				panel: panel
  18117 			},
  18118 			complete = function( jqXHR, status ) {
  18119 				if ( status === "abort" ) {
  18120 					that.panels.stop( false, true );
  18121 				}
  18122 
  18123 				that._removeClass( tab, "ui-tabs-loading" );
  18124 				panel.removeAttr( "aria-busy" );
  18125 
  18126 				if ( jqXHR === that.xhr ) {
  18127 					delete that.xhr;
  18128 				}
  18129 			};
  18130 
  18131 		// Not remote
  18132 		if ( this._isLocal( anchor[ 0 ] ) ) {
  18133 			return;
  18134 		}
  18135 
  18136 		this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) );
  18137 
  18138 		// Support: jQuery <1.8
  18139 		// jQuery <1.8 returns false if the request is canceled in beforeSend,
  18140 		// but as of 1.8, $.ajax() always returns a jqXHR object.
  18141 		if ( this.xhr && this.xhr.statusText !== "canceled" ) {
  18142 			this._addClass( tab, "ui-tabs-loading" );
  18143 			panel.attr( "aria-busy", "true" );
  18144 
  18145 			this.xhr
  18146 				.done( function( response, status, jqXHR ) {
  18147 
  18148 					// support: jQuery <1.8
  18149 					// http://bugs.jquery.com/ticket/11778
  18150 					setTimeout( function() {
  18151 						panel.html( response );
  18152 						that._trigger( "load", event, eventData );
  18153 
  18154 						complete( jqXHR, status );
  18155 					}, 1 );
  18156 				} )
  18157 				.fail( function( jqXHR, status ) {
  18158 
  18159 					// support: jQuery <1.8
  18160 					// http://bugs.jquery.com/ticket/11778
  18161 					setTimeout( function() {
  18162 						complete( jqXHR, status );
  18163 					}, 1 );
  18164 				} );
  18165 		}
  18166 	},
  18167 
  18168 	_ajaxSettings: function( anchor, event, eventData ) {
  18169 		var that = this;
  18170 		return {
  18171 
  18172 			// Support: IE <11 only
  18173 			// Strip any hash that exists to prevent errors with the Ajax request
  18174 			url: anchor.attr( "href" ).replace( /#.*$/, "" ),
  18175 			beforeSend: function( jqXHR, settings ) {
  18176 				return that._trigger( "beforeLoad", event,
  18177 					$.extend( { jqXHR: jqXHR, ajaxSettings: settings }, eventData ) );
  18178 			}
  18179 		};
  18180 	},
  18181 
  18182 	_getPanelForTab: function( tab ) {
  18183 		var id = $( tab ).attr( "aria-controls" );
  18184 		return this.element.find( this._sanitizeSelector( "#" + id ) );
  18185 	}
  18186 } );
  18187 
  18188 // DEPRECATED
  18189 // TODO: Switch return back to widget declaration at top of file when this is removed
  18190 if ( $.uiBackCompat !== false ) {
  18191 
  18192 	// Backcompat for ui-tab class (now ui-tabs-tab)
  18193 	$.widget( "ui.tabs", $.ui.tabs, {
  18194 		_processTabs: function() {
  18195 			this._superApply( arguments );
  18196 			this._addClass( this.tabs, "ui-tab" );
  18197 		}
  18198 	} );
  18199 }
  18200 
  18201 var widgetsTabs = $.ui.tabs;
  18202 
  18203 
  18204 /*!
  18205  * jQuery UI Tooltip 1.12.1
  18206  * http://jqueryui.com
  18207  *
  18208  * Copyright jQuery Foundation and other contributors
  18209  * Released under the MIT license.
  18210  * http://jquery.org/license
  18211  */
  18212 
  18213 //>>label: Tooltip
  18214 //>>group: Widgets
  18215 //>>description: Shows additional information for any element on hover or focus.
  18216 //>>docs: http://api.jqueryui.com/tooltip/
  18217 //>>demos: http://jqueryui.com/tooltip/
  18218 //>>css.structure: ../../themes/base/core.css
  18219 //>>css.structure: ../../themes/base/tooltip.css
  18220 //>>css.theme: ../../themes/base/theme.css
  18221 
  18222 
  18223 
  18224 $.widget( "ui.tooltip", {
  18225 	version: "1.12.1",
  18226 	options: {
  18227 		classes: {
  18228 			"ui-tooltip": "ui-corner-all ui-widget-shadow"
  18229 		},
  18230 		content: function() {
  18231 
  18232 			// support: IE<9, Opera in jQuery <1.7
  18233 			// .text() can't accept undefined, so coerce to a string
  18234 			var title = $( this ).attr( "title" ) || "";
  18235 
  18236 			// Escape title, since we're going from an attribute to raw HTML
  18237 			return $( "<a>" ).text( title ).html();
  18238 		},
  18239 		hide: true,
  18240 
  18241 		// Disabled elements have inconsistent behavior across browsers (#8661)
  18242 		items: "[title]:not([disabled])",
  18243 		position: {
  18244 			my: "left top+15",
  18245 			at: "left bottom",
  18246 			collision: "flipfit flip"
  18247 		},
  18248 		show: true,
  18249 		track: false,
  18250 
  18251 		// Callbacks
  18252 		close: null,
  18253 		open: null
  18254 	},
  18255 
  18256 	_addDescribedBy: function( elem, id ) {
  18257 		var describedby = ( elem.attr( "aria-describedby" ) || "" ).split( /\s+/ );
  18258 		describedby.push( id );
  18259 		elem
  18260 			.data( "ui-tooltip-id", id )
  18261 			.attr( "aria-describedby", $.trim( describedby.join( " " ) ) );
  18262 	},
  18263 
  18264 	_removeDescribedBy: function( elem ) {
  18265 		var id = elem.data( "ui-tooltip-id" ),
  18266 			describedby = ( elem.attr( "aria-describedby" ) || "" ).split( /\s+/ ),
  18267 			index = $.inArray( id, describedby );
  18268 
  18269 		if ( index !== -1 ) {
  18270 			describedby.splice( index, 1 );
  18271 		}
  18272 
  18273 		elem.removeData( "ui-tooltip-id" );
  18274 		describedby = $.trim( describedby.join( " " ) );
  18275 		if ( describedby ) {
  18276 			elem.attr( "aria-describedby", describedby );
  18277 		} else {
  18278 			elem.removeAttr( "aria-describedby" );
  18279 		}
  18280 	},
  18281 
  18282 	_create: function() {
  18283 		this._on( {
  18284 			mouseover: "open",
  18285 			focusin: "open"
  18286 		} );
  18287 
  18288 		// IDs of generated tooltips, needed for destroy
  18289 		this.tooltips = {};
  18290 
  18291 		// IDs of parent tooltips where we removed the title attribute
  18292 		this.parents = {};
  18293 
  18294 		// Append the aria-live region so tooltips announce correctly
  18295 		this.liveRegion = $( "<div>" )
  18296 			.attr( {
  18297 				role: "log",
  18298 				"aria-live": "assertive",
  18299 				"aria-relevant": "additions"
  18300 			} )
  18301 			.appendTo( this.document[ 0 ].body );
  18302 		this._addClass( this.liveRegion, null, "ui-helper-hidden-accessible" );
  18303 
  18304 		this.disabledTitles = $( [] );
  18305 	},
  18306 
  18307 	_setOption: function( key, value ) {
  18308 		var that = this;
  18309 
  18310 		this._super( key, value );
  18311 
  18312 		if ( key === "content" ) {
  18313 			$.each( this.tooltips, function( id, tooltipData ) {
  18314 				that._updateContent( tooltipData.element );
  18315 			} );
  18316 		}
  18317 	},
  18318 
  18319 	_setOptionDisabled: function( value ) {
  18320 		this[ value ? "_disable" : "_enable" ]();
  18321 	},
  18322 
  18323 	_disable: function() {
  18324 		var that = this;
  18325 
  18326 		// Close open tooltips
  18327 		$.each( this.tooltips, function( id, tooltipData ) {
  18328 			var event = $.Event( "blur" );
  18329 			event.target = event.currentTarget = tooltipData.element[ 0 ];
  18330 			that.close( event, true );
  18331 		} );
  18332 
  18333 		// Remove title attributes to prevent native tooltips
  18334 		this.disabledTitles = this.disabledTitles.add(
  18335 			this.element.find( this.options.items ).addBack()
  18336 				.filter( function() {
  18337 					var element = $( this );
  18338 					if ( element.is( "[title]" ) ) {
  18339 						return element
  18340 							.data( "ui-tooltip-title", element.attr( "title" ) )
  18341 							.removeAttr( "title" );
  18342 					}
  18343 				} )
  18344 		);
  18345 	},
  18346 
  18347 	_enable: function() {
  18348 
  18349 		// restore title attributes
  18350 		this.disabledTitles.each( function() {
  18351 			var element = $( this );
  18352 			if ( element.data( "ui-tooltip-title" ) ) {
  18353 				element.attr( "title", element.data( "ui-tooltip-title" ) );
  18354 			}
  18355 		} );
  18356 		this.disabledTitles = $( [] );
  18357 	},
  18358 
  18359 	open: function( event ) {
  18360 		var that = this,
  18361 			target = $( event ? event.target : this.element )
  18362 
  18363 				// we need closest here due to mouseover bubbling,
  18364 				// but always pointing at the same event target
  18365 				.closest( this.options.items );
  18366 
  18367 		// No element to show a tooltip for or the tooltip is already open
  18368 		if ( !target.length || target.data( "ui-tooltip-id" ) ) {
  18369 			return;
  18370 		}
  18371 
  18372 		if ( target.attr( "title" ) ) {
  18373 			target.data( "ui-tooltip-title", target.attr( "title" ) );
  18374 		}
  18375 
  18376 		target.data( "ui-tooltip-open", true );
  18377 
  18378 		// Kill parent tooltips, custom or native, for hover
  18379 		if ( event && event.type === "mouseover" ) {
  18380 			target.parents().each( function() {
  18381 				var parent = $( this ),
  18382 					blurEvent;
  18383 				if ( parent.data( "ui-tooltip-open" ) ) {
  18384 					blurEvent = $.Event( "blur" );
  18385 					blurEvent.target = blurEvent.currentTarget = this;
  18386 					that.close( blurEvent, true );
  18387 				}
  18388 				if ( parent.attr( "title" ) ) {
  18389 					parent.uniqueId();
  18390 					that.parents[ this.id ] = {
  18391 						element: this,
  18392 						title: parent.attr( "title" )
  18393 					};
  18394 					parent.attr( "title", "" );
  18395 				}
  18396 			} );
  18397 		}
  18398 
  18399 		this._registerCloseHandlers( event, target );
  18400 		this._updateContent( target, event );
  18401 	},
  18402 
  18403 	_updateContent: function( target, event ) {
  18404 		var content,
  18405 			contentOption = this.options.content,
  18406 			that = this,
  18407 			eventType = event ? event.type : null;
  18408 
  18409 		if ( typeof contentOption === "string" || contentOption.nodeType ||
  18410 				contentOption.jquery ) {
  18411 			return this._open( event, target, contentOption );
  18412 		}
  18413 
  18414 		content = contentOption.call( target[ 0 ], function( response ) {
  18415 
  18416 			// IE may instantly serve a cached response for ajax requests
  18417 			// delay this call to _open so the other call to _open runs first
  18418 			that._delay( function() {
  18419 
  18420 				// Ignore async response if tooltip was closed already
  18421 				if ( !target.data( "ui-tooltip-open" ) ) {
  18422 					return;
  18423 				}
  18424 
  18425 				// JQuery creates a special event for focusin when it doesn't
  18426 				// exist natively. To improve performance, the native event
  18427 				// object is reused and the type is changed. Therefore, we can't
  18428 				// rely on the type being correct after the event finished
  18429 				// bubbling, so we set it back to the previous value. (#8740)
  18430 				if ( event ) {
  18431 					event.type = eventType;
  18432 				}
  18433 				this._open( event, target, response );
  18434 			} );
  18435 		} );
  18436 		if ( content ) {
  18437 			this._open( event, target, content );
  18438 		}
  18439 	},
  18440 
  18441 	_open: function( event, target, content ) {
  18442 		var tooltipData, tooltip, delayedShow, a11yContent,
  18443 			positionOption = $.extend( {}, this.options.position );
  18444 
  18445 		if ( !content ) {
  18446 			return;
  18447 		}
  18448 
  18449 		// Content can be updated multiple times. If the tooltip already
  18450 		// exists, then just update the content and bail.
  18451 		tooltipData = this._find( target );
  18452 		if ( tooltipData ) {
  18453 			tooltipData.tooltip.find( ".ui-tooltip-content" ).html( content );
  18454 			return;
  18455 		}
  18456 
  18457 		// If we have a title, clear it to prevent the native tooltip
  18458 		// we have to check first to avoid defining a title if none exists
  18459 		// (we don't want to cause an element to start matching [title])
  18460 		//
  18461 		// We use removeAttr only for key events, to allow IE to export the correct
  18462 		// accessible attributes. For mouse events, set to empty string to avoid
  18463 		// native tooltip showing up (happens only when removing inside mouseover).
  18464 		if ( target.is( "[title]" ) ) {
  18465 			if ( event && event.type === "mouseover" ) {
  18466 				target.attr( "title", "" );
  18467 			} else {
  18468 				target.removeAttr( "title" );
  18469 			}
  18470 		}
  18471 
  18472 		tooltipData = this._tooltip( target );
  18473 		tooltip = tooltipData.tooltip;
  18474 		this._addDescribedBy( target, tooltip.attr( "id" ) );
  18475 		tooltip.find( ".ui-tooltip-content" ).html( content );
  18476 
  18477 		// Support: Voiceover on OS X, JAWS on IE <= 9
  18478 		// JAWS announces deletions even when aria-relevant="additions"
  18479 		// Voiceover will sometimes re-read the entire log region's contents from the beginning
  18480 		this.liveRegion.children().hide();
  18481 		a11yContent = $( "<div>" ).html( tooltip.find( ".ui-tooltip-content" ).html() );
  18482 		a11yContent.removeAttr( "name" ).find( "[name]" ).removeAttr( "name" );
  18483 		a11yContent.removeAttr( "id" ).find( "[id]" ).removeAttr( "id" );
  18484 		a11yContent.appendTo( this.liveRegion );
  18485 
  18486 		function position( event ) {
  18487 			positionOption.of = event;
  18488 			if ( tooltip.is( ":hidden" ) ) {
  18489 				return;
  18490 			}
  18491 			tooltip.position( positionOption );
  18492 		}
  18493 		if ( this.options.track && event && /^mouse/.test( event.type ) ) {
  18494 			this._on( this.document, {
  18495 				mousemove: position
  18496 			} );
  18497 
  18498 			// trigger once to override element-relative positioning
  18499 			position( event );
  18500 		} else {
  18501 			tooltip.position( $.extend( {
  18502 				of: target
  18503 			}, this.options.position ) );
  18504 		}
  18505 
  18506 		tooltip.hide();
  18507 
  18508 		this._show( tooltip, this.options.show );
  18509 
  18510 		// Handle tracking tooltips that are shown with a delay (#8644). As soon
  18511 		// as the tooltip is visible, position the tooltip using the most recent
  18512 		// event.
  18513 		// Adds the check to add the timers only when both delay and track options are set (#14682)
  18514 		if ( this.options.track && this.options.show && this.options.show.delay ) {
  18515 			delayedShow = this.delayedShow = setInterval( function() {
  18516 				if ( tooltip.is( ":visible" ) ) {
  18517 					position( positionOption.of );
  18518 					clearInterval( delayedShow );
  18519 				}
  18520 			}, $.fx.interval );
  18521 		}
  18522 
  18523 		this._trigger( "open", event, { tooltip: tooltip } );
  18524 	},
  18525 
  18526 	_registerCloseHandlers: function( event, target ) {
  18527 		var events = {
  18528 			keyup: function( event ) {
  18529 				if ( event.keyCode === $.ui.keyCode.ESCAPE ) {
  18530 					var fakeEvent = $.Event( event );
  18531 					fakeEvent.currentTarget = target[ 0 ];
  18532 					this.close( fakeEvent, true );
  18533 				}
  18534 			}
  18535 		};
  18536 
  18537 		// Only bind remove handler for delegated targets. Non-delegated
  18538 		// tooltips will handle this in destroy.
  18539 		if ( target[ 0 ] !== this.element[ 0 ] ) {
  18540 			events.remove = function() {
  18541 				this._removeTooltip( this._find( target ).tooltip );
  18542 			};
  18543 		}
  18544 
  18545 		if ( !event || event.type === "mouseover" ) {
  18546 			events.mouseleave = "close";
  18547 		}
  18548 		if ( !event || event.type === "focusin" ) {
  18549 			events.focusout = "close";
  18550 		}
  18551 		this._on( true, target, events );
  18552 	},
  18553 
  18554 	close: function( event ) {
  18555 		var tooltip,
  18556 			that = this,
  18557 			target = $( event ? event.currentTarget : this.element ),
  18558 			tooltipData = this._find( target );
  18559 
  18560 		// The tooltip may already be closed
  18561 		if ( !tooltipData ) {
  18562 
  18563 			// We set ui-tooltip-open immediately upon open (in open()), but only set the
  18564 			// additional data once there's actually content to show (in _open()). So even if the
  18565 			// tooltip doesn't have full data, we always remove ui-tooltip-open in case we're in
  18566 			// the period between open() and _open().
  18567 			target.removeData( "ui-tooltip-open" );
  18568 			return;
  18569 		}
  18570 
  18571 		tooltip = tooltipData.tooltip;
  18572 
  18573 		// Disabling closes the tooltip, so we need to track when we're closing
  18574 		// to avoid an infinite loop in case the tooltip becomes disabled on close
  18575 		if ( tooltipData.closing ) {
  18576 			return;
  18577 		}
  18578 
  18579 		// Clear the interval for delayed tracking tooltips
  18580 		clearInterval( this.delayedShow );
  18581 
  18582 		// Only set title if we had one before (see comment in _open())
  18583 		// If the title attribute has changed since open(), don't restore
  18584 		if ( target.data( "ui-tooltip-title" ) && !target.attr( "title" ) ) {
  18585 			target.attr( "title", target.data( "ui-tooltip-title" ) );
  18586 		}
  18587 
  18588 		this._removeDescribedBy( target );
  18589 
  18590 		tooltipData.hiding = true;
  18591 		tooltip.stop( true );
  18592 		this._hide( tooltip, this.options.hide, function() {
  18593 			that._removeTooltip( $( this ) );
  18594 		} );
  18595 
  18596 		target.removeData( "ui-tooltip-open" );
  18597 		this._off( target, "mouseleave focusout keyup" );
  18598 
  18599 		// Remove 'remove' binding only on delegated targets
  18600 		if ( target[ 0 ] !== this.element[ 0 ] ) {
  18601 			this._off( target, "remove" );
  18602 		}
  18603 		this._off( this.document, "mousemove" );
  18604 
  18605 		if ( event && event.type === "mouseleave" ) {
  18606 			$.each( this.parents, function( id, parent ) {
  18607 				$( parent.element ).attr( "title", parent.title );
  18608 				delete that.parents[ id ];
  18609 			} );
  18610 		}
  18611 
  18612 		tooltipData.closing = true;
  18613 		this._trigger( "close", event, { tooltip: tooltip } );
  18614 		if ( !tooltipData.hiding ) {
  18615 			tooltipData.closing = false;
  18616 		}
  18617 	},
  18618 
  18619 	_tooltip: function( element ) {
  18620 		var tooltip = $( "<div>" ).attr( "role", "tooltip" ),
  18621 			content = $( "<div>" ).appendTo( tooltip ),
  18622 			id = tooltip.uniqueId().attr( "id" );
  18623 
  18624 		this._addClass( content, "ui-tooltip-content" );
  18625 		this._addClass( tooltip, "ui-tooltip", "ui-widget ui-widget-content" );
  18626 
  18627 		tooltip.appendTo( this._appendTo( element ) );
  18628 
  18629 		return this.tooltips[ id ] = {
  18630 			element: element,
  18631 			tooltip: tooltip
  18632 		};
  18633 	},
  18634 
  18635 	_find: function( target ) {
  18636 		var id = target.data( "ui-tooltip-id" );
  18637 		return id ? this.tooltips[ id ] : null;
  18638 	},
  18639 
  18640 	_removeTooltip: function( tooltip ) {
  18641 		tooltip.remove();
  18642 		delete this.tooltips[ tooltip.attr( "id" ) ];
  18643 	},
  18644 
  18645 	_appendTo: function( target ) {
  18646 		var element = target.closest( ".ui-front, dialog" );
  18647 
  18648 		if ( !element.length ) {
  18649 			element = this.document[ 0 ].body;
  18650 		}
  18651 
  18652 		return element;
  18653 	},
  18654 
  18655 	_destroy: function() {
  18656 		var that = this;
  18657 
  18658 		// Close open tooltips
  18659 		$.each( this.tooltips, function( id, tooltipData ) {
  18660 
  18661 			// Delegate to close method to handle common cleanup
  18662 			var event = $.Event( "blur" ),
  18663 				element = tooltipData.element;
  18664 			event.target = event.currentTarget = element[ 0 ];
  18665 			that.close( event, true );
  18666 
  18667 			// Remove immediately; destroying an open tooltip doesn't use the
  18668 			// hide animation
  18669 			$( "#" + id ).remove();
  18670 
  18671 			// Restore the title
  18672 			if ( element.data( "ui-tooltip-title" ) ) {
  18673 
  18674 				// If the title attribute has changed since open(), don't restore
  18675 				if ( !element.attr( "title" ) ) {
  18676 					element.attr( "title", element.data( "ui-tooltip-title" ) );
  18677 				}
  18678 				element.removeData( "ui-tooltip-title" );
  18679 			}
  18680 		} );
  18681 		this.liveRegion.remove();
  18682 	}
  18683 } );
  18684 
  18685 // DEPRECATED
  18686 // TODO: Switch return back to widget declaration at top of file when this is removed
  18687 if ( $.uiBackCompat !== false ) {
  18688 
  18689 	// Backcompat for tooltipClass option
  18690 	$.widget( "ui.tooltip", $.ui.tooltip, {
  18691 		options: {
  18692 			tooltipClass: null
  18693 		},
  18694 		_tooltip: function() {
  18695 			var tooltipData = this._superApply( arguments );
  18696 			if ( this.options.tooltipClass ) {
  18697 				tooltipData.tooltip.addClass( this.options.tooltipClass );
  18698 			}
  18699 			return tooltipData;
  18700 		}
  18701 	} );
  18702 }
  18703 
  18704 var widgetsTooltip = $.ui.tooltip;
  18705 
  18706 
  18707 
  18708 
  18709 }));