Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1441 ariadna 1
/*! jQuery UI - v1.14.1 - 2024-10-30
2
* https://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-patch.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 OpenJS Foundation and other contributors; Licensed MIT */
5
 
6
( function( factory ) {
7
	"use strict";
8
 
9
	if ( typeof define === "function" && define.amd ) {
10
 
11
		// AMD. Register as an anonymous module.
12
		define( [ "jquery" ], factory );
13
	} else {
14
 
15
		// Browser globals
16
		factory( jQuery );
17
	}
18
} )( function( $ ) {
19
"use strict";
20
 
21
$.ui = $.ui || {};
22
 
23
var version = $.ui.version = "1.14.1";
24
 
25
 
26
/*!
27
 * jQuery UI Widget 1.14.1
28
 * https://jqueryui.com
29
 *
30
 * Copyright OpenJS Foundation and other contributors
31
 * Released under the MIT license.
32
 * https://jquery.org/license
33
 */
34
 
35
//>>label: Widget
36
//>>group: Core
37
//>>description: Provides a factory for creating stateful widgets with a common API.
38
//>>docs: https://api.jqueryui.com/jQuery.widget/
39
//>>demos: https://jqueryui.com/widget/
40
 
41
 
42
var widgetUuid = 0;
43
var widgetHasOwnProperty = Array.prototype.hasOwnProperty;
44
var widgetSlice = Array.prototype.slice;
45
 
46
$.cleanData = ( function( orig ) {
47
	return function( elems ) {
48
		var events, elem, i;
49
		for ( i = 0; ( elem = elems[ i ] ) != null; i++ ) {
50
 
51
			// Only trigger remove when necessary to save time
52
			events = $._data( elem, "events" );
53
			if ( events && events.remove ) {
54
				$( elem ).triggerHandler( "remove" );
55
			}
56
		}
57
		orig( elems );
58
	};
59
} )( $.cleanData );
60
 
61
$.widget = function( name, base, prototype ) {
62
	var existingConstructor, constructor, basePrototype;
63
 
64
	// ProxiedPrototype allows the provided prototype to remain unmodified
65
	// so that it can be used as a mixin for multiple widgets (#8876)
66
	var proxiedPrototype = {};
67
 
68
	var namespace = name.split( "." )[ 0 ];
69
	name = name.split( "." )[ 1 ];
70
	if ( name === "__proto__" || name === "constructor" ) {
71
		return $.error( "Invalid widget name: " + name );
72
	}
73
	var fullName = namespace + "-" + name;
74
 
75
	if ( !prototype ) {
76
		prototype = base;
77
		base = $.Widget;
78
	}
79
 
80
	if ( Array.isArray( prototype ) ) {
81
		prototype = $.extend.apply( null, [ {} ].concat( prototype ) );
82
	}
83
 
84
	// Create selector for plugin
85
	$.expr.pseudos[ fullName.toLowerCase() ] = function( elem ) {
86
		return !!$.data( elem, fullName );
87
	};
88
 
89
	$[ namespace ] = $[ namespace ] || {};
90
	existingConstructor = $[ namespace ][ name ];
91
	constructor = $[ namespace ][ name ] = function( options, element ) {
92
 
93
		// Allow instantiation without "new" keyword
94
		if ( !this || !this._createWidget ) {
95
			return new constructor( options, element );
96
		}
97
 
98
		// Allow instantiation without initializing for simple inheritance
99
		// must use "new" keyword (the code above always passes args)
100
		if ( arguments.length ) {
101
			this._createWidget( options, element );
102
		}
103
	};
104
 
105
	// Extend with the existing constructor to carry over any static properties
106
	$.extend( constructor, existingConstructor, {
107
		version: prototype.version,
108
 
109
		// Copy the object used to create the prototype in case we need to
110
		// redefine the widget later
111
		_proto: $.extend( {}, prototype ),
112
 
113
		// Track widgets that inherit from this widget in case this widget is
114
		// redefined after a widget inherits from it
115
		_childConstructors: []
116
	} );
117
 
118
	basePrototype = new base();
119
 
120
	// We need to make the options hash a property directly on the new instance
121
	// otherwise we'll modify the options hash on the prototype that we're
122
	// inheriting from
123
	basePrototype.options = $.widget.extend( {}, basePrototype.options );
124
	$.each( prototype, function( prop, value ) {
125
		if ( typeof value !== "function" ) {
126
			proxiedPrototype[ prop ] = value;
127
			return;
128
		}
129
		proxiedPrototype[ prop ] = ( function() {
130
			function _super() {
131
				return base.prototype[ prop ].apply( this, arguments );
132
			}
133
 
134
			function _superApply( args ) {
135
				return base.prototype[ prop ].apply( this, args );
136
			}
137
 
138
			return function() {
139
				var __super = this._super;
140
				var __superApply = this._superApply;
141
				var returnValue;
142
 
143
				this._super = _super;
144
				this._superApply = _superApply;
145
 
146
				returnValue = value.apply( this, arguments );
147
 
148
				this._super = __super;
149
				this._superApply = __superApply;
150
 
151
				return returnValue;
152
			};
153
		} )();
154
	} );
155
	constructor.prototype = $.widget.extend( basePrototype, {
156
 
157
		// TODO: remove support for widgetEventPrefix
158
		// always use the name + a colon as the prefix, e.g., draggable:start
159
		// don't prefix for widgets that aren't DOM-based
160
		widgetEventPrefix: existingConstructor ? ( basePrototype.widgetEventPrefix || name ) : name
161
	}, proxiedPrototype, {
162
		constructor: constructor,
163
		namespace: namespace,
164
		widgetName: name,
165
		widgetFullName: fullName
166
	} );
167
 
168
	// If this widget is being redefined then we need to find all widgets that
169
	// are inheriting from it and redefine all of them so that they inherit from
170
	// the new version of this widget. We're essentially trying to replace one
171
	// level in the prototype chain.
172
	if ( existingConstructor ) {
173
		$.each( existingConstructor._childConstructors, function( i, child ) {
174
			var childPrototype = child.prototype;
175
 
176
			// Redefine the child widget using the same prototype that was
177
			// originally used, but inherit from the new version of the base
178
			$.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor,
179
				child._proto );
180
		} );
181
 
182
		// Remove the list of existing child constructors from the old constructor
183
		// so the old child constructors can be garbage collected
184
		delete existingConstructor._childConstructors;
185
	} else {
186
		base._childConstructors.push( constructor );
187
	}
188
 
189
	$.widget.bridge( name, constructor );
190
 
191
	return constructor;
192
};
193
 
194
$.widget.extend = function( target ) {
195
	var input = widgetSlice.call( arguments, 1 );
196
	var inputIndex = 0;
197
	var inputLength = input.length;
198
	var key;
199
	var value;
200
 
201
	for ( ; inputIndex < inputLength; inputIndex++ ) {
202
		for ( key in input[ inputIndex ] ) {
203
			value = input[ inputIndex ][ key ];
204
			if ( widgetHasOwnProperty.call( input[ inputIndex ], key ) && value !== undefined ) {
205
 
206
				// Clone objects
207
				if ( $.isPlainObject( value ) ) {
208
					target[ key ] = $.isPlainObject( target[ key ] ) ?
209
						$.widget.extend( {}, target[ key ], value ) :
210
 
211
						// Don't extend strings, arrays, etc. with objects
212
						$.widget.extend( {}, value );
213
 
214
				// Copy everything else by reference
215
				} else {
216
					target[ key ] = value;
217
				}
218
			}
219
		}
220
	}
221
	return target;
222
};
223
 
224
$.widget.bridge = function( name, object ) {
225
	var fullName = object.prototype.widgetFullName || name;
226
	$.fn[ name ] = function( options ) {
227
		var isMethodCall = typeof options === "string";
228
		var args = widgetSlice.call( arguments, 1 );
229
		var returnValue = this;
230
 
231
		if ( isMethodCall ) {
232
 
233
			// If this is an empty collection, we need to have the instance method
234
			// return undefined instead of the jQuery instance
235
			if ( !this.length && options === "instance" ) {
236
				returnValue = undefined;
237
			} else {
238
				this.each( function() {
239
					var methodValue;
240
					var instance = $.data( this, fullName );
241
 
242
					if ( options === "instance" ) {
243
						returnValue = instance;
244
						return false;
245
					}
246
 
247
					if ( !instance ) {
248
						return $.error( "cannot call methods on " + name +
249
							" prior to initialization; " +
250
							"attempted to call method '" + options + "'" );
251
					}
252
 
253
					if ( typeof instance[ options ] !== "function" ||
254
						options.charAt( 0 ) === "_" ) {
255
						return $.error( "no such method '" + options + "' for " + name +
256
							" widget instance" );
257
					}
258
 
259
					methodValue = instance[ options ].apply( instance, args );
260
 
261
					if ( methodValue !== instance && methodValue !== undefined ) {
262
						returnValue = methodValue && methodValue.jquery ?
263
							returnValue.pushStack( methodValue.get() ) :
264
							methodValue;
265
						return false;
266
					}
267
				} );
268
			}
269
		} else {
270
 
271
			// Allow multiple hashes to be passed on init
272
			if ( args.length ) {
273
				options = $.widget.extend.apply( null, [ options ].concat( args ) );
274
			}
275
 
276
			this.each( function() {
277
				var instance = $.data( this, fullName );
278
				if ( instance ) {
279
					instance.option( options || {} );
280
					if ( instance._init ) {
281
						instance._init();
282
					}
283
				} else {
284
					$.data( this, fullName, new object( options, this ) );
285
				}
286
			} );
287
		}
288
 
289
		return returnValue;
290
	};
291
};
292
 
293
$.Widget = function( /* options, element */ ) {};
294
$.Widget._childConstructors = [];
295
 
296
$.Widget.prototype = {
297
	widgetName: "widget",
298
	widgetEventPrefix: "",
299
	defaultElement: "<div>",
300
 
301
	options: {
302
		classes: {},
303
		disabled: false,
304
 
305
		// Callbacks
306
		create: null
307
	},
308
 
309
	_createWidget: function( options, element ) {
310
		element = $( element || this.defaultElement || this )[ 0 ];
311
		this.element = $( element );
312
		this.uuid = widgetUuid++;
313
		this.eventNamespace = "." + this.widgetName + this.uuid;
314
 
315
		this.bindings = $();
316
		this.hoverable = $();
317
		this.focusable = $();
318
		this.classesElementLookup = {};
319
 
320
		if ( element !== this ) {
321
			$.data( element, this.widgetFullName, this );
322
			this._on( true, this.element, {
323
				remove: function( event ) {
324
					if ( event.target === element ) {
325
						this.destroy();
326
					}
327
				}
328
			} );
329
			this.document = $( element.style ?
330
 
331
				// Element within the document
332
				element.ownerDocument :
333
 
334
				// Element is window or document
335
				element.document || element );
336
			this.window = $( this.document[ 0 ].defaultView || this.document[ 0 ].parentWindow );
337
		}
338
 
339
		this.options = $.widget.extend( {},
340
			this.options,
341
			this._getCreateOptions(),
342
			options );
343
 
344
		this._create();
345
 
346
		if ( this.options.disabled ) {
347
			this._setOptionDisabled( this.options.disabled );
348
		}
349
 
350
		this._trigger( "create", null, this._getCreateEventData() );
351
		this._init();
352
	},
353
 
354
	_getCreateOptions: function() {
355
		return {};
356
	},
357
 
358
	_getCreateEventData: $.noop,
359
 
360
	_create: $.noop,
361
 
362
	_init: $.noop,
363
 
364
	destroy: function() {
365
		var that = this;
366
 
367
		this._destroy();
368
		$.each( this.classesElementLookup, function( key, value ) {
369
			that._removeClass( value, key );
370
		} );
371
 
372
		// We can probably remove the unbind calls in 2.0
373
		// all event bindings should go through this._on()
374
		this.element
375
			.off( this.eventNamespace )
376
			.removeData( this.widgetFullName );
377
		this.widget()
378
			.off( this.eventNamespace )
379
			.removeAttr( "aria-disabled" );
380
 
381
		// Clean up events and states
382
		this.bindings.off( this.eventNamespace );
383
	},
384
 
385
	_destroy: $.noop,
386
 
387
	widget: function() {
388
		return this.element;
389
	},
390
 
391
	option: function( key, value ) {
392
		var options = key;
393
		var parts;
394
		var curOption;
395
		var i;
396
 
397
		if ( arguments.length === 0 ) {
398
 
399
			// Don't return a reference to the internal hash
400
			return $.widget.extend( {}, this.options );
401
		}
402
 
403
		if ( typeof key === "string" ) {
404
 
405
			// Handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
406
			options = {};
407
			parts = key.split( "." );
408
			key = parts.shift();
409
			if ( parts.length ) {
410
				curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
411
				for ( i = 0; i < parts.length - 1; i++ ) {
412
					curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
413
					curOption = curOption[ parts[ i ] ];
414
				}
415
				key = parts.pop();
416
				if ( arguments.length === 1 ) {
417
					return curOption[ key ] === undefined ? null : curOption[ key ];
418
				}
419
				curOption[ key ] = value;
420
			} else {
421
				if ( arguments.length === 1 ) {
422
					return this.options[ key ] === undefined ? null : this.options[ key ];
423
				}
424
				options[ key ] = value;
425
			}
426
		}
427
 
428
		this._setOptions( options );
429
 
430
		return this;
431
	},
432
 
433
	_setOptions: function( options ) {
434
		var key;
435
 
436
		for ( key in options ) {
437
			this._setOption( key, options[ key ] );
438
		}
439
 
440
		return this;
441
	},
442
 
443
	_setOption: function( key, value ) {
444
		if ( key === "classes" ) {
445
			this._setOptionClasses( value );
446
		}
447
 
448
		this.options[ key ] = value;
449
 
450
		if ( key === "disabled" ) {
451
			this._setOptionDisabled( value );
452
		}
453
 
454
		return this;
455
	},
456
 
457
	_setOptionClasses: function( value ) {
458
		var classKey, elements, currentElements;
459
 
460
		for ( classKey in value ) {
461
			currentElements = this.classesElementLookup[ classKey ];
462
			if ( value[ classKey ] === this.options.classes[ classKey ] ||
463
					!currentElements ||
464
					!currentElements.length ) {
465
				continue;
466
			}
467
 
468
			// We are doing this to create a new jQuery object because the _removeClass() call
469
			// on the next line is going to destroy the reference to the current elements being
470
			// tracked. We need to save a copy of this collection so that we can add the new classes
471
			// below.
472
			elements = $( currentElements.get() );
473
			this._removeClass( currentElements, classKey );
474
 
475
			// We don't use _addClass() here, because that uses this.options.classes
476
			// for generating the string of classes. We want to use the value passed in from
477
			// _setOption(), this is the new value of the classes option which was passed to
478
			// _setOption(). We pass this value directly to _classes().
479
			elements.addClass( this._classes( {
480
				element: elements,
481
				keys: classKey,
482
				classes: value,
483
				add: true
484
			} ) );
485
		}
486
	},
487
 
488
	_setOptionDisabled: function( value ) {
489
		this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null, !!value );
490
 
491
		// If the widget is becoming disabled, then nothing is interactive
492
		if ( value ) {
493
			this._removeClass( this.hoverable, null, "ui-state-hover" );
494
			this._removeClass( this.focusable, null, "ui-state-focus" );
495
		}
496
	},
497
 
498
	enable: function() {
499
		return this._setOptions( { disabled: false } );
500
	},
501
 
502
	disable: function() {
503
		return this._setOptions( { disabled: true } );
504
	},
505
 
506
	_classes: function( options ) {
507
		var full = [];
508
		var that = this;
509
 
510
		options = $.extend( {
511
			element: this.element,
512
			classes: this.options.classes || {}
513
		}, options );
514
 
515
		function bindRemoveEvent() {
516
			var nodesToBind = [];
517
 
518
			options.element.each( function( _, element ) {
519
				var isTracked = $.map( that.classesElementLookup, function( elements ) {
520
					return elements;
521
				} )
522
					.some( function( elements ) {
523
						return elements.is( element );
524
					} );
525
 
526
				if ( !isTracked ) {
527
					nodesToBind.push( element );
528
				}
529
			} );
530
 
531
			that._on( $( nodesToBind ), {
532
				remove: "_untrackClassesElement"
533
			} );
534
		}
535
 
536
		function processClassString( classes, checkOption ) {
537
			var current, i;
538
			for ( i = 0; i < classes.length; i++ ) {
539
				current = that.classesElementLookup[ classes[ i ] ] || $();
540
				if ( options.add ) {
541
					bindRemoveEvent();
542
					current = $( $.uniqueSort( current.get().concat( options.element.get() ) ) );
543
				} else {
544
					current = $( current.not( options.element ).get() );
545
				}
546
				that.classesElementLookup[ classes[ i ] ] = current;
547
				full.push( classes[ i ] );
548
				if ( checkOption && options.classes[ classes[ i ] ] ) {
549
					full.push( options.classes[ classes[ i ] ] );
550
				}
551
			}
552
		}
553
 
554
		if ( options.keys ) {
555
			processClassString( options.keys.match( /\S+/g ) || [], true );
556
		}
557
		if ( options.extra ) {
558
			processClassString( options.extra.match( /\S+/g ) || [] );
559
		}
560
 
561
		return full.join( " " );
562
	},
563
 
564
	_untrackClassesElement: function( event ) {
565
		var that = this;
566
		$.each( that.classesElementLookup, function( key, value ) {
567
			if ( $.inArray( event.target, value ) !== -1 ) {
568
				that.classesElementLookup[ key ] = $( value.not( event.target ).get() );
569
			}
570
		} );
571
 
572
		this._off( $( event.target ) );
573
	},
574
 
575
	_removeClass: function( element, keys, extra ) {
576
		return this._toggleClass( element, keys, extra, false );
577
	},
578
 
579
	_addClass: function( element, keys, extra ) {
580
		return this._toggleClass( element, keys, extra, true );
581
	},
582
 
583
	_toggleClass: function( element, keys, extra, add ) {
584
		add = ( typeof add === "boolean" ) ? add : extra;
585
		var shift = ( typeof element === "string" || element === null ),
586
			options = {
587
				extra: shift ? keys : extra,
588
				keys: shift ? element : keys,
589
				element: shift ? this.element : element,
590
				add: add
591
			};
592
		options.element.toggleClass( this._classes( options ), add );
593
		return this;
594
	},
595
 
596
	_on: function( suppressDisabledCheck, element, handlers ) {
597
		var delegateElement;
598
		var instance = this;
599
 
600
		// No suppressDisabledCheck flag, shuffle arguments
601
		if ( typeof suppressDisabledCheck !== "boolean" ) {
602
			handlers = element;
603
			element = suppressDisabledCheck;
604
			suppressDisabledCheck = false;
605
		}
606
 
607
		// No element argument, shuffle and use this.element
608
		if ( !handlers ) {
609
			handlers = element;
610
			element = this.element;
611
			delegateElement = this.widget();
612
		} else {
613
			element = delegateElement = $( element );
614
			this.bindings = this.bindings.add( element );
615
		}
616
 
617
		$.each( handlers, function( event, handler ) {
618
			function handlerProxy() {
619
 
620
				// Allow widgets to customize the disabled handling
621
				// - disabled as an array instead of boolean
622
				// - disabled class as method for disabling individual parts
623
				if ( !suppressDisabledCheck &&
624
						( instance.options.disabled === true ||
625
						$( this ).hasClass( "ui-state-disabled" ) ) ) {
626
					return;
627
				}
628
				return ( typeof handler === "string" ? instance[ handler ] : handler )
629
					.apply( instance, arguments );
630
			}
631
 
632
			// Copy the guid so direct unbinding works
633
			if ( typeof handler !== "string" ) {
634
				handlerProxy.guid = handler.guid =
635
					handler.guid || handlerProxy.guid || $.guid++;
636
			}
637
 
638
			var match = event.match( /^([\w:-]*)\s*(.*)$/ );
639
			var eventName = match[ 1 ] + instance.eventNamespace;
640
			var selector = match[ 2 ];
641
 
642
			if ( selector ) {
643
				delegateElement.on( eventName, selector, handlerProxy );
644
			} else {
645
				element.on( eventName, handlerProxy );
646
			}
647
		} );
648
	},
649
 
650
	_off: function( element, eventName ) {
651
		eventName = ( eventName || "" ).split( " " ).join( this.eventNamespace + " " ) +
652
			this.eventNamespace;
653
		element.off( eventName );
654
 
655
		// Clear the stack to avoid memory leaks (#10056)
656
		this.bindings = $( this.bindings.not( element ).get() );
657
		this.focusable = $( this.focusable.not( element ).get() );
658
		this.hoverable = $( this.hoverable.not( element ).get() );
659
	},
660
 
661
	_delay: function( handler, delay ) {
662
		function handlerProxy() {
663
			return ( typeof handler === "string" ? instance[ handler ] : handler )
664
				.apply( instance, arguments );
665
		}
666
		var instance = this;
667
		return setTimeout( handlerProxy, delay || 0 );
668
	},
669
 
670
	_hoverable: function( element ) {
671
		this.hoverable = this.hoverable.add( element );
672
		this._on( element, {
673
			mouseenter: function( event ) {
674
				this._addClass( $( event.currentTarget ), null, "ui-state-hover" );
675
			},
676
			mouseleave: function( event ) {
677
				this._removeClass( $( event.currentTarget ), null, "ui-state-hover" );
678
			}
679
		} );
680
	},
681
 
682
	_focusable: function( element ) {
683
		this.focusable = this.focusable.add( element );
684
		this._on( element, {
685
			focusin: function( event ) {
686
				this._addClass( $( event.currentTarget ), null, "ui-state-focus" );
687
			},
688
			focusout: function( event ) {
689
				this._removeClass( $( event.currentTarget ), null, "ui-state-focus" );
690
			}
691
		} );
692
	},
693
 
694
	_trigger: function( type, event, data ) {
695
		var prop, orig;
696
		var callback = this.options[ type ];
697
 
698
		data = data || {};
699
		event = $.Event( event );
700
		event.type = ( type === this.widgetEventPrefix ?
701
			type :
702
			this.widgetEventPrefix + type ).toLowerCase();
703
 
704
		// The original event may come from any element
705
		// so we need to reset the target on the new event
706
		event.target = this.element[ 0 ];
707
 
708
		// Copy original event properties over to the new event
709
		orig = event.originalEvent;
710
		if ( orig ) {
711
			for ( prop in orig ) {
712
				if ( !( prop in event ) ) {
713
					event[ prop ] = orig[ prop ];
714
				}
715
			}
716
		}
717
 
718
		this.element.trigger( event, data );
719
		return !( typeof callback === "function" &&
720
			callback.apply( this.element[ 0 ], [ event ].concat( data ) ) === false ||
721
			event.isDefaultPrevented() );
722
	}
723
};
724
 
725
$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
726
	$.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
727
		if ( typeof options === "string" ) {
728
			options = { effect: options };
729
		}
730
 
731
		var hasOptions;
732
		var effectName = !options ?
733
			method :
734
			options === true || typeof options === "number" ?
735
				defaultEffect :
736
				options.effect || defaultEffect;
737
 
738
		options = options || {};
739
		if ( typeof options === "number" ) {
740
			options = { duration: options };
741
		} else if ( options === true ) {
742
			options = {};
743
		}
744
 
745
		hasOptions = !$.isEmptyObject( options );
746
		options.complete = callback;
747
 
748
		if ( options.delay ) {
749
			element.delay( options.delay );
750
		}
751
 
752
		if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
753
			element[ method ]( options );
754
		} else if ( effectName !== method && element[ effectName ] ) {
755
			element[ effectName ]( options.duration, options.easing, callback );
756
		} else {
757
			element.queue( function( next ) {
758
				$( this )[ method ]();
759
				if ( callback ) {
760
					callback.call( element[ 0 ] );
761
				}
762
				next();
763
			} );
764
		}
765
	};
766
} );
767
 
768
var widget = $.widget;
769
 
770
 
771
/*!
772
 * jQuery UI Position 1.14.1
773
 * https://jqueryui.com
774
 *
775
 * Copyright OpenJS Foundation and other contributors
776
 * Released under the MIT license.
777
 * https://jquery.org/license
778
 *
779
 * https://api.jqueryui.com/position/
780
 */
781
 
782
//>>label: Position
783
//>>group: Core
784
//>>description: Positions elements relative to other elements.
785
//>>docs: https://api.jqueryui.com/position/
786
//>>demos: https://jqueryui.com/position/
787
 
788
 
789
( function() {
790
var cachedScrollbarWidth,
791
	max = Math.max,
792
	abs = Math.abs,
793
	rhorizontal = /left|center|right/,
794
	rvertical = /top|center|bottom/,
795
	roffset = /[\+\-]\d+(\.[\d]+)?%?/,
796
	rposition = /^\w+/,
797
	rpercent = /%$/,
798
	_position = $.fn.position;
799
 
800
function getOffsets( offsets, width, height ) {
801
	return [
802
		parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),
803
		parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )
804
	];
805
}
806
 
807
function parseCss( element, property ) {
808
	return parseInt( $.css( element, property ), 10 ) || 0;
809
}
810
 
811
function isWindow( obj ) {
812
	return obj != null && obj === obj.window;
813
}
814
 
815
function getDimensions( elem ) {
816
	var raw = elem[ 0 ];
817
	if ( raw.nodeType === 9 ) {
818
		return {
819
			width: elem.width(),
820
			height: elem.height(),
821
			offset: { top: 0, left: 0 }
822
		};
823
	}
824
	if ( isWindow( raw ) ) {
825
		return {
826
			width: elem.width(),
827
			height: elem.height(),
828
			offset: { top: elem.scrollTop(), left: elem.scrollLeft() }
829
		};
830
	}
831
	if ( raw.preventDefault ) {
832
		return {
833
			width: 0,
834
			height: 0,
835
			offset: { top: raw.pageY, left: raw.pageX }
836
		};
837
	}
838
	return {
839
		width: elem.outerWidth(),
840
		height: elem.outerHeight(),
841
		offset: elem.offset()
842
	};
843
}
844
 
845
$.position = {
846
	scrollbarWidth: function() {
847
		if ( cachedScrollbarWidth !== undefined ) {
848
			return cachedScrollbarWidth;
849
		}
850
		var w1, w2,
851
			div = $( "<div style=" +
852
				"'display:block;position:absolute;width:200px;height:200px;overflow:hidden;'>" +
853
				"<div style='height:300px;width:auto;'></div></div>" ),
854
			innerDiv = div.children()[ 0 ];
855
 
856
		$( "body" ).append( div );
857
		w1 = innerDiv.offsetWidth;
858
		div.css( "overflow", "scroll" );
859
 
860
		w2 = innerDiv.offsetWidth;
861
 
862
		if ( w1 === w2 ) {
863
			w2 = div[ 0 ].clientWidth;
864
		}
865
 
866
		div.remove();
867
 
868
		return ( cachedScrollbarWidth = w1 - w2 );
869
	},
870
	getScrollInfo: function( within ) {
871
		var overflowX = within.isWindow || within.isDocument ? "" :
872
				within.element.css( "overflow-x" ),
873
			overflowY = within.isWindow || within.isDocument ? "" :
874
				within.element.css( "overflow-y" ),
875
			hasOverflowX = overflowX === "scroll" ||
876
				( overflowX === "auto" && within.width < within.element[ 0 ].scrollWidth ),
877
			hasOverflowY = overflowY === "scroll" ||
878
				( overflowY === "auto" && within.height < within.element[ 0 ].scrollHeight );
879
		return {
880
			width: hasOverflowY ? $.position.scrollbarWidth() : 0,
881
			height: hasOverflowX ? $.position.scrollbarWidth() : 0
882
		};
883
	},
884
	getWithinInfo: function( element ) {
885
		var withinElement = $( element || window ),
886
			isElemWindow = isWindow( withinElement[ 0 ] ),
887
			isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9,
888
			hasOffset = !isElemWindow && !isDocument;
889
		return {
890
			element: withinElement,
891
			isWindow: isElemWindow,
892
			isDocument: isDocument,
893
			offset: hasOffset ? $( element ).offset() : { left: 0, top: 0 },
894
			scrollLeft: withinElement.scrollLeft(),
895
			scrollTop: withinElement.scrollTop(),
896
			width: withinElement.outerWidth(),
897
			height: withinElement.outerHeight()
898
		};
899
	}
900
};
901
 
902
$.fn.position = function( options ) {
903
	if ( !options || !options.of ) {
904
		return _position.apply( this, arguments );
905
	}
906
 
907
	// Make a copy, we don't want to modify arguments
908
	options = $.extend( {}, options );
909
 
910
	var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,
911
 
912
		// Make sure string options are treated as CSS selectors
913
		target = typeof options.of === "string" ?
914
			$( document ).find( options.of ) :
915
			$( options.of ),
916
 
917
		within = $.position.getWithinInfo( options.within ),
918
		scrollInfo = $.position.getScrollInfo( within ),
919
		collision = ( options.collision || "flip" ).split( " " ),
920
		offsets = {};
921
 
922
	dimensions = getDimensions( target );
923
	if ( target[ 0 ].preventDefault ) {
924
 
925
		// Force left top to allow flipping
926
		options.at = "left top";
927
	}
928
	targetWidth = dimensions.width;
929
	targetHeight = dimensions.height;
930
	targetOffset = dimensions.offset;
931
 
932
	// Clone to reuse original targetOffset later
933
	basePosition = $.extend( {}, targetOffset );
934
 
935
	// Force my and at to have valid horizontal and vertical positions
936
	// if a value is missing or invalid, it will be converted to center
937
	$.each( [ "my", "at" ], function() {
938
		var pos = ( options[ this ] || "" ).split( " " ),
939
			horizontalOffset,
940
			verticalOffset;
941
 
942
		if ( pos.length === 1 ) {
943
			pos = rhorizontal.test( pos[ 0 ] ) ?
944
				pos.concat( [ "center" ] ) :
945
				rvertical.test( pos[ 0 ] ) ?
946
					[ "center" ].concat( pos ) :
947
					[ "center", "center" ];
948
		}
949
		pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center";
950
		pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";
951
 
952
		// Calculate offsets
953
		horizontalOffset = roffset.exec( pos[ 0 ] );
954
		verticalOffset = roffset.exec( pos[ 1 ] );
955
		offsets[ this ] = [
956
			horizontalOffset ? horizontalOffset[ 0 ] : 0,
957
			verticalOffset ? verticalOffset[ 0 ] : 0
958
		];
959
 
960
		// Reduce to just the positions without the offsets
961
		options[ this ] = [
962
			rposition.exec( pos[ 0 ] )[ 0 ],
963
			rposition.exec( pos[ 1 ] )[ 0 ]
964
		];
965
	} );
966
 
967
	// Normalize collision option
968
	if ( collision.length === 1 ) {
969
		collision[ 1 ] = collision[ 0 ];
970
	}
971
 
972
	if ( options.at[ 0 ] === "right" ) {
973
		basePosition.left += targetWidth;
974
	} else if ( options.at[ 0 ] === "center" ) {
975
		basePosition.left += targetWidth / 2;
976
	}
977
 
978
	if ( options.at[ 1 ] === "bottom" ) {
979
		basePosition.top += targetHeight;
980
	} else if ( options.at[ 1 ] === "center" ) {
981
		basePosition.top += targetHeight / 2;
982
	}
983
 
984
	atOffset = getOffsets( offsets.at, targetWidth, targetHeight );
985
	basePosition.left += atOffset[ 0 ];
986
	basePosition.top += atOffset[ 1 ];
987
 
988
	return this.each( function() {
989
		var collisionPosition, using,
990
			elem = $( this ),
991
			elemWidth = elem.outerWidth(),
992
			elemHeight = elem.outerHeight(),
993
			marginLeft = parseCss( this, "marginLeft" ),
994
			marginTop = parseCss( this, "marginTop" ),
995
			collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) +
996
				scrollInfo.width,
997
			collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) +
998
				scrollInfo.height,
999
			position = $.extend( {}, basePosition ),
1000
			myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );
1001
 
1002
		if ( options.my[ 0 ] === "right" ) {
1003
			position.left -= elemWidth;
1004
		} else if ( options.my[ 0 ] === "center" ) {
1005
			position.left -= elemWidth / 2;
1006
		}
1007
 
1008
		if ( options.my[ 1 ] === "bottom" ) {
1009
			position.top -= elemHeight;
1010
		} else if ( options.my[ 1 ] === "center" ) {
1011
			position.top -= elemHeight / 2;
1012
		}
1013
 
1014
		position.left += myOffset[ 0 ];
1015
		position.top += myOffset[ 1 ];
1016
 
1017
		collisionPosition = {
1018
			marginLeft: marginLeft,
1019
			marginTop: marginTop
1020
		};
1021
 
1022
		$.each( [ "left", "top" ], function( i, dir ) {
1023
			if ( $.ui.position[ collision[ i ] ] ) {
1024
				$.ui.position[ collision[ i ] ][ dir ]( position, {
1025
					targetWidth: targetWidth,
1026
					targetHeight: targetHeight,
1027
					elemWidth: elemWidth,
1028
					elemHeight: elemHeight,
1029
					collisionPosition: collisionPosition,
1030
					collisionWidth: collisionWidth,
1031
					collisionHeight: collisionHeight,
1032
					offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],
1033
					my: options.my,
1034
					at: options.at,
1035
					within: within,
1036
					elem: elem
1037
				} );
1038
			}
1039
		} );
1040
 
1041
		if ( options.using ) {
1042
 
1043
			// Adds feedback as second argument to using callback, if present
1044
			using = function( props ) {
1045
				var left = targetOffset.left - position.left,
1046
					right = left + targetWidth - elemWidth,
1047
					top = targetOffset.top - position.top,
1048
					bottom = top + targetHeight - elemHeight,
1049
					feedback = {
1050
						target: {
1051
							element: target,
1052
							left: targetOffset.left,
1053
							top: targetOffset.top,
1054
							width: targetWidth,
1055
							height: targetHeight
1056
						},
1057
						element: {
1058
							element: elem,
1059
							left: position.left,
1060
							top: position.top,
1061
							width: elemWidth,
1062
							height: elemHeight
1063
						},
1064
						horizontal: right < 0 ? "left" : left > 0 ? "right" : "center",
1065
						vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle"
1066
					};
1067
				if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {
1068
					feedback.horizontal = "center";
1069
				}
1070
				if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {
1071
					feedback.vertical = "middle";
1072
				}
1073
				if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {
1074
					feedback.important = "horizontal";
1075
				} else {
1076
					feedback.important = "vertical";
1077
				}
1078
				options.using.call( this, props, feedback );
1079
			};
1080
		}
1081
 
1082
		elem.offset( $.extend( position, { using: using } ) );
1083
	} );
1084
};
1085
 
1086
$.ui.position = {
1087
	fit: {
1088
		left: function( position, data ) {
1089
			var within = data.within,
1090
				withinOffset = within.isWindow ? within.scrollLeft : within.offset.left,
1091
				outerWidth = within.width,
1092
				collisionPosLeft = position.left - data.collisionPosition.marginLeft,
1093
				overLeft = withinOffset - collisionPosLeft,
1094
				overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
1095
				newOverRight;
1096
 
1097
			// Element is wider than within
1098
			if ( data.collisionWidth > outerWidth ) {
1099
 
1100
				// Element is initially over the left side of within
1101
				if ( overLeft > 0 && overRight <= 0 ) {
1102
					newOverRight = position.left + overLeft + data.collisionWidth - outerWidth -
1103
						withinOffset;
1104
					position.left += overLeft - newOverRight;
1105
 
1106
				// Element is initially over right side of within
1107
				} else if ( overRight > 0 && overLeft <= 0 ) {
1108
					position.left = withinOffset;
1109
 
1110
				// Element is initially over both left and right sides of within
1111
				} else {
1112
					if ( overLeft > overRight ) {
1113
						position.left = withinOffset + outerWidth - data.collisionWidth;
1114
					} else {
1115
						position.left = withinOffset;
1116
					}
1117
				}
1118
 
1119
			// Too far left -> align with left edge
1120
			} else if ( overLeft > 0 ) {
1121
				position.left += overLeft;
1122
 
1123
			// Too far right -> align with right edge
1124
			} else if ( overRight > 0 ) {
1125
				position.left -= overRight;
1126
 
1127
			// Adjust based on position and margin
1128
			} else {
1129
				position.left = max( position.left - collisionPosLeft, position.left );
1130
			}
1131
		},
1132
		top: function( position, data ) {
1133
			var within = data.within,
1134
				withinOffset = within.isWindow ? within.scrollTop : within.offset.top,
1135
				outerHeight = data.within.height,
1136
				collisionPosTop = position.top - data.collisionPosition.marginTop,
1137
				overTop = withinOffset - collisionPosTop,
1138
				overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
1139
				newOverBottom;
1140
 
1141
			// Element is taller than within
1142
			if ( data.collisionHeight > outerHeight ) {
1143
 
1144
				// Element is initially over the top of within
1145
				if ( overTop > 0 && overBottom <= 0 ) {
1146
					newOverBottom = position.top + overTop + data.collisionHeight - outerHeight -
1147
						withinOffset;
1148
					position.top += overTop - newOverBottom;
1149
 
1150
				// Element is initially over bottom of within
1151
				} else if ( overBottom > 0 && overTop <= 0 ) {
1152
					position.top = withinOffset;
1153
 
1154
				// Element is initially over both top and bottom of within
1155
				} else {
1156
					if ( overTop > overBottom ) {
1157
						position.top = withinOffset + outerHeight - data.collisionHeight;
1158
					} else {
1159
						position.top = withinOffset;
1160
					}
1161
				}
1162
 
1163
			// Too far up -> align with top
1164
			} else if ( overTop > 0 ) {
1165
				position.top += overTop;
1166
 
1167
			// Too far down -> align with bottom edge
1168
			} else if ( overBottom > 0 ) {
1169
				position.top -= overBottom;
1170
 
1171
			// Adjust based on position and margin
1172
			} else {
1173
				position.top = max( position.top - collisionPosTop, position.top );
1174
			}
1175
		}
1176
	},
1177
	flip: {
1178
		left: function( position, data ) {
1179
			var within = data.within,
1180
				withinOffset = within.offset.left + within.scrollLeft,
1181
				outerWidth = within.width,
1182
				offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,
1183
				collisionPosLeft = position.left - data.collisionPosition.marginLeft,
1184
				overLeft = collisionPosLeft - offsetLeft,
1185
				overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,
1186
				myOffset = data.my[ 0 ] === "left" ?
1187
					-data.elemWidth :
1188
					data.my[ 0 ] === "right" ?
1189
						data.elemWidth :
1190
						0,
1191
				atOffset = data.at[ 0 ] === "left" ?
1192
					data.targetWidth :
1193
					data.at[ 0 ] === "right" ?
1194
						-data.targetWidth :
1195
						0,
1196
				offset = -2 * data.offset[ 0 ],
1197
				newOverRight,
1198
				newOverLeft;
1199
 
1200
			if ( overLeft < 0 ) {
1201
				newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth -
1202
					outerWidth - withinOffset;
1203
				if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {
1204
					position.left += myOffset + atOffset + offset;
1205
				}
1206
			} else if ( overRight > 0 ) {
1207
				newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset +
1208
					atOffset + offset - offsetLeft;
1209
				if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {
1210
					position.left += myOffset + atOffset + offset;
1211
				}
1212
			}
1213
		},
1214
		top: function( position, data ) {
1215
			var within = data.within,
1216
				withinOffset = within.offset.top + within.scrollTop,
1217
				outerHeight = within.height,
1218
				offsetTop = within.isWindow ? within.scrollTop : within.offset.top,
1219
				collisionPosTop = position.top - data.collisionPosition.marginTop,
1220
				overTop = collisionPosTop - offsetTop,
1221
				overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,
1222
				top = data.my[ 1 ] === "top",
1223
				myOffset = top ?
1224
					-data.elemHeight :
1225
					data.my[ 1 ] === "bottom" ?
1226
						data.elemHeight :
1227
						0,
1228
				atOffset = data.at[ 1 ] === "top" ?
1229
					data.targetHeight :
1230
					data.at[ 1 ] === "bottom" ?
1231
						-data.targetHeight :
1232
						0,
1233
				offset = -2 * data.offset[ 1 ],
1234
				newOverTop,
1235
				newOverBottom;
1236
			if ( overTop < 0 ) {
1237
				newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight -
1238
					outerHeight - withinOffset;
1239
				if ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) {
1240
					position.top += myOffset + atOffset + offset;
1241
				}
1242
			} else if ( overBottom > 0 ) {
1243
				newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset +
1244
					offset - offsetTop;
1245
				if ( newOverTop > 0 || abs( newOverTop ) < overBottom ) {
1246
					position.top += myOffset + atOffset + offset;
1247
				}
1248
			}
1249
		}
1250
	},
1251
	flipfit: {
1252
		left: function() {
1253
			$.ui.position.flip.left.apply( this, arguments );
1254
			$.ui.position.fit.left.apply( this, arguments );
1255
		},
1256
		top: function() {
1257
			$.ui.position.flip.top.apply( this, arguments );
1258
			$.ui.position.fit.top.apply( this, arguments );
1259
		}
1260
	}
1261
};
1262
 
1263
} )();
1264
 
1265
var position = $.ui.position;
1266
 
1267
 
1268
/*!
1269
 * jQuery UI :data 1.14.1
1270
 * https://jqueryui.com
1271
 *
1272
 * Copyright OpenJS Foundation and other contributors
1273
 * Released under the MIT license.
1274
 * https://jquery.org/license
1275
 */
1276
 
1277
//>>label: :data Selector
1278
//>>group: Core
1279
//>>description: Selects elements which have data stored under the specified key.
1280
//>>docs: https://api.jqueryui.com/data-selector/
1281
 
1282
 
1283
var data = $.extend( $.expr.pseudos, {
1284
	data: $.expr.createPseudo( function( dataName ) {
1285
		return function( elem ) {
1286
			return !!$.data( elem, dataName );
1287
		};
1288
	} )
1289
} );
1290
 
1291
/*!
1292
 * jQuery UI Disable Selection 1.14.1
1293
 * https://jqueryui.com
1294
 *
1295
 * Copyright OpenJS Foundation and other contributors
1296
 * Released under the MIT license.
1297
 * https://jquery.org/license
1298
 */
1299
 
1300
//>>label: disableSelection
1301
//>>group: Core
1302
//>>description: Disable selection of text content within the set of matched elements.
1303
//>>docs: https://api.jqueryui.com/disableSelection/
1304
 
1305
// This file is deprecated
1306
 
1307
var disableSelection = $.fn.extend( {
1308
	disableSelection: ( function() {
1309
		var eventType = "onselectstart" in document.createElement( "div" ) ?
1310
			"selectstart" :
1311
			"mousedown";
1312
 
1313
		return function() {
1314
			return this.on( eventType + ".ui-disableSelection", function( event ) {
1315
				event.preventDefault();
1316
			} );
1317
		};
1318
	} )(),
1319
 
1320
	enableSelection: function() {
1321
		return this.off( ".ui-disableSelection" );
1322
	}
1323
} );
1324
 
1325
 
1326
 
1327
// Create a local jQuery because jQuery Color relies on it and the
1328
// global may not exist with AMD and a custom build (#10199).
1329
// This module is a noop if used as a regular AMD module.
1330
// eslint-disable-next-line no-unused-vars
1331
var jQuery = $;
1332
 
1333
 
1334
/*!
1335
 * jQuery Color Animations v3.0.0
1336
 * https://github.com/jquery/jquery-color
1337
 *
1338
 * Copyright OpenJS Foundation and other contributors
1339
 * Released under the MIT license.
1340
 * https://jquery.org/license
1341
 *
1342
 * Date: Wed May 15 16:49:44 2024 +0200
1343
 */
1344
 
1345
 
1346
	var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor " +
1347
		"borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor",
1348
 
1349
	class2type = {},
1350
	toString = class2type.toString,
1351
 
1352
	// plusequals test for += 100 -= 100
1353
	rplusequals = /^([\-+])=\s*(\d+\.?\d*)/,
1354
 
1355
	// a set of RE's that can match strings and generate color tuples.
1356
	stringParsers = [ {
1357
			re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
1358
			parse: function( execResult ) {
1359
				return [
1360
					execResult[ 1 ],
1361
					execResult[ 2 ],
1362
					execResult[ 3 ],
1363
					execResult[ 4 ]
1364
				];
1365
			}
1366
		}, {
1367
			re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
1368
			parse: function( execResult ) {
1369
				return [
1370
					execResult[ 1 ] * 2.55,
1371
					execResult[ 2 ] * 2.55,
1372
					execResult[ 3 ] * 2.55,
1373
					execResult[ 4 ]
1374
				];
1375
			}
1376
		}, {
1377
 
1378
			// this regex ignores A-F because it's compared against an already lowercased string
1379
			re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})?/,
1380
			parse: function( execResult ) {
1381
				return [
1382
					parseInt( execResult[ 1 ], 16 ),
1383
					parseInt( execResult[ 2 ], 16 ),
1384
					parseInt( execResult[ 3 ], 16 ),
1385
					execResult[ 4 ] ?
1386
						( parseInt( execResult[ 4 ], 16 ) / 255 ).toFixed( 2 ) :
1387
						1
1388
				];
1389
			}
1390
		}, {
1391
 
1392
			// this regex ignores A-F because it's compared against an already lowercased string
1393
			re: /#([a-f0-9])([a-f0-9])([a-f0-9])([a-f0-9])?/,
1394
			parse: function( execResult ) {
1395
				return [
1396
					parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ),
1397
					parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ),
1398
					parseInt( execResult[ 3 ] + execResult[ 3 ], 16 ),
1399
					execResult[ 4 ] ?
1400
						( parseInt( execResult[ 4 ] + execResult[ 4 ], 16 ) / 255 )
1401
							.toFixed( 2 ) :
1402
						1
1403
				];
1404
			}
1405
		}, {
1406
			re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
1407
			space: "hsla",
1408
			parse: function( execResult ) {
1409
				return [
1410
					execResult[ 1 ],
1411
					execResult[ 2 ] / 100,
1412
					execResult[ 3 ] / 100,
1413
					execResult[ 4 ]
1414
				];
1415
			}
1416
		} ],
1417
 
1418
	// jQuery.Color( )
1419
	color = jQuery.Color = function( color, green, blue, alpha ) {
1420
		return new jQuery.Color.fn.parse( color, green, blue, alpha );
1421
	},
1422
	spaces = {
1423
		rgba: {
1424
			props: {
1425
				red: {
1426
					idx: 0,
1427
					type: "byte"
1428
				},
1429
				green: {
1430
					idx: 1,
1431
					type: "byte"
1432
				},
1433
				blue: {
1434
					idx: 2,
1435
					type: "byte"
1436
				}
1437
			}
1438
		},
1439
 
1440
		hsla: {
1441
			props: {
1442
				hue: {
1443
					idx: 0,
1444
					type: "degrees"
1445
				},
1446
				saturation: {
1447
					idx: 1,
1448
					type: "percent"
1449
				},
1450
				lightness: {
1451
					idx: 2,
1452
					type: "percent"
1453
				}
1454
			}
1455
		}
1456
	},
1457
	propTypes = {
1458
		"byte": {
1459
			floor: true,
1460
			max: 255
1461
		},
1462
		"percent": {
1463
			max: 1
1464
		},
1465
		"degrees": {
1466
			mod: 360,
1467
			floor: true
1468
		}
1469
	},
1470
 
1471
	// colors = jQuery.Color.names
1472
	colors,
1473
 
1474
	// local aliases of functions called often
1475
	each = jQuery.each;
1476
 
1477
// define cache name and alpha properties
1478
// for rgba and hsla spaces
1479
each( spaces, function( spaceName, space ) {
1480
	space.cache = "_" + spaceName;
1481
	space.props.alpha = {
1482
		idx: 3,
1483
		type: "percent",
1484
		def: 1
1485
	};
1486
} );
1487
 
1488
// Populate the class2type map
1489
jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ),
1490
	function( _i, name ) {
1491
		class2type[ "[object " + name + "]" ] = name.toLowerCase();
1492
	} );
1493
 
1494
function getType( obj ) {
1495
	if ( obj == null ) {
1496
		return obj + "";
1497
	}
1498
 
1499
	return typeof obj === "object" ?
1500
		class2type[ toString.call( obj ) ] || "object" :
1501
		typeof obj;
1502
}
1503
 
1504
function clamp( value, prop, allowEmpty ) {
1505
	var type = propTypes[ prop.type ] || {};
1506
 
1507
	if ( value == null ) {
1508
		return ( allowEmpty || !prop.def ) ? null : prop.def;
1509
	}
1510
 
1511
	// ~~ is an short way of doing floor for positive numbers
1512
	value = type.floor ? ~~value : parseFloat( value );
1513
 
1514
	if ( type.mod ) {
1515
 
1516
		// we add mod before modding to make sure that negatives values
1517
		// get converted properly: -10 -> 350
1518
		return ( value + type.mod ) % type.mod;
1519
	}
1520
 
1521
	// for now all property types without mod have min and max
1522
	return Math.min( type.max, Math.max( 0, value ) );
1523
}
1524
 
1525
function stringParse( string ) {
1526
	var inst = color(),
1527
		rgba = inst._rgba = [];
1528
 
1529
	string = string.toLowerCase();
1530
 
1531
	each( stringParsers, function( _i, parser ) {
1532
		var parsed,
1533
			match = parser.re.exec( string ),
1534
			values = match && parser.parse( match ),
1535
			spaceName = parser.space || "rgba";
1536
 
1537
		if ( values ) {
1538
			parsed = inst[ spaceName ]( values );
1539
 
1540
			// if this was an rgba parse the assignment might happen twice
1541
			// oh well....
1542
			inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ];
1543
			rgba = inst._rgba = parsed._rgba;
1544
 
1545
			// exit each( stringParsers ) here because we matched
1546
			return false;
1547
		}
1548
	} );
1549
 
1550
	// Found a stringParser that handled it
1551
	if ( rgba.length ) {
1552
 
1553
		// if this came from a parsed string, force "transparent" when alpha is 0
1554
		// chrome, (and maybe others) return "transparent" as rgba(0,0,0,0)
1555
		if ( rgba.join() === "0,0,0,0" ) {
1556
			jQuery.extend( rgba, colors.transparent );
1557
		}
1558
		return inst;
1559
	}
1560
 
1561
	// named colors
1562
	return colors[ string ];
1563
}
1564
 
1565
color.fn = jQuery.extend( color.prototype, {
1566
	parse: function( red, green, blue, alpha ) {
1567
		if ( red === undefined ) {
1568
			this._rgba = [ null, null, null, null ];
1569
			return this;
1570
		}
1571
		if ( red.jquery || red.nodeType ) {
1572
			red = jQuery( red ).css( green );
1573
			green = undefined;
1574
		}
1575
 
1576
		var inst = this,
1577
			type = getType( red ),
1578
			rgba = this._rgba = [];
1579
 
1580
		// more than 1 argument specified - assume ( red, green, blue, alpha )
1581
		if ( green !== undefined ) {
1582
			red = [ red, green, blue, alpha ];
1583
			type = "array";
1584
		}
1585
 
1586
		if ( type === "string" ) {
1587
			return this.parse( stringParse( red ) || colors._default );
1588
		}
1589
 
1590
		if ( type === "array" ) {
1591
			each( spaces.rgba.props, function( _key, prop ) {
1592
				rgba[ prop.idx ] = clamp( red[ prop.idx ], prop );
1593
			} );
1594
			return this;
1595
		}
1596
 
1597
		if ( type === "object" ) {
1598
			if ( red instanceof color ) {
1599
				each( spaces, function( _spaceName, space ) {
1600
					if ( red[ space.cache ] ) {
1601
						inst[ space.cache ] = red[ space.cache ].slice();
1602
					}
1603
				} );
1604
			} else {
1605
				each( spaces, function( _spaceName, space ) {
1606
					var cache = space.cache;
1607
					each( space.props, function( key, prop ) {
1608
 
1609
						// if the cache doesn't exist, and we know how to convert
1610
						if ( !inst[ cache ] && space.to ) {
1611
 
1612
							// if the value was null, we don't need to copy it
1613
							// if the key was alpha, we don't need to copy it either
1614
							if ( key === "alpha" || red[ key ] == null ) {
1615
								return;
1616
							}
1617
							inst[ cache ] = space.to( inst._rgba );
1618
						}
1619
 
1620
						// this is the only case where we allow nulls for ALL properties.
1621
						// call clamp with alwaysAllowEmpty
1622
						inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true );
1623
					} );
1624
 
1625
					// everything defined but alpha?
1626
					if ( inst[ cache ] && jQuery.inArray(
1627
						null,
1628
						inst[ cache ].slice( 0, 3 )
1629
					) < 0 ) {
1630
 
1631
						// use the default of 1
1632
						if ( inst[ cache ][ 3 ] == null ) {
1633
							inst[ cache ][ 3 ] = 1;
1634
						}
1635
 
1636
						if ( space.from ) {
1637
							inst._rgba = space.from( inst[ cache ] );
1638
						}
1639
					}
1640
				} );
1641
			}
1642
			return this;
1643
		}
1644
	},
1645
	is: function( compare ) {
1646
		var is = color( compare ),
1647
			same = true,
1648
			inst = this;
1649
 
1650
		each( spaces, function( _, space ) {
1651
			var localCache,
1652
				isCache = is[ space.cache ];
1653
			if ( isCache ) {
1654
				localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || [];
1655
				each( space.props, function( _, prop ) {
1656
					if ( isCache[ prop.idx ] != null ) {
1657
						same = ( isCache[ prop.idx ] === localCache[ prop.idx ] );
1658
						return same;
1659
					}
1660
				} );
1661
			}
1662
			return same;
1663
		} );
1664
		return same;
1665
	},
1666
	_space: function() {
1667
		var used = [],
1668
			inst = this;
1669
		each( spaces, function( spaceName, space ) {
1670
			if ( inst[ space.cache ] ) {
1671
				used.push( spaceName );
1672
			}
1673
		} );
1674
		return used.pop();
1675
	},
1676
	transition: function( other, distance ) {
1677
		var end = color( other ),
1678
			spaceName = end._space(),
1679
			space = spaces[ spaceName ],
1680
			startColor = this.alpha() === 0 ? color( "transparent" ) : this,
1681
			start = startColor[ space.cache ] || space.to( startColor._rgba ),
1682
			result = start.slice();
1683
 
1684
		end = end[ space.cache ];
1685
		each( space.props, function( _key, prop ) {
1686
			var index = prop.idx,
1687
				startValue = start[ index ],
1688
				endValue = end[ index ],
1689
				type = propTypes[ prop.type ] || {};
1690
 
1691
			// if null, don't override start value
1692
			if ( endValue === null ) {
1693
				return;
1694
			}
1695
 
1696
			// if null - use end
1697
			if ( startValue === null ) {
1698
				result[ index ] = endValue;
1699
			} else {
1700
				if ( type.mod ) {
1701
					if ( endValue - startValue > type.mod / 2 ) {
1702
						startValue += type.mod;
1703
					} else if ( startValue - endValue > type.mod / 2 ) {
1704
						startValue -= type.mod;
1705
					}
1706
				}
1707
				result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop );
1708
			}
1709
		} );
1710
		return this[ spaceName ]( result );
1711
	},
1712
	blend: function( opaque ) {
1713
 
1714
		// if we are already opaque - return ourself
1715
		if ( this._rgba[ 3 ] === 1 ) {
1716
			return this;
1717
		}
1718
 
1719
		var rgb = this._rgba.slice(),
1720
			a = rgb.pop(),
1721
			blend = color( opaque )._rgba;
1722
 
1723
		return color( jQuery.map( rgb, function( v, i ) {
1724
			return ( 1 - a ) * blend[ i ] + a * v;
1725
		} ) );
1726
	},
1727
	toRgbaString: function() {
1728
		var prefix = "rgba(",
1729
			rgba = jQuery.map( this._rgba, function( v, i ) {
1730
				if ( v != null ) {
1731
					return v;
1732
				}
1733
				return i > 2 ? 1 : 0;
1734
			} );
1735
 
1736
		if ( rgba[ 3 ] === 1 ) {
1737
			rgba.pop();
1738
			prefix = "rgb(";
1739
		}
1740
 
1741
		return prefix + rgba.join( ", " ) + ")";
1742
	},
1743
	toHslaString: function() {
1744
		var prefix = "hsla(",
1745
			hsla = jQuery.map( this.hsla(), function( v, i ) {
1746
				if ( v == null ) {
1747
					v = i > 2 ? 1 : 0;
1748
				}
1749
 
1750
				// catch 1 and 2
1751
				if ( i && i < 3 ) {
1752
					v = Math.round( v * 100 ) + "%";
1753
				}
1754
				return v;
1755
			} );
1756
 
1757
		if ( hsla[ 3 ] === 1 ) {
1758
			hsla.pop();
1759
			prefix = "hsl(";
1760
		}
1761
		return prefix + hsla.join( ", " ) + ")";
1762
	},
1763
	toHexString: function( includeAlpha ) {
1764
		var rgba = this._rgba.slice(),
1765
			alpha = rgba.pop();
1766
 
1767
		if ( includeAlpha ) {
1768
			rgba.push( ~~( alpha * 255 ) );
1769
		}
1770
 
1771
		return "#" + jQuery.map( rgba, function( v ) {
1772
 
1773
			// default to 0 when nulls exist
1774
			return ( "0" + ( v || 0 ).toString( 16 ) ).substr( -2 );
1775
		} ).join( "" );
1776
	},
1777
	toString: function() {
1778
		return this.toRgbaString();
1779
	}
1780
} );
1781
color.fn.parse.prototype = color.fn;
1782
 
1783
// hsla conversions adapted from:
1784
// https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021
1785
 
1786
function hue2rgb( p, q, h ) {
1787
	h = ( h + 1 ) % 1;
1788
	if ( h * 6 < 1 ) {
1789
		return p + ( q - p ) * h * 6;
1790
	}
1791
	if ( h * 2 < 1 ) {
1792
		return q;
1793
	}
1794
	if ( h * 3 < 2 ) {
1795
		return p + ( q - p ) * ( ( 2 / 3 ) - h ) * 6;
1796
	}
1797
	return p;
1798
}
1799
 
1800
spaces.hsla.to = function( rgba ) {
1801
	if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) {
1802
		return [ null, null, null, rgba[ 3 ] ];
1803
	}
1804
	var r = rgba[ 0 ] / 255,
1805
		g = rgba[ 1 ] / 255,
1806
		b = rgba[ 2 ] / 255,
1807
		a = rgba[ 3 ],
1808
		max = Math.max( r, g, b ),
1809
		min = Math.min( r, g, b ),
1810
		diff = max - min,
1811
		add = max + min,
1812
		l = add * 0.5,
1813
		h, s;
1814
 
1815
	if ( min === max ) {
1816
		h = 0;
1817
	} else if ( r === max ) {
1818
		h = ( 60 * ( g - b ) / diff ) + 360;
1819
	} else if ( g === max ) {
1820
		h = ( 60 * ( b - r ) / diff ) + 120;
1821
	} else {
1822
		h = ( 60 * ( r - g ) / diff ) + 240;
1823
	}
1824
 
1825
	// chroma (diff) == 0 means greyscale which, by definition, saturation = 0%
1826
	// otherwise, saturation is based on the ratio of chroma (diff) to lightness (add)
1827
	if ( diff === 0 ) {
1828
		s = 0;
1829
	} else if ( l <= 0.5 ) {
1830
		s = diff / add;
1831
	} else {
1832
		s = diff / ( 2 - add );
1833
	}
1834
	return [ Math.round( h ) % 360, s, l, a == null ? 1 : a ];
1835
};
1836
 
1837
spaces.hsla.from = function( hsla ) {
1838
	if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) {
1839
		return [ null, null, null, hsla[ 3 ] ];
1840
	}
1841
	var h = hsla[ 0 ] / 360,
1842
		s = hsla[ 1 ],
1843
		l = hsla[ 2 ],
1844
		a = hsla[ 3 ],
1845
		q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s,
1846
		p = 2 * l - q;
1847
 
1848
	return [
1849
		Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ),
1850
		Math.round( hue2rgb( p, q, h ) * 255 ),
1851
		Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ),
1852
		a
1853
	];
1854
};
1855
 
1856
 
1857
each( spaces, function( spaceName, space ) {
1858
	var props = space.props,
1859
		cache = space.cache,
1860
		to = space.to,
1861
		from = space.from;
1862
 
1863
	// makes rgba() and hsla()
1864
	color.fn[ spaceName ] = function( value ) {
1865
 
1866
		// generate a cache for this space if it doesn't exist
1867
		if ( to && !this[ cache ] ) {
1868
			this[ cache ] = to( this._rgba );
1869
		}
1870
		if ( value === undefined ) {
1871
			return this[ cache ].slice();
1872
		}
1873
 
1874
		var ret,
1875
			type = getType( value ),
1876
			arr = ( type === "array" || type === "object" ) ? value : arguments,
1877
			local = this[ cache ].slice();
1878
 
1879
		each( props, function( key, prop ) {
1880
			var val = arr[ type === "object" ? key : prop.idx ];
1881
			if ( val == null ) {
1882
				val = local[ prop.idx ];
1883
			}
1884
			local[ prop.idx ] = clamp( val, prop );
1885
		} );
1886
 
1887
		if ( from ) {
1888
			ret = color( from( local ) );
1889
			ret[ cache ] = local;
1890
			return ret;
1891
		} else {
1892
			return color( local );
1893
		}
1894
	};
1895
 
1896
	// makes red() green() blue() alpha() hue() saturation() lightness()
1897
	each( props, function( key, prop ) {
1898
 
1899
		// alpha is included in more than one space
1900
		if ( color.fn[ key ] ) {
1901
			return;
1902
		}
1903
		color.fn[ key ] = function( value ) {
1904
			var local, cur, match, fn,
1905
				vtype = getType( value );
1906
 
1907
			if ( key === "alpha" ) {
1908
				fn = this._hsla ? "hsla" : "rgba";
1909
			} else {
1910
				fn = spaceName;
1911
			}
1912
			local = this[ fn ]();
1913
			cur = local[ prop.idx ];
1914
 
1915
			if ( vtype === "undefined" ) {
1916
				return cur;
1917
			}
1918
 
1919
			if ( vtype === "function" ) {
1920
				value = value.call( this, cur );
1921
				vtype = getType( value );
1922
			}
1923
			if ( value == null && prop.empty ) {
1924
				return this;
1925
			}
1926
			if ( vtype === "string" ) {
1927
				match = rplusequals.exec( value );
1928
				if ( match ) {
1929
					value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 );
1930
				}
1931
			}
1932
			local[ prop.idx ] = value;
1933
			return this[ fn ]( local );
1934
		};
1935
	} );
1936
} );
1937
 
1938
// add cssHook and .fx.step function for each named hook.
1939
// accept a space separated string of properties
1940
color.hook = function( hook ) {
1941
	var hooks = hook.split( " " );
1942
	each( hooks, function( _i, hook ) {
1943
		jQuery.cssHooks[ hook ] = {
1944
			set: function( elem, value ) {
1945
				var parsed;
1946
 
1947
				if ( value !== "transparent" &&
1948
					( getType( value ) !== "string" ||
1949
						( parsed = stringParse( value ) ) ) ) {
1950
					value = color( parsed || value );
1951
					value = value.toRgbaString();
1952
				}
1953
				elem.style[ hook ] = value;
1954
			}
1955
		};
1956
		jQuery.fx.step[ hook ] = function( fx ) {
1957
			if ( !fx.colorInit ) {
1958
				fx.start = color( fx.elem, hook );
1959
				fx.end = color( fx.end );
1960
				fx.colorInit = true;
1961
			}
1962
			jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) );
1963
		};
1964
	} );
1965
 
1966
};
1967
 
1968
color.hook( stepHooks );
1969
 
1970
jQuery.cssHooks.borderColor = {
1971
	expand: function( value ) {
1972
		var expanded = {};
1973
 
1974
		each( [ "Top", "Right", "Bottom", "Left" ], function( _i, part ) {
1975
			expanded[ "border" + part + "Color" ] = value;
1976
		} );
1977
		return expanded;
1978
	}
1979
};
1980
 
1981
// Basic color names only.
1982
// Usage of any of the other color names requires adding yourself or including
1983
// jquery.color.svg-names.js.
1984
colors = jQuery.Color.names = {
1985
 
1986
	// 4.1. Basic color keywords
1987
	aqua: "#00ffff",
1988
	black: "#000000",
1989
	blue: "#0000ff",
1990
	fuchsia: "#ff00ff",
1991
	gray: "#808080",
1992
	green: "#008000",
1993
	lime: "#00ff00",
1994
	maroon: "#800000",
1995
	navy: "#000080",
1996
	olive: "#808000",
1997
	purple: "#800080",
1998
	red: "#ff0000",
1999
	silver: "#c0c0c0",
2000
	teal: "#008080",
2001
	white: "#ffffff",
2002
	yellow: "#ffff00",
2003
 
2004
	// 4.2.3. "transparent" color keyword
2005
	transparent: [ null, null, null, 0 ],
2006
 
2007
	_default: "#ffffff"
2008
};
2009
 
2010
 
2011
/*!
2012
 * jQuery UI Effects 1.14.1
2013
 * https://jqueryui.com
2014
 *
2015
 * Copyright OpenJS Foundation and other contributors
2016
 * Released under the MIT license.
2017
 * https://jquery.org/license
2018
 */
2019
 
2020
//>>label: Effects Core
2021
//>>group: Effects
2022
/* eslint-disable max-len */
2023
//>>description: Extends the internal jQuery effects. Includes morphing and easing. Required by all other effects.
2024
/* eslint-enable max-len */
2025
//>>docs: https://api.jqueryui.com/category/effects-core/
2026
//>>demos: https://jqueryui.com/effect/
2027
 
2028
 
2029
var dataSpace = "ui-effects-",
2030
	dataSpaceStyle = "ui-effects-style",
2031
	dataSpaceAnimated = "ui-effects-animated";
2032
 
2033
$.effects = {
2034
	effect: {}
2035
};
2036
 
2037
/******************************************************************************/
2038
/****************************** CLASS ANIMATIONS ******************************/
2039
/******************************************************************************/
2040
( function() {
2041
 
2042
var classAnimationActions = [ "add", "remove", "toggle" ],
2043
	shorthandStyles = {
2044
		border: 1,
2045
		borderBottom: 1,
2046
		borderColor: 1,
2047
		borderLeft: 1,
2048
		borderRight: 1,
2049
		borderTop: 1,
2050
		borderWidth: 1,
2051
		margin: 1,
2052
		padding: 1
2053
	};
2054
 
2055
$.each(
2056
	[ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ],
2057
	function( _, prop ) {
2058
		$.fx.step[ prop ] = function( fx ) {
2059
			if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) {
2060
				jQuery.style( fx.elem, prop, fx.end );
2061
				fx.setAttr = true;
2062
			}
2063
		};
2064
	}
2065
);
2066
 
2067
function camelCase( string ) {
2068
	return string.replace( /-([\da-z])/gi, function( all, letter ) {
2069
		return letter.toUpperCase();
2070
	} );
2071
}
2072
 
2073
function getElementStyles( elem ) {
2074
	var key, len,
2075
		style = elem.ownerDocument.defaultView.getComputedStyle( elem ),
2076
		styles = {};
2077
 
2078
	len = style.length;
2079
	while ( len-- ) {
2080
		key = style[ len ];
2081
		if ( typeof style[ key ] === "string" ) {
2082
			styles[ camelCase( key ) ] = style[ key ];
2083
		}
2084
	}
2085
 
2086
	return styles;
2087
}
2088
 
2089
function styleDifference( oldStyle, newStyle ) {
2090
	var diff = {},
2091
		name, value;
2092
 
2093
	for ( name in newStyle ) {
2094
		value = newStyle[ name ];
2095
		if ( oldStyle[ name ] !== value ) {
2096
			if ( !shorthandStyles[ name ] ) {
2097
				if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) {
2098
					diff[ name ] = value;
2099
				}
2100
			}
2101
		}
2102
	}
2103
 
2104
	return diff;
2105
}
2106
 
2107
$.effects.animateClass = function( value, duration, easing, callback ) {
2108
	var o = $.speed( duration, easing, callback );
2109
 
2110
	return this.queue( function() {
2111
		var animated = $( this ),
2112
			baseClass = animated.attr( "class" ) || "",
2113
			applyClassChange,
2114
			allAnimations = o.children ? animated.find( "*" ).addBack() : animated;
2115
 
2116
		// Map the animated objects to store the original styles.
2117
		allAnimations = allAnimations.map( function() {
2118
			var el = $( this );
2119
			return {
2120
				el: el,
2121
				start: getElementStyles( this )
2122
			};
2123
		} );
2124
 
2125
		// Apply class change
2126
		applyClassChange = function() {
2127
			$.each( classAnimationActions, function( i, action ) {
2128
				if ( value[ action ] ) {
2129
					animated[ action + "Class" ]( value[ action ] );
2130
				}
2131
			} );
2132
		};
2133
		applyClassChange();
2134
 
2135
		// Map all animated objects again - calculate new styles and diff
2136
		allAnimations = allAnimations.map( function() {
2137
			this.end = getElementStyles( this.el[ 0 ] );
2138
			this.diff = styleDifference( this.start, this.end );
2139
			return this;
2140
		} );
2141
 
2142
		// Apply original class
2143
		animated.attr( "class", baseClass );
2144
 
2145
		// Map all animated objects again - this time collecting a promise
2146
		allAnimations = allAnimations.map( function() {
2147
			var styleInfo = this,
2148
				dfd = $.Deferred(),
2149
				opts = $.extend( {}, o, {
2150
					queue: false,
2151
					complete: function() {
2152
						dfd.resolve( styleInfo );
2153
					}
2154
				} );
2155
 
2156
			this.el.animate( this.diff, opts );
2157
			return dfd.promise();
2158
		} );
2159
 
2160
		// Once all animations have completed:
2161
		$.when.apply( $, allAnimations.get() ).done( function() {
2162
 
2163
			// Set the final class
2164
			applyClassChange();
2165
 
2166
			// For each animated element,
2167
			// clear all css properties that were animated
2168
			$.each( arguments, function() {
2169
				var el = this.el;
2170
				$.each( this.diff, function( key ) {
2171
					el.css( key, "" );
2172
				} );
2173
			} );
2174
 
2175
			// This is guarnteed to be there if you use jQuery.speed()
2176
			// it also handles dequeuing the next anim...
2177
			o.complete.call( animated[ 0 ] );
2178
		} );
2179
	} );
2180
};
2181
 
2182
$.fn.extend( {
2183
	addClass: ( function( orig ) {
2184
		return function( classNames, speed, easing, callback ) {
2185
			return speed ?
2186
				$.effects.animateClass.call( this,
2187
					{ add: classNames }, speed, easing, callback ) :
2188
				orig.apply( this, arguments );
2189
		};
2190
	} )( $.fn.addClass ),
2191
 
2192
	removeClass: ( function( orig ) {
2193
		return function( classNames, speed, easing, callback ) {
2194
			return arguments.length > 1 ?
2195
				$.effects.animateClass.call( this,
2196
					{ remove: classNames }, speed, easing, callback ) :
2197
				orig.apply( this, arguments );
2198
		};
2199
	} )( $.fn.removeClass ),
2200
 
2201
	toggleClass: ( function( orig ) {
2202
		return function( classNames, force, speed, easing, callback ) {
2203
			if ( typeof force === "boolean" || force === undefined ) {
2204
				if ( !speed ) {
2205
 
2206
					// Without speed parameter
2207
					return orig.apply( this, arguments );
2208
				} else {
2209
					return $.effects.animateClass.call( this,
2210
						( force ? { add: classNames } : { remove: classNames } ),
2211
						speed, easing, callback );
2212
				}
2213
			} else {
2214
 
2215
				// Without force parameter
2216
				return $.effects.animateClass.call( this,
2217
					{ toggle: classNames }, force, speed, easing );
2218
			}
2219
		};
2220
	} )( $.fn.toggleClass ),
2221
 
2222
	switchClass: function( remove, add, speed, easing, callback ) {
2223
		return $.effects.animateClass.call( this, {
2224
			add: add,
2225
			remove: remove
2226
		}, speed, easing, callback );
2227
	}
2228
} );
2229
 
2230
} )();
2231
 
2232
/******************************************************************************/
2233
/*********************************** EFFECTS **********************************/
2234
/******************************************************************************/
2235
 
2236
( function() {
2237
 
2238
if ( $.expr && $.expr.pseudos && $.expr.pseudos.animated ) {
2239
	$.expr.pseudos.animated = ( function( orig ) {
2240
		return function( elem ) {
2241
			return !!$( elem ).data( dataSpaceAnimated ) || orig( elem );
2242
		};
2243
	} )( $.expr.pseudos.animated );
2244
}
2245
 
2246
if ( $.uiBackCompat === true ) {
2247
	$.extend( $.effects, {
2248
 
2249
		// Saves a set of properties in a data storage
2250
		save: function( element, set ) {
2251
			var i = 0, length = set.length;
2252
			for ( ; i < length; i++ ) {
2253
				if ( set[ i ] !== null ) {
2254
					element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] );
2255
				}
2256
			}
2257
		},
2258
 
2259
		// Restores a set of previously saved properties from a data storage
2260
		restore: function( element, set ) {
2261
			var val, i = 0, length = set.length;
2262
			for ( ; i < length; i++ ) {
2263
				if ( set[ i ] !== null ) {
2264
					val = element.data( dataSpace + set[ i ] );
2265
					element.css( set[ i ], val );
2266
				}
2267
			}
2268
		},
2269
 
2270
		setMode: function( el, mode ) {
2271
			if ( mode === "toggle" ) {
2272
				mode = el.is( ":hidden" ) ? "show" : "hide";
2273
			}
2274
			return mode;
2275
		},
2276
 
2277
		// Wraps the element around a wrapper that copies position properties
2278
		createWrapper: function( element ) {
2279
 
2280
			// If the element is already wrapped, return it
2281
			if ( element.parent().is( ".ui-effects-wrapper" ) ) {
2282
				return element.parent();
2283
			}
2284
 
2285
			// Wrap the element
2286
			var props = {
2287
					width: element.outerWidth( true ),
2288
					height: element.outerHeight( true ),
2289
					"float": element.css( "float" )
2290
				},
2291
				wrapper = $( "<div></div>" )
2292
					.addClass( "ui-effects-wrapper" )
2293
					.css( {
2294
						fontSize: "100%",
2295
						background: "transparent",
2296
						border: "none",
2297
						margin: 0,
2298
						padding: 0
2299
					} ),
2300
 
2301
				// Store the size in case width/height are defined in % - Fixes #5245
2302
				size = {
2303
					width: element.width(),
2304
					height: element.height()
2305
				},
2306
				active = document.activeElement;
2307
 
2308
			// Support: Firefox
2309
			// Firefox incorrectly exposes anonymous content
2310
			// https://bugzilla.mozilla.org/show_bug.cgi?id=561664
2311
			try {
2312
				// eslint-disable-next-line no-unused-expressions
2313
				active.id;
2314
			} catch ( e ) {
2315
				active = document.body;
2316
			}
2317
 
2318
			element.wrap( wrapper );
2319
 
2320
			// Fixes #7595 - Elements lose focus when wrapped.
2321
			if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
2322
				$( active ).trigger( "focus" );
2323
			}
2324
 
2325
			// Hotfix for jQuery 1.4 since some change in wrap() seems to actually
2326
			// lose the reference to the wrapped element
2327
			wrapper = element.parent();
2328
 
2329
			// Transfer positioning properties to the wrapper
2330
			if ( element.css( "position" ) === "static" ) {
2331
				wrapper.css( { position: "relative" } );
2332
				element.css( { position: "relative" } );
2333
			} else {
2334
				$.extend( props, {
2335
					position: element.css( "position" ),
2336
					zIndex: element.css( "z-index" )
2337
				} );
2338
				$.each( [ "top", "left", "bottom", "right" ], function( i, pos ) {
2339
					props[ pos ] = element.css( pos );
2340
					if ( isNaN( parseInt( props[ pos ], 10 ) ) ) {
2341
						props[ pos ] = "auto";
2342
					}
2343
				} );
2344
				element.css( {
2345
					position: "relative",
2346
					top: 0,
2347
					left: 0,
2348
					right: "auto",
2349
					bottom: "auto"
2350
				} );
2351
			}
2352
			element.css( size );
2353
 
2354
			return wrapper.css( props ).show();
2355
		},
2356
 
2357
		removeWrapper: function( element ) {
2358
			var active = document.activeElement;
2359
 
2360
			if ( element.parent().is( ".ui-effects-wrapper" ) ) {
2361
				element.parent().replaceWith( element );
2362
 
2363
				// Fixes #7595 - Elements lose focus when wrapped.
2364
				if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
2365
					$( active ).trigger( "focus" );
2366
				}
2367
			}
2368
 
2369
			return element;
2370
		}
2371
	} );
2372
}
2373
 
2374
$.extend( $.effects, {
2375
	version: "1.14.1",
2376
 
2377
	define: function( name, mode, effect ) {
2378
		if ( !effect ) {
2379
			effect = mode;
2380
			mode = "effect";
2381
		}
2382
 
2383
		$.effects.effect[ name ] = effect;
2384
		$.effects.effect[ name ].mode = mode;
2385
 
2386
		return effect;
2387
	},
2388
 
2389
	scaledDimensions: function( element, percent, direction ) {
2390
		if ( percent === 0 ) {
2391
			return {
2392
				height: 0,
2393
				width: 0,
2394
				outerHeight: 0,
2395
				outerWidth: 0
2396
			};
2397
		}
2398
 
2399
		var x = direction !== "horizontal" ? ( ( percent || 100 ) / 100 ) : 1,
2400
			y = direction !== "vertical" ? ( ( percent || 100 ) / 100 ) : 1;
2401
 
2402
		return {
2403
			height: element.height() * y,
2404
			width: element.width() * x,
2405
			outerHeight: element.outerHeight() * y,
2406
			outerWidth: element.outerWidth() * x
2407
		};
2408
 
2409
	},
2410
 
2411
	clipToBox: function( animation ) {
2412
		return {
2413
			width: animation.clip.right - animation.clip.left,
2414
			height: animation.clip.bottom - animation.clip.top,
2415
			left: animation.clip.left,
2416
			top: animation.clip.top
2417
		};
2418
	},
2419
 
2420
	// Injects recently queued functions to be first in line (after "inprogress")
2421
	unshift: function( element, queueLength, count ) {
2422
		var queue = element.queue();
2423
 
2424
		if ( queueLength > 1 ) {
2425
			queue.splice.apply( queue,
2426
				[ 1, 0 ].concat( queue.splice( queueLength, count ) ) );
2427
		}
2428
		element.dequeue();
2429
	},
2430
 
2431
	saveStyle: function( element ) {
2432
		element.data( dataSpaceStyle, element[ 0 ].style.cssText );
2433
	},
2434
 
2435
	restoreStyle: function( element ) {
2436
		element[ 0 ].style.cssText = element.data( dataSpaceStyle ) || "";
2437
		element.removeData( dataSpaceStyle );
2438
	},
2439
 
2440
	mode: function( element, mode ) {
2441
		var hidden = element.is( ":hidden" );
2442
 
2443
		if ( mode === "toggle" ) {
2444
			mode = hidden ? "show" : "hide";
2445
		}
2446
		if ( hidden ? mode === "hide" : mode === "show" ) {
2447
			mode = "none";
2448
		}
2449
		return mode;
2450
	},
2451
 
2452
	// Translates a [top,left] array into a baseline value
2453
	getBaseline: function( origin, original ) {
2454
		var y, x;
2455
 
2456
		switch ( origin[ 0 ] ) {
2457
		case "top":
2458
			y = 0;
2459
			break;
2460
		case "middle":
2461
			y = 0.5;
2462
			break;
2463
		case "bottom":
2464
			y = 1;
2465
			break;
2466
		default:
2467
			y = origin[ 0 ] / original.height;
2468
		}
2469
 
2470
		switch ( origin[ 1 ] ) {
2471
		case "left":
2472
			x = 0;
2473
			break;
2474
		case "center":
2475
			x = 0.5;
2476
			break;
2477
		case "right":
2478
			x = 1;
2479
			break;
2480
		default:
2481
			x = origin[ 1 ] / original.width;
2482
		}
2483
 
2484
		return {
2485
			x: x,
2486
			y: y
2487
		};
2488
	},
2489
 
2490
	// Creates a placeholder element so that the original element can be made absolute
2491
	createPlaceholder: function( element ) {
2492
		var placeholder,
2493
			cssPosition = element.css( "position" ),
2494
			position = element.position();
2495
 
2496
		// Lock in margins first to account for form elements, which
2497
		// will change margin if you explicitly set height
2498
		// see: https://jsfiddle.net/JZSMt/3/ https://bugs.webkit.org/show_bug.cgi?id=107380
2499
		// Support: Safari
2500
		element.css( {
2501
			marginTop: element.css( "marginTop" ),
2502
			marginBottom: element.css( "marginBottom" ),
2503
			marginLeft: element.css( "marginLeft" ),
2504
			marginRight: element.css( "marginRight" )
2505
		} )
2506
		.outerWidth( element.outerWidth() )
2507
		.outerHeight( element.outerHeight() );
2508
 
2509
		if ( /^(static|relative)/.test( cssPosition ) ) {
2510
			cssPosition = "absolute";
2511
 
2512
			placeholder = $( "<" + element[ 0 ].nodeName + ">" ).insertAfter( element ).css( {
2513
 
2514
				// Convert inline to inline block to account for inline elements
2515
				// that turn to inline block based on content (like img)
2516
				display: /^(inline|ruby)/.test( element.css( "display" ) ) ?
2517
					"inline-block" :
2518
					"block",
2519
				visibility: "hidden",
2520
 
2521
				// Margins need to be set to account for margin collapse
2522
				marginTop: element.css( "marginTop" ),
2523
				marginBottom: element.css( "marginBottom" ),
2524
				marginLeft: element.css( "marginLeft" ),
2525
				marginRight: element.css( "marginRight" ),
2526
				"float": element.css( "float" )
2527
			} )
2528
			.outerWidth( element.outerWidth() )
2529
			.outerHeight( element.outerHeight() )
2530
			.addClass( "ui-effects-placeholder" );
2531
 
2532
			element.data( dataSpace + "placeholder", placeholder );
2533
		}
2534
 
2535
		element.css( {
2536
			position: cssPosition,
2537
			left: position.left,
2538
			top: position.top
2539
		} );
2540
 
2541
		return placeholder;
2542
	},
2543
 
2544
	removePlaceholder: function( element ) {
2545
		var dataKey = dataSpace + "placeholder",
2546
				placeholder = element.data( dataKey );
2547
 
2548
		if ( placeholder ) {
2549
			placeholder.remove();
2550
			element.removeData( dataKey );
2551
		}
2552
	},
2553
 
2554
	// Removes a placeholder if it exists and restores
2555
	// properties that were modified during placeholder creation
2556
	cleanUp: function( element ) {
2557
		$.effects.restoreStyle( element );
2558
		$.effects.removePlaceholder( element );
2559
	},
2560
 
2561
	setTransition: function( element, list, factor, value ) {
2562
		value = value || {};
2563
		$.each( list, function( i, x ) {
2564
			var unit = element.cssUnit( x );
2565
			if ( unit[ 0 ] > 0 ) {
2566
				value[ x ] = unit[ 0 ] * factor + unit[ 1 ];
2567
			}
2568
		} );
2569
		return value;
2570
	}
2571
} );
2572
 
2573
// Return an effect options object for the given parameters:
2574
function _normalizeArguments( effect, options, speed, callback ) {
2575
 
2576
	// Allow passing all options as the first parameter
2577
	if ( $.isPlainObject( effect ) ) {
2578
		options = effect;
2579
		effect = effect.effect;
2580
	}
2581
 
2582
	// Convert to an object
2583
	effect = { effect: effect };
2584
 
2585
	// Catch (effect, null, ...)
2586
	if ( options == null ) {
2587
		options = {};
2588
	}
2589
 
2590
	// Catch (effect, callback)
2591
	if ( typeof options === "function" ) {
2592
		callback = options;
2593
		speed = null;
2594
		options = {};
2595
	}
2596
 
2597
	// Catch (effect, speed, ?)
2598
	if ( typeof options === "number" || $.fx.speeds[ options ] ) {
2599
		callback = speed;
2600
		speed = options;
2601
		options = {};
2602
	}
2603
 
2604
	// Catch (effect, options, callback)
2605
	if ( typeof speed === "function" ) {
2606
		callback = speed;
2607
		speed = null;
2608
	}
2609
 
2610
	// Add options to effect
2611
	if ( options ) {
2612
		$.extend( effect, options );
2613
	}
2614
 
2615
	speed = speed || options.duration;
2616
	effect.duration = $.fx.off ? 0 :
2617
		typeof speed === "number" ? speed :
2618
		speed in $.fx.speeds ? $.fx.speeds[ speed ] :
2619
		$.fx.speeds._default;
2620
 
2621
	effect.complete = callback || options.complete;
2622
 
2623
	return effect;
2624
}
2625
 
2626
function standardAnimationOption( option ) {
2627
 
2628
	// Valid standard speeds (nothing, number, named speed)
2629
	if ( !option || typeof option === "number" || $.fx.speeds[ option ] ) {
2630
		return true;
2631
	}
2632
 
2633
	// Invalid strings - treat as "normal" speed
2634
	if ( typeof option === "string" && !$.effects.effect[ option ] ) {
2635
		return true;
2636
	}
2637
 
2638
	// Complete callback
2639
	if ( typeof option === "function" ) {
2640
		return true;
2641
	}
2642
 
2643
	// Options hash (but not naming an effect)
2644
	if ( typeof option === "object" && !option.effect ) {
2645
		return true;
2646
	}
2647
 
2648
	// Didn't match any standard API
2649
	return false;
2650
}
2651
 
2652
$.fn.extend( {
2653
	effect: function( /* effect, options, speed, callback */ ) {
2654
		var args = _normalizeArguments.apply( this, arguments ),
2655
			effectMethod = $.effects.effect[ args.effect ],
2656
			defaultMode = effectMethod.mode,
2657
			queue = args.queue,
2658
			queueName = queue || "fx",
2659
			complete = args.complete,
2660
			mode = args.mode,
2661
			modes = [],
2662
			prefilter = function( next ) {
2663
				var el = $( this ),
2664
					normalizedMode = $.effects.mode( el, mode ) || defaultMode;
2665
 
2666
				// Sentinel for duck-punching the :animated pseudo-selector
2667
				el.data( dataSpaceAnimated, true );
2668
 
2669
				// Save effect mode for later use,
2670
				// we can't just call $.effects.mode again later,
2671
				// as the .show() below destroys the initial state
2672
				modes.push( normalizedMode );
2673
 
2674
				// See $.uiBackCompat inside of run() for removal of defaultMode in 1.14
2675
				if ( defaultMode && ( normalizedMode === "show" ||
2676
						( normalizedMode === defaultMode && normalizedMode === "hide" ) ) ) {
2677
					el.show();
2678
				}
2679
 
2680
				if ( !defaultMode || normalizedMode !== "none" ) {
2681
					$.effects.saveStyle( el );
2682
				}
2683
 
2684
				if ( typeof next === "function" ) {
2685
					next();
2686
				}
2687
			};
2688
 
2689
		if ( $.fx.off || !effectMethod ) {
2690
 
2691
			// Delegate to the original method (e.g., .show()) if possible
2692
			if ( mode ) {
2693
				return this[ mode ]( args.duration, complete );
2694
			} else {
2695
				return this.each( function() {
2696
					if ( complete ) {
2697
						complete.call( this );
2698
					}
2699
				} );
2700
			}
2701
		}
2702
 
2703
		function run( next ) {
2704
			var elem = $( this );
2705
 
2706
			function cleanup() {
2707
				elem.removeData( dataSpaceAnimated );
2708
 
2709
				$.effects.cleanUp( elem );
2710
 
2711
				if ( args.mode === "hide" ) {
2712
					elem.hide();
2713
				}
2714
 
2715
				done();
2716
			}
2717
 
2718
			function done() {
2719
				if ( typeof complete === "function" ) {
2720
					complete.call( elem[ 0 ] );
2721
				}
2722
 
2723
				if ( typeof next === "function" ) {
2724
					next();
2725
				}
2726
			}
2727
 
2728
			// Override mode option on a per element basis,
2729
			// as toggle can be either show or hide depending on element state
2730
			args.mode = modes.shift();
2731
 
2732
			if ( $.uiBackCompat === true && !defaultMode ) {
2733
				if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) {
2734
 
2735
					// Call the core method to track "olddisplay" properly
2736
					elem[ mode ]();
2737
					done();
2738
				} else {
2739
					effectMethod.call( elem[ 0 ], args, done );
2740
				}
2741
			} else {
2742
				if ( args.mode === "none" ) {
2743
 
2744
					// Call the core method to track "olddisplay" properly
2745
					elem[ mode ]();
2746
					done();
2747
				} else {
2748
					effectMethod.call( elem[ 0 ], args, cleanup );
2749
				}
2750
			}
2751
		}
2752
 
2753
		// Run prefilter on all elements first to ensure that
2754
		// any showing or hiding happens before placeholder creation,
2755
		// which ensures that any layout changes are correctly captured.
2756
		return queue === false ?
2757
			this.each( prefilter ).each( run ) :
2758
			this.queue( queueName, prefilter ).queue( queueName, run );
2759
	},
2760
 
2761
	show: ( function( orig ) {
2762
		return function( option ) {
2763
			if ( standardAnimationOption( option ) ) {
2764
				return orig.apply( this, arguments );
2765
			} else {
2766
				var args = _normalizeArguments.apply( this, arguments );
2767
				args.mode = "show";
2768
				return this.effect.call( this, args );
2769
			}
2770
		};
2771
	} )( $.fn.show ),
2772
 
2773
	hide: ( function( orig ) {
2774
		return function( option ) {
2775
			if ( standardAnimationOption( option ) ) {
2776
				return orig.apply( this, arguments );
2777
			} else {
2778
				var args = _normalizeArguments.apply( this, arguments );
2779
				args.mode = "hide";
2780
				return this.effect.call( this, args );
2781
			}
2782
		};
2783
	} )( $.fn.hide ),
2784
 
2785
	toggle: ( function( orig ) {
2786
		return function( option ) {
2787
			if ( standardAnimationOption( option ) || typeof option === "boolean" ) {
2788
				return orig.apply( this, arguments );
2789
			} else {
2790
				var args = _normalizeArguments.apply( this, arguments );
2791
				args.mode = "toggle";
2792
				return this.effect.call( this, args );
2793
			}
2794
		};
2795
	} )( $.fn.toggle ),
2796
 
2797
	cssUnit: function( key ) {
2798
		var style = this.css( key ),
2799
			val = [];
2800
 
2801
		$.each( [ "em", "px", "%", "pt" ], function( i, unit ) {
2802
			if ( style.indexOf( unit ) > 0 ) {
2803
				val = [ parseFloat( style ), unit ];
2804
			}
2805
		} );
2806
		return val;
2807
	},
2808
 
2809
	cssClip: function( clipObj ) {
2810
		if ( clipObj ) {
2811
			return this.css( "clip", "rect(" + clipObj.top + "px " + clipObj.right + "px " +
2812
				clipObj.bottom + "px " + clipObj.left + "px)" );
2813
		}
2814
		return parseClip( this.css( "clip" ), this );
2815
	},
2816
 
2817
	transfer: function( options, done ) {
2818
		var element = $( this ),
2819
			target = $( options.to ),
2820
			targetFixed = target.css( "position" ) === "fixed",
2821
			body = $( "body" ),
2822
			fixTop = targetFixed ? body.scrollTop() : 0,
2823
			fixLeft = targetFixed ? body.scrollLeft() : 0,
2824
			endPosition = target.offset(),
2825
			animation = {
2826
				top: endPosition.top - fixTop,
2827
				left: endPosition.left - fixLeft,
2828
				height: target.innerHeight(),
2829
				width: target.innerWidth()
2830
			},
2831
			startPosition = element.offset(),
2832
			transfer = $( "<div class='ui-effects-transfer'></div>" );
2833
 
2834
		transfer
2835
			.appendTo( "body" )
2836
			.addClass( options.className )
2837
			.css( {
2838
				top: startPosition.top - fixTop,
2839
				left: startPosition.left - fixLeft,
2840
				height: element.innerHeight(),
2841
				width: element.innerWidth(),
2842
				position: targetFixed ? "fixed" : "absolute"
2843
			} )
2844
			.animate( animation, options.duration, options.easing, function() {
2845
				transfer.remove();
2846
				if ( typeof done === "function" ) {
2847
					done();
2848
				}
2849
			} );
2850
	}
2851
} );
2852
 
2853
function parseClip( str, element ) {
2854
		var outerWidth = element.outerWidth(),
2855
			outerHeight = element.outerHeight(),
2856
			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)\)$/,
2857
			values = clipRegex.exec( str ) || [ "", 0, outerWidth, outerHeight, 0 ];
2858
 
2859
		return {
2860
			top: parseFloat( values[ 1 ] ) || 0,
2861
			right: values[ 2 ] === "auto" ? outerWidth : parseFloat( values[ 2 ] ),
2862
			bottom: values[ 3 ] === "auto" ? outerHeight : parseFloat( values[ 3 ] ),
2863
			left: parseFloat( values[ 4 ] ) || 0
2864
		};
2865
}
2866
 
2867
$.fx.step.clip = function( fx ) {
2868
	if ( !fx.clipInit ) {
2869
		fx.start = $( fx.elem ).cssClip();
2870
		if ( typeof fx.end === "string" ) {
2871
			fx.end = parseClip( fx.end, fx.elem );
2872
		}
2873
		fx.clipInit = true;
2874
	}
2875
 
2876
	$( fx.elem ).cssClip( {
2877
		top: fx.pos * ( fx.end.top - fx.start.top ) + fx.start.top,
2878
		right: fx.pos * ( fx.end.right - fx.start.right ) + fx.start.right,
2879
		bottom: fx.pos * ( fx.end.bottom - fx.start.bottom ) + fx.start.bottom,
2880
		left: fx.pos * ( fx.end.left - fx.start.left ) + fx.start.left
2881
	} );
2882
};
2883
 
2884
} )();
2885
 
2886
/******************************************************************************/
2887
/*********************************** EASING ***********************************/
2888
/******************************************************************************/
2889
 
2890
( function() {
2891
 
2892
// Based on easing equations from Robert Penner (http://robertpenner.com/easing)
2893
 
2894
var baseEasings = {};
2895
 
2896
$.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) {
2897
	baseEasings[ name ] = function( p ) {
2898
		return Math.pow( p, i + 2 );
2899
	};
2900
} );
2901
 
2902
$.extend( baseEasings, {
2903
	Sine: function( p ) {
2904
		return 1 - Math.cos( p * Math.PI / 2 );
2905
	},
2906
	Circ: function( p ) {
2907
		return 1 - Math.sqrt( 1 - p * p );
2908
	},
2909
	Elastic: function( p ) {
2910
		return p === 0 || p === 1 ? p :
2911
			-Math.pow( 2, 8 * ( p - 1 ) ) * Math.sin( ( ( p - 1 ) * 80 - 7.5 ) * Math.PI / 15 );
2912
	},
2913
	Back: function( p ) {
2914
		return p * p * ( 3 * p - 2 );
2915
	},
2916
	Bounce: function( p ) {
2917
		var pow2,
2918
			bounce = 4;
2919
 
2920
		while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {}
2921
		return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 );
2922
	}
2923
} );
2924
 
2925
$.each( baseEasings, function( name, easeIn ) {
2926
	$.easing[ "easeIn" + name ] = easeIn;
2927
	$.easing[ "easeOut" + name ] = function( p ) {
2928
		return 1 - easeIn( 1 - p );
2929
	};
2930
	$.easing[ "easeInOut" + name ] = function( p ) {
2931
		return p < 0.5 ?
2932
			easeIn( p * 2 ) / 2 :
2933
			1 - easeIn( p * -2 + 2 ) / 2;
2934
	};
2935
} );
2936
 
2937
} )();
2938
 
2939
var effect = $.effects;
2940
 
2941
 
2942
/*!
2943
 * jQuery UI Effects Blind 1.14.1
2944
 * https://jqueryui.com
2945
 *
2946
 * Copyright OpenJS Foundation and other contributors
2947
 * Released under the MIT license.
2948
 * https://jquery.org/license
2949
 */
2950
 
2951
//>>label: Blind Effect
2952
//>>group: Effects
2953
//>>description: Blinds the element.
2954
//>>docs: https://api.jqueryui.com/blind-effect/
2955
//>>demos: https://jqueryui.com/effect/
2956
 
2957
 
2958
var effectsEffectBlind = $.effects.define( "blind", "hide", function( options, done ) {
2959
	var map = {
2960
			up: [ "bottom", "top" ],
2961
			vertical: [ "bottom", "top" ],
2962
			down: [ "top", "bottom" ],
2963
			left: [ "right", "left" ],
2964
			horizontal: [ "right", "left" ],
2965
			right: [ "left", "right" ]
2966
		},
2967
		element = $( this ),
2968
		direction = options.direction || "up",
2969
		start = element.cssClip(),
2970
		animate = { clip: $.extend( {}, start ) },
2971
		placeholder = $.effects.createPlaceholder( element );
2972
 
2973
	animate.clip[ map[ direction ][ 0 ] ] = animate.clip[ map[ direction ][ 1 ] ];
2974
 
2975
	if ( options.mode === "show" ) {
2976
		element.cssClip( animate.clip );
2977
		if ( placeholder ) {
2978
			placeholder.css( $.effects.clipToBox( animate ) );
2979
		}
2980
 
2981
		animate.clip = start;
2982
	}
2983
 
2984
	if ( placeholder ) {
2985
		placeholder.animate( $.effects.clipToBox( animate ), options.duration, options.easing );
2986
	}
2987
 
2988
	element.animate( animate, {
2989
		queue: false,
2990
		duration: options.duration,
2991
		easing: options.easing,
2992
		complete: done
2993
	} );
2994
} );
2995
 
2996
 
2997
/*!
2998
 * jQuery UI Effects Bounce 1.14.1
2999
 * https://jqueryui.com
3000
 *
3001
 * Copyright OpenJS Foundation and other contributors
3002
 * Released under the MIT license.
3003
 * https://jquery.org/license
3004
 */
3005
 
3006
//>>label: Bounce Effect
3007
//>>group: Effects
3008
//>>description: Bounces an element horizontally or vertically n times.
3009
//>>docs: https://api.jqueryui.com/bounce-effect/
3010
//>>demos: https://jqueryui.com/effect/
3011
 
3012
 
3013
var effectsEffectBounce = $.effects.define( "bounce", function( options, done ) {
3014
	var upAnim, downAnim, refValue,
3015
		element = $( this ),
3016
 
3017
		// Defaults:
3018
		mode = options.mode,
3019
		hide = mode === "hide",
3020
		show = mode === "show",
3021
		direction = options.direction || "up",
3022
		distance = options.distance,
3023
		times = options.times || 5,
3024
 
3025
		// Number of internal animations
3026
		anims = times * 2 + ( show || hide ? 1 : 0 ),
3027
		speed = options.duration / anims,
3028
		easing = options.easing,
3029
 
3030
		// Utility:
3031
		ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
3032
		motion = ( direction === "up" || direction === "left" ),
3033
		i = 0,
3034
 
3035
		queuelen = element.queue().length;
3036
 
3037
	$.effects.createPlaceholder( element );
3038
 
3039
	refValue = element.css( ref );
3040
 
3041
	// Default distance for the BIGGEST bounce is the outer Distance / 3
3042
	if ( !distance ) {
3043
		distance = element[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3;
3044
	}
3045
 
3046
	if ( show ) {
3047
		downAnim = { opacity: 1 };
3048
		downAnim[ ref ] = refValue;
3049
 
3050
		// If we are showing, force opacity 0 and set the initial position
3051
		// then do the "first" animation
3052
		element
3053
			.css( "opacity", 0 )
3054
			.css( ref, motion ? -distance * 2 : distance * 2 )
3055
			.animate( downAnim, speed, easing );
3056
	}
3057
 
3058
	// Start at the smallest distance if we are hiding
3059
	if ( hide ) {
3060
		distance = distance / Math.pow( 2, times - 1 );
3061
	}
3062
 
3063
	downAnim = {};
3064
	downAnim[ ref ] = refValue;
3065
 
3066
	// Bounces up/down/left/right then back to 0 -- times * 2 animations happen here
3067
	for ( ; i < times; i++ ) {
3068
		upAnim = {};
3069
		upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
3070
 
3071
		element
3072
			.animate( upAnim, speed, easing )
3073
			.animate( downAnim, speed, easing );
3074
 
3075
		distance = hide ? distance * 2 : distance / 2;
3076
	}
3077
 
3078
	// Last Bounce when Hiding
3079
	if ( hide ) {
3080
		upAnim = { opacity: 0 };
3081
		upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
3082
 
3083
		element.animate( upAnim, speed, easing );
3084
	}
3085
 
3086
	element.queue( done );
3087
 
3088
	$.effects.unshift( element, queuelen, anims + 1 );
3089
} );
3090
 
3091
 
3092
/*!
3093
 * jQuery UI Effects Clip 1.14.1
3094
 * https://jqueryui.com
3095
 *
3096
 * Copyright OpenJS Foundation and other contributors
3097
 * Released under the MIT license.
3098
 * https://jquery.org/license
3099
 */
3100
 
3101
//>>label: Clip Effect
3102
//>>group: Effects
3103
//>>description: Clips the element on and off like an old TV.
3104
//>>docs: https://api.jqueryui.com/clip-effect/
3105
//>>demos: https://jqueryui.com/effect/
3106
 
3107
 
3108
var effectsEffectClip = $.effects.define( "clip", "hide", function( options, done ) {
3109
	var start,
3110
		animate = {},
3111
		element = $( this ),
3112
		direction = options.direction || "vertical",
3113
		both = direction === "both",
3114
		horizontal = both || direction === "horizontal",
3115
		vertical = both || direction === "vertical";
3116
 
3117
	start = element.cssClip();
3118
	animate.clip = {
3119
		top: vertical ? ( start.bottom - start.top ) / 2 : start.top,
3120
		right: horizontal ? ( start.right - start.left ) / 2 : start.right,
3121
		bottom: vertical ? ( start.bottom - start.top ) / 2 : start.bottom,
3122
		left: horizontal ? ( start.right - start.left ) / 2 : start.left
3123
	};
3124
 
3125
	$.effects.createPlaceholder( element );
3126
 
3127
	if ( options.mode === "show" ) {
3128
		element.cssClip( animate.clip );
3129
		animate.clip = start;
3130
	}
3131
 
3132
	element.animate( animate, {
3133
		queue: false,
3134
		duration: options.duration,
3135
		easing: options.easing,
3136
		complete: done
3137
	} );
3138
 
3139
} );
3140
 
3141
 
3142
/*!
3143
 * jQuery UI Effects Drop 1.14.1
3144
 * https://jqueryui.com
3145
 *
3146
 * Copyright OpenJS Foundation and other contributors
3147
 * Released under the MIT license.
3148
 * https://jquery.org/license
3149
 */
3150
 
3151
//>>label: Drop Effect
3152
//>>group: Effects
3153
//>>description: Moves an element in one direction and hides it at the same time.
3154
//>>docs: https://api.jqueryui.com/drop-effect/
3155
//>>demos: https://jqueryui.com/effect/
3156
 
3157
 
3158
var effectsEffectDrop = $.effects.define( "drop", "hide", function( options, done ) {
3159
 
3160
	var distance,
3161
		element = $( this ),
3162
		mode = options.mode,
3163
		show = mode === "show",
3164
		direction = options.direction || "left",
3165
		ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
3166
		motion = ( direction === "up" || direction === "left" ) ? "-=" : "+=",
3167
		oppositeMotion = ( motion === "+=" ) ? "-=" : "+=",
3168
		animation = {
3169
			opacity: 0
3170
		};
3171
 
3172
	$.effects.createPlaceholder( element );
3173
 
3174
	distance = options.distance ||
3175
		element[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ) / 2;
3176
 
3177
	animation[ ref ] = motion + distance;
3178
 
3179
	if ( show ) {
3180
		element.css( animation );
3181
 
3182
		animation[ ref ] = oppositeMotion + distance;
3183
		animation.opacity = 1;
3184
	}
3185
 
3186
	// Animate
3187
	element.animate( animation, {
3188
		queue: false,
3189
		duration: options.duration,
3190
		easing: options.easing,
3191
		complete: done
3192
	} );
3193
} );
3194
 
3195
 
3196
/*!
3197
 * jQuery UI Effects Explode 1.14.1
3198
 * https://jqueryui.com
3199
 *
3200
 * Copyright OpenJS Foundation and other contributors
3201
 * Released under the MIT license.
3202
 * https://jquery.org/license
3203
 */
3204
 
3205
//>>label: Explode Effect
3206
//>>group: Effects
3207
/* eslint-disable max-len */
3208
//>>description: Explodes an element in all directions into n pieces. Implodes an element to its original wholeness.
3209
/* eslint-enable max-len */
3210
//>>docs: https://api.jqueryui.com/explode-effect/
3211
//>>demos: https://jqueryui.com/effect/
3212
 
3213
 
3214
var effectsEffectExplode = $.effects.define( "explode", "hide", function( options, done ) {
3215
 
3216
	var i, j, left, top, mx, my,
3217
		rows = options.pieces ? Math.round( Math.sqrt( options.pieces ) ) : 3,
3218
		cells = rows,
3219
		element = $( this ),
3220
		mode = options.mode,
3221
		show = mode === "show",
3222
 
3223
		// Show and then visibility:hidden the element before calculating offset
3224
		offset = element.show().css( "visibility", "hidden" ).offset(),
3225
 
3226
		// Width and height of a piece
3227
		width = Math.ceil( element.outerWidth() / cells ),
3228
		height = Math.ceil( element.outerHeight() / rows ),
3229
		pieces = [];
3230
 
3231
	// Children animate complete:
3232
	function childComplete() {
3233
		pieces.push( this );
3234
		if ( pieces.length === rows * cells ) {
3235
			animComplete();
3236
		}
3237
	}
3238
 
3239
	// Clone the element for each row and cell.
3240
	for ( i = 0; i < rows; i++ ) { // ===>
3241
		top = offset.top + i * height;
3242
		my = i - ( rows - 1 ) / 2;
3243
 
3244
		for ( j = 0; j < cells; j++ ) { // |||
3245
			left = offset.left + j * width;
3246
			mx = j - ( cells - 1 ) / 2;
3247
 
3248
			// Create a clone of the now hidden main element that will be absolute positioned
3249
			// within a wrapper div off the -left and -top equal to size of our pieces
3250
			element
3251
				.clone()
3252
				.appendTo( "body" )
3253
				.wrap( "<div></div>" )
3254
				.css( {
3255
					position: "absolute",
3256
					visibility: "visible",
3257
					left: -j * width,
3258
					top: -i * height
3259
				} )
3260
 
3261
				// Select the wrapper - make it overflow: hidden and absolute positioned based on
3262
				// where the original was located +left and +top equal to the size of pieces
3263
				.parent()
3264
					.addClass( "ui-effects-explode" )
3265
					.css( {
3266
						position: "absolute",
3267
						overflow: "hidden",
3268
						width: width,
3269
						height: height,
3270
						left: left + ( show ? mx * width : 0 ),
3271
						top: top + ( show ? my * height : 0 ),
3272
						opacity: show ? 0 : 1
3273
					} )
3274
					.animate( {
3275
						left: left + ( show ? 0 : mx * width ),
3276
						top: top + ( show ? 0 : my * height ),
3277
						opacity: show ? 1 : 0
3278
					}, options.duration || 500, options.easing, childComplete );
3279
		}
3280
	}
3281
 
3282
	function animComplete() {
3283
		element.css( {
3284
			visibility: "visible"
3285
		} );
3286
		$( pieces ).remove();
3287
		done();
3288
	}
3289
} );
3290
 
3291
 
3292
/*!
3293
 * jQuery UI Effects Fade 1.14.1
3294
 * https://jqueryui.com
3295
 *
3296
 * Copyright OpenJS Foundation and other contributors
3297
 * Released under the MIT license.
3298
 * https://jquery.org/license
3299
 */
3300
 
3301
//>>label: Fade Effect
3302
//>>group: Effects
3303
//>>description: Fades the element.
3304
//>>docs: https://api.jqueryui.com/fade-effect/
3305
//>>demos: https://jqueryui.com/effect/
3306
 
3307
 
3308
var effectsEffectFade = $.effects.define( "fade", "toggle", function( options, done ) {
3309
	var show = options.mode === "show";
3310
 
3311
	$( this )
3312
		.css( "opacity", show ? 0 : 1 )
3313
		.animate( {
3314
			opacity: show ? 1 : 0
3315
		}, {
3316
			queue: false,
3317
			duration: options.duration,
3318
			easing: options.easing,
3319
			complete: done
3320
		} );
3321
} );
3322
 
3323
 
3324
/*!
3325
 * jQuery UI Effects Fold 1.14.1
3326
 * https://jqueryui.com
3327
 *
3328
 * Copyright OpenJS Foundation and other contributors
3329
 * Released under the MIT license.
3330
 * https://jquery.org/license
3331
 */
3332
 
3333
//>>label: Fold Effect
3334
//>>group: Effects
3335
//>>description: Folds an element first horizontally and then vertically.
3336
//>>docs: https://api.jqueryui.com/fold-effect/
3337
//>>demos: https://jqueryui.com/effect/
3338
 
3339
 
3340
var effectsEffectFold = $.effects.define( "fold", "hide", function( options, done ) {
3341
 
3342
	// Create element
3343
	var element = $( this ),
3344
		mode = options.mode,
3345
		show = mode === "show",
3346
		hide = mode === "hide",
3347
		size = options.size || 15,
3348
		percent = /([0-9]+)%/.exec( size ),
3349
		horizFirst = !!options.horizFirst,
3350
		ref = horizFirst ? [ "right", "bottom" ] : [ "bottom", "right" ],
3351
		duration = options.duration / 2,
3352
 
3353
		placeholder = $.effects.createPlaceholder( element ),
3354
 
3355
		start = element.cssClip(),
3356
		animation1 = { clip: $.extend( {}, start ) },
3357
		animation2 = { clip: $.extend( {}, start ) },
3358
 
3359
		distance = [ start[ ref[ 0 ] ], start[ ref[ 1 ] ] ],
3360
 
3361
		queuelen = element.queue().length;
3362
 
3363
	if ( percent ) {
3364
		size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ];
3365
	}
3366
	animation1.clip[ ref[ 0 ] ] = size;
3367
	animation2.clip[ ref[ 0 ] ] = size;
3368
	animation2.clip[ ref[ 1 ] ] = 0;
3369
 
3370
	if ( show ) {
3371
		element.cssClip( animation2.clip );
3372
		if ( placeholder ) {
3373
			placeholder.css( $.effects.clipToBox( animation2 ) );
3374
		}
3375
 
3376
		animation2.clip = start;
3377
	}
3378
 
3379
	// Animate
3380
	element
3381
		.queue( function( next ) {
3382
			if ( placeholder ) {
3383
				placeholder
3384
					.animate( $.effects.clipToBox( animation1 ), duration, options.easing )
3385
					.animate( $.effects.clipToBox( animation2 ), duration, options.easing );
3386
			}
3387
 
3388
			next();
3389
		} )
3390
		.animate( animation1, duration, options.easing )
3391
		.animate( animation2, duration, options.easing )
3392
		.queue( done );
3393
 
3394
	$.effects.unshift( element, queuelen, 4 );
3395
} );
3396
 
3397
 
3398
/*!
3399
 * jQuery UI Effects Highlight 1.14.1
3400
 * https://jqueryui.com
3401
 *
3402
 * Copyright OpenJS Foundation and other contributors
3403
 * Released under the MIT license.
3404
 * https://jquery.org/license
3405
 */
3406
 
3407
//>>label: Highlight Effect
3408
//>>group: Effects
3409
//>>description: Highlights the background of an element in a defined color for a custom duration.
3410
//>>docs: https://api.jqueryui.com/highlight-effect/
3411
//>>demos: https://jqueryui.com/effect/
3412
 
3413
 
3414
var effectsEffectHighlight = $.effects.define( "highlight", "show", function( options, done ) {
3415
	var element = $( this ),
3416
		animation = {
3417
			backgroundColor: element.css( "backgroundColor" )
3418
		};
3419
 
3420
	if ( options.mode === "hide" ) {
3421
		animation.opacity = 0;
3422
	}
3423
 
3424
	$.effects.saveStyle( element );
3425
 
3426
	element
3427
		.css( {
3428
			backgroundImage: "none",
3429
			backgroundColor: options.color || "#ffff99"
3430
		} )
3431
		.animate( animation, {
3432
			queue: false,
3433
			duration: options.duration,
3434
			easing: options.easing,
3435
			complete: done
3436
		} );
3437
} );
3438
 
3439
 
3440
/*!
3441
 * jQuery UI Effects Size 1.14.1
3442
 * https://jqueryui.com
3443
 *
3444
 * Copyright OpenJS Foundation and other contributors
3445
 * Released under the MIT license.
3446
 * https://jquery.org/license
3447
 */
3448
 
3449
//>>label: Size Effect
3450
//>>group: Effects
3451
//>>description: Resize an element to a specified width and height.
3452
//>>docs: https://api.jqueryui.com/size-effect/
3453
//>>demos: https://jqueryui.com/effect/
3454
 
3455
 
3456
var effectsEffectSize = $.effects.define( "size", function( options, done ) {
3457
 
3458
	// Create element
3459
	var baseline, factor, temp,
3460
		element = $( this ),
3461
 
3462
		// Copy for children
3463
		cProps = [ "fontSize" ],
3464
		vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ],
3465
		hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ],
3466
 
3467
		// Set options
3468
		mode = options.mode,
3469
		restore = mode !== "effect",
3470
		scale = options.scale || "both",
3471
		origin = options.origin || [ "middle", "center" ],
3472
		position = element.css( "position" ),
3473
		pos = element.position(),
3474
		original = $.effects.scaledDimensions( element ),
3475
		from = options.from || original,
3476
		to = options.to || $.effects.scaledDimensions( element, 0 );
3477
 
3478
	$.effects.createPlaceholder( element );
3479
 
3480
	if ( mode === "show" ) {
3481
		temp = from;
3482
		from = to;
3483
		to = temp;
3484
	}
3485
 
3486
	// Set scaling factor
3487
	factor = {
3488
		from: {
3489
			y: from.height / original.height,
3490
			x: from.width / original.width
3491
		},
3492
		to: {
3493
			y: to.height / original.height,
3494
			x: to.width / original.width
3495
		}
3496
	};
3497
 
3498
	// Scale the css box
3499
	if ( scale === "box" || scale === "both" ) {
3500
 
3501
		// Vertical props scaling
3502
		if ( factor.from.y !== factor.to.y ) {
3503
			from = $.effects.setTransition( element, vProps, factor.from.y, from );
3504
			to = $.effects.setTransition( element, vProps, factor.to.y, to );
3505
		}
3506
 
3507
		// Horizontal props scaling
3508
		if ( factor.from.x !== factor.to.x ) {
3509
			from = $.effects.setTransition( element, hProps, factor.from.x, from );
3510
			to = $.effects.setTransition( element, hProps, factor.to.x, to );
3511
		}
3512
	}
3513
 
3514
	// Scale the content
3515
	if ( scale === "content" || scale === "both" ) {
3516
 
3517
		// Vertical props scaling
3518
		if ( factor.from.y !== factor.to.y ) {
3519
			from = $.effects.setTransition( element, cProps, factor.from.y, from );
3520
			to = $.effects.setTransition( element, cProps, factor.to.y, to );
3521
		}
3522
	}
3523
 
3524
	// Adjust the position properties based on the provided origin points
3525
	if ( origin ) {
3526
		baseline = $.effects.getBaseline( origin, original );
3527
		from.top = ( original.outerHeight - from.outerHeight ) * baseline.y + pos.top;
3528
		from.left = ( original.outerWidth - from.outerWidth ) * baseline.x + pos.left;
3529
		to.top = ( original.outerHeight - to.outerHeight ) * baseline.y + pos.top;
3530
		to.left = ( original.outerWidth - to.outerWidth ) * baseline.x + pos.left;
3531
	}
3532
	delete from.outerHeight;
3533
	delete from.outerWidth;
3534
	element.css( from );
3535
 
3536
	// Animate the children if desired
3537
	if ( scale === "content" || scale === "both" ) {
3538
 
3539
		vProps = vProps.concat( [ "marginTop", "marginBottom" ] ).concat( cProps );
3540
		hProps = hProps.concat( [ "marginLeft", "marginRight" ] );
3541
 
3542
		// Only animate children with width attributes specified
3543
		// TODO: is this right? should we include anything with css width specified as well
3544
		element.find( "*[width]" ).each( function() {
3545
			var child = $( this ),
3546
				childOriginal = $.effects.scaledDimensions( child ),
3547
				childFrom = {
3548
					height: childOriginal.height * factor.from.y,
3549
					width: childOriginal.width * factor.from.x,
3550
					outerHeight: childOriginal.outerHeight * factor.from.y,
3551
					outerWidth: childOriginal.outerWidth * factor.from.x
3552
				},
3553
				childTo = {
3554
					height: childOriginal.height * factor.to.y,
3555
					width: childOriginal.width * factor.to.x,
3556
					outerHeight: childOriginal.height * factor.to.y,
3557
					outerWidth: childOriginal.width * factor.to.x
3558
				};
3559
 
3560
			// Vertical props scaling
3561
			if ( factor.from.y !== factor.to.y ) {
3562
				childFrom = $.effects.setTransition( child, vProps, factor.from.y, childFrom );
3563
				childTo = $.effects.setTransition( child, vProps, factor.to.y, childTo );
3564
			}
3565
 
3566
			// Horizontal props scaling
3567
			if ( factor.from.x !== factor.to.x ) {
3568
				childFrom = $.effects.setTransition( child, hProps, factor.from.x, childFrom );
3569
				childTo = $.effects.setTransition( child, hProps, factor.to.x, childTo );
3570
			}
3571
 
3572
			if ( restore ) {
3573
				$.effects.saveStyle( child );
3574
			}
3575
 
3576
			// Animate children
3577
			child.css( childFrom );
3578
			child.animate( childTo, options.duration, options.easing, function() {
3579
 
3580
				// Restore children
3581
				if ( restore ) {
3582
					$.effects.restoreStyle( child );
3583
				}
3584
			} );
3585
		} );
3586
	}
3587
 
3588
	// Animate
3589
	element.animate( to, {
3590
		queue: false,
3591
		duration: options.duration,
3592
		easing: options.easing,
3593
		complete: function() {
3594
 
3595
			var offset = element.offset();
3596
 
3597
			if ( to.opacity === 0 ) {
3598
				element.css( "opacity", from.opacity );
3599
			}
3600
 
3601
			if ( !restore ) {
3602
				element
3603
					.css( "position", position === "static" ? "relative" : position )
3604
					.offset( offset );
3605
 
3606
				// Need to save style here so that automatic style restoration
3607
				// doesn't restore to the original styles from before the animation.
3608
				$.effects.saveStyle( element );
3609
			}
3610
 
3611
			done();
3612
		}
3613
	} );
3614
 
3615
} );
3616
 
3617
 
3618
/*!
3619
 * jQuery UI Effects Scale 1.14.1
3620
 * https://jqueryui.com
3621
 *
3622
 * Copyright OpenJS Foundation and other contributors
3623
 * Released under the MIT license.
3624
 * https://jquery.org/license
3625
 */
3626
 
3627
//>>label: Scale Effect
3628
//>>group: Effects
3629
//>>description: Grows or shrinks an element and its content.
3630
//>>docs: https://api.jqueryui.com/scale-effect/
3631
//>>demos: https://jqueryui.com/effect/
3632
 
3633
 
3634
var effectsEffectScale = $.effects.define( "scale", function( options, done ) {
3635
 
3636
	// Create element
3637
	var el = $( this ),
3638
		mode = options.mode,
3639
		percent = parseInt( options.percent, 10 ) ||
3640
			( parseInt( options.percent, 10 ) === 0 ? 0 : ( mode !== "effect" ? 0 : 100 ) ),
3641
 
3642
		newOptions = $.extend( true, {
3643
			from: $.effects.scaledDimensions( el ),
3644
			to: $.effects.scaledDimensions( el, percent, options.direction || "both" ),
3645
			origin: options.origin || [ "middle", "center" ]
3646
		}, options );
3647
 
3648
	// Fade option to support puff
3649
	if ( options.fade ) {
3650
		newOptions.from.opacity = 1;
3651
		newOptions.to.opacity = 0;
3652
	}
3653
 
3654
	$.effects.effect.size.call( this, newOptions, done );
3655
} );
3656
 
3657
 
3658
/*!
3659
 * jQuery UI Effects Puff 1.14.1
3660
 * https://jqueryui.com
3661
 *
3662
 * Copyright OpenJS Foundation and other contributors
3663
 * Released under the MIT license.
3664
 * https://jquery.org/license
3665
 */
3666
 
3667
//>>label: Puff Effect
3668
//>>group: Effects
3669
//>>description: Creates a puff effect by scaling the element up and hiding it at the same time.
3670
//>>docs: https://api.jqueryui.com/puff-effect/
3671
//>>demos: https://jqueryui.com/effect/
3672
 
3673
 
3674
var effectsEffectPuff = $.effects.define( "puff", "hide", function( options, done ) {
3675
	var newOptions = $.extend( true, {}, options, {
3676
		fade: true,
3677
		percent: parseInt( options.percent, 10 ) || 150
3678
	} );
3679
 
3680
	$.effects.effect.scale.call( this, newOptions, done );
3681
} );
3682
 
3683
 
3684
/*!
3685
 * jQuery UI Effects Pulsate 1.14.1
3686
 * https://jqueryui.com
3687
 *
3688
 * Copyright OpenJS Foundation and other contributors
3689
 * Released under the MIT license.
3690
 * https://jquery.org/license
3691
 */
3692
 
3693
//>>label: Pulsate Effect
3694
//>>group: Effects
3695
//>>description: Pulsates an element n times by changing the opacity to zero and back.
3696
//>>docs: https://api.jqueryui.com/pulsate-effect/
3697
//>>demos: https://jqueryui.com/effect/
3698
 
3699
 
3700
var effectsEffectPulsate = $.effects.define( "pulsate", "show", function( options, done ) {
3701
	var element = $( this ),
3702
		mode = options.mode,
3703
		show = mode === "show",
3704
		hide = mode === "hide",
3705
		showhide = show || hide,
3706
 
3707
		// Showing or hiding leaves off the "last" animation
3708
		anims = ( ( options.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ),
3709
		duration = options.duration / anims,
3710
		animateTo = 0,
3711
		i = 1,
3712
		queuelen = element.queue().length;
3713
 
3714
	if ( show || !element.is( ":visible" ) ) {
3715
		element.css( "opacity", 0 ).show();
3716
		animateTo = 1;
3717
	}
3718
 
3719
	// Anims - 1 opacity "toggles"
3720
	for ( ; i < anims; i++ ) {
3721
		element.animate( { opacity: animateTo }, duration, options.easing );
3722
		animateTo = 1 - animateTo;
3723
	}
3724
 
3725
	element.animate( { opacity: animateTo }, duration, options.easing );
3726
 
3727
	element.queue( done );
3728
 
3729
	$.effects.unshift( element, queuelen, anims + 1 );
3730
} );
3731
 
3732
 
3733
/*!
3734
 * jQuery UI Effects Shake 1.14.1
3735
 * https://jqueryui.com
3736
 *
3737
 * Copyright OpenJS Foundation and other contributors
3738
 * Released under the MIT license.
3739
 * https://jquery.org/license
3740
 */
3741
 
3742
//>>label: Shake Effect
3743
//>>group: Effects
3744
//>>description: Shakes an element horizontally or vertically n times.
3745
//>>docs: https://api.jqueryui.com/shake-effect/
3746
//>>demos: https://jqueryui.com/effect/
3747
 
3748
 
3749
var effectsEffectShake = $.effects.define( "shake", function( options, done ) {
3750
 
3751
	var i = 1,
3752
		element = $( this ),
3753
		direction = options.direction || "left",
3754
		distance = options.distance || 20,
3755
		times = options.times || 3,
3756
		anims = times * 2 + 1,
3757
		speed = Math.round( options.duration / anims ),
3758
		ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
3759
		positiveMotion = ( direction === "up" || direction === "left" ),
3760
		animation = {},
3761
		animation1 = {},
3762
		animation2 = {},
3763
 
3764
		queuelen = element.queue().length;
3765
 
3766
	$.effects.createPlaceholder( element );
3767
 
3768
	// Animation
3769
	animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance;
3770
	animation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2;
3771
	animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2;
3772
 
3773
	// Animate
3774
	element.animate( animation, speed, options.easing );
3775
 
3776
	// Shakes
3777
	for ( ; i < times; i++ ) {
3778
		element
3779
			.animate( animation1, speed, options.easing )
3780
			.animate( animation2, speed, options.easing );
3781
	}
3782
 
3783
	element
3784
		.animate( animation1, speed, options.easing )
3785
		.animate( animation, speed / 2, options.easing )
3786
		.queue( done );
3787
 
3788
	$.effects.unshift( element, queuelen, anims + 1 );
3789
} );
3790
 
3791
 
3792
/*!
3793
 * jQuery UI Effects Slide 1.14.1
3794
 * https://jqueryui.com
3795
 *
3796
 * Copyright OpenJS Foundation and other contributors
3797
 * Released under the MIT license.
3798
 * https://jquery.org/license
3799
 */
3800
 
3801
//>>label: Slide Effect
3802
//>>group: Effects
3803
//>>description: Slides an element in and out of the viewport.
3804
//>>docs: https://api.jqueryui.com/slide-effect/
3805
//>>demos: https://jqueryui.com/effect/
3806
 
3807
 
3808
var effectsEffectSlide = $.effects.define( "slide", "show", function( options, done ) {
3809
	var startClip, startRef,
3810
		element = $( this ),
3811
		map = {
3812
			up: [ "bottom", "top" ],
3813
			down: [ "top", "bottom" ],
3814
			left: [ "right", "left" ],
3815
			right: [ "left", "right" ]
3816
		},
3817
		mode = options.mode,
3818
		direction = options.direction || "left",
3819
		ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
3820
		positiveMotion = ( direction === "up" || direction === "left" ),
3821
		distance = options.distance ||
3822
			element[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ),
3823
		animation = {};
3824
 
3825
	$.effects.createPlaceholder( element );
3826
 
3827
	startClip = element.cssClip();
3828
	startRef = element.position()[ ref ];
3829
 
3830
	// Define hide animation
3831
	animation[ ref ] = ( positiveMotion ? -1 : 1 ) * distance + startRef;
3832
	animation.clip = element.cssClip();
3833
	animation.clip[ map[ direction ][ 1 ] ] = animation.clip[ map[ direction ][ 0 ] ];
3834
 
3835
	// Reverse the animation if we're showing
3836
	if ( mode === "show" ) {
3837
		element.cssClip( animation.clip );
3838
		element.css( ref, animation[ ref ] );
3839
		animation.clip = startClip;
3840
		animation[ ref ] = startRef;
3841
	}
3842
 
3843
	// Actually animate
3844
	element.animate( animation, {
3845
		queue: false,
3846
		duration: options.duration,
3847
		easing: options.easing,
3848
		complete: done
3849
	} );
3850
} );
3851
 
3852
 
3853
/*!
3854
 * jQuery UI Effects Transfer 1.14.1
3855
 * https://jqueryui.com
3856
 *
3857
 * Copyright OpenJS Foundation and other contributors
3858
 * Released under the MIT license.
3859
 * https://jquery.org/license
3860
 */
3861
 
3862
//>>label: Transfer Effect
3863
//>>group: Effects
3864
//>>description: Displays a transfer effect from one element to another.
3865
//>>docs: https://api.jqueryui.com/transfer-effect/
3866
//>>demos: https://jqueryui.com/effect/
3867
 
3868
 
3869
var effect;
3870
if ( $.uiBackCompat === true ) {
3871
	effect = $.effects.define( "transfer", function( options, done ) {
3872
		$( this ).transfer( options, done );
3873
	} );
3874
}
3875
var effectsEffectTransfer = effect;
3876
 
3877
 
3878
/*!
3879
 * jQuery UI Focusable 1.14.1
3880
 * https://jqueryui.com
3881
 *
3882
 * Copyright OpenJS Foundation and other contributors
3883
 * Released under the MIT license.
3884
 * https://jquery.org/license
3885
 */
3886
 
3887
//>>label: :focusable Selector
3888
//>>group: Core
3889
//>>description: Selects elements which can be focused.
3890
//>>docs: https://api.jqueryui.com/focusable-selector/
3891
 
3892
 
3893
// Selectors
3894
$.ui.focusable = function( element, hasTabindex ) {
3895
	var map, mapName, img, focusableIfVisible, fieldset,
3896
		nodeName = element.nodeName.toLowerCase();
3897
 
3898
	if ( "area" === nodeName ) {
3899
		map = element.parentNode;
3900
		mapName = map.name;
3901
		if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
3902
			return false;
3903
		}
3904
		img = $( "img[usemap='#" + mapName + "']" );
3905
		return img.length > 0 && img.is( ":visible" );
3906
	}
3907
 
3908
	if ( /^(input|select|textarea|button|object)$/.test( nodeName ) ) {
3909
		focusableIfVisible = !element.disabled;
3910
 
3911
		if ( focusableIfVisible ) {
3912
 
3913
			// Form controls within a disabled fieldset are disabled.
3914
			// However, controls within the fieldset's legend do not get disabled.
3915
			// Since controls generally aren't placed inside legends, we skip
3916
			// this portion of the check.
3917
			fieldset = $( element ).closest( "fieldset" )[ 0 ];
3918
			if ( fieldset ) {
3919
				focusableIfVisible = !fieldset.disabled;
3920
			}
3921
		}
3922
	} else if ( "a" === nodeName ) {
3923
		focusableIfVisible = element.href || hasTabindex;
3924
	} else {
3925
		focusableIfVisible = hasTabindex;
3926
	}
3927
 
3928
	return focusableIfVisible && $( element ).is( ":visible" ) &&
3929
		$( element ).css( "visibility" ) === "visible";
3930
};
3931
 
3932
$.extend( $.expr.pseudos, {
3933
	focusable: function( element ) {
3934
		return $.ui.focusable( element, $.attr( element, "tabindex" ) != null );
3935
	}
3936
} );
3937
 
3938
var focusable = $.ui.focusable;
3939
 
3940
 
3941
/*!
3942
 * jQuery UI Form Reset Mixin 1.14.1
3943
 * https://jqueryui.com
3944
 *
3945
 * Copyright OpenJS Foundation and other contributors
3946
 * Released under the MIT license.
3947
 * https://jquery.org/license
3948
 */
3949
 
3950
//>>label: Form Reset Mixin
3951
//>>group: Core
3952
//>>description: Refresh input widgets when their form is reset
3953
//>>docs: https://api.jqueryui.com/form-reset-mixin/
3954
 
3955
 
3956
var formResetMixin = $.ui.formResetMixin = {
3957
	_formResetHandler: function() {
3958
		var form = $( this );
3959
 
3960
		// Wait for the form reset to actually happen before refreshing
3961
		setTimeout( function() {
3962
			var instances = form.data( "ui-form-reset-instances" );
3963
			$.each( instances, function() {
3964
				this.refresh();
3965
			} );
3966
		} );
3967
	},
3968
 
3969
	_bindFormResetHandler: function() {
3970
		this.form = $( this.element.prop( "form" ) );
3971
		if ( !this.form.length ) {
3972
			return;
3973
		}
3974
 
3975
		var instances = this.form.data( "ui-form-reset-instances" ) || [];
3976
		if ( !instances.length ) {
3977
 
3978
			// We don't use _on() here because we use a single event handler per form
3979
			this.form.on( "reset.ui-form-reset", this._formResetHandler );
3980
		}
3981
		instances.push( this );
3982
		this.form.data( "ui-form-reset-instances", instances );
3983
	},
3984
 
3985
	_unbindFormResetHandler: function() {
3986
		if ( !this.form.length ) {
3987
			return;
3988
		}
3989
 
3990
		var instances = this.form.data( "ui-form-reset-instances" );
3991
		instances.splice( $.inArray( this, instances ), 1 );
3992
		if ( instances.length ) {
3993
			this.form.data( "ui-form-reset-instances", instances );
3994
		} else {
3995
			this.form
3996
				.removeData( "ui-form-reset-instances" )
3997
				.off( "reset.ui-form-reset" );
3998
		}
3999
	}
4000
};
4001
 
4002
 
4003
/*!
4004
 * jQuery UI Legacy jQuery Core patches 1.14.1
4005
 * https://jqueryui.com
4006
 *
4007
 * Copyright OpenJS Foundation and other contributors
4008
 * Released under the MIT license.
4009
 * https://jquery.org/license
4010
 *
4011
 */
4012
 
4013
//>>label: Legacy jQuery Core patches
4014
//>>group: Core
4015
//>>description: Backport `.even()`, `.odd()` and `$.escapeSelector` to older jQuery Core versions (deprecated)
4016
 
4017
 
4018
// Support: jQuery 2.2.x or older.
4019
// This method has been defined in jQuery 3.0.0.
4020
// Code from https://github.com/jquery/jquery/blob/e539bac79e666bba95bba86d690b4e609dca2286/src/selector/escapeSelector.js
4021
if ( !$.escapeSelector ) {
4022
	$.escapeSelector = function( id ) {
4023
		return CSS.escape( id + "" );
4024
	};
4025
}
4026
 
4027
// Support: jQuery 3.4.x or older
4028
// These methods have been defined in jQuery 3.5.0.
4029
if ( !$.fn.even || !$.fn.odd ) {
4030
	$.fn.extend( {
4031
		even: function() {
4032
			return this.filter( function( i ) {
4033
				return i % 2 === 0;
4034
			} );
4035
		},
4036
		odd: function() {
4037
			return this.filter( function( i ) {
4038
				return i % 2 === 1;
4039
			} );
4040
		}
4041
	} );
4042
}
4043
 
4044
;
4045
/*!
4046
 * jQuery UI Keycode 1.14.1
4047
 * https://jqueryui.com
4048
 *
4049
 * Copyright OpenJS Foundation and other contributors
4050
 * Released under the MIT license.
4051
 * https://jquery.org/license
4052
 */
4053
 
4054
//>>label: Keycode
4055
//>>group: Core
4056
//>>description: Provide keycodes as keynames
4057
//>>docs: https://api.jqueryui.com/jQuery.ui.keyCode/
4058
 
4059
 
4060
var keycode = $.ui.keyCode = {
4061
	BACKSPACE: 8,
4062
	COMMA: 188,
4063
	DELETE: 46,
4064
	DOWN: 40,
4065
	END: 35,
4066
	ENTER: 13,
4067
	ESCAPE: 27,
4068
	HOME: 36,
4069
	LEFT: 37,
4070
	PAGE_DOWN: 34,
4071
	PAGE_UP: 33,
4072
	PERIOD: 190,
4073
	RIGHT: 39,
4074
	SPACE: 32,
4075
	TAB: 9,
4076
	UP: 38
4077
};
4078
 
4079
 
4080
/*!
4081
 * jQuery UI Labels 1.14.1
4082
 * https://jqueryui.com
4083
 *
4084
 * Copyright OpenJS Foundation and other contributors
4085
 * Released under the MIT license.
4086
 * https://jquery.org/license
4087
 */
4088
 
4089
//>>label: labels
4090
//>>group: Core
4091
//>>description: Find all the labels associated with a given input
4092
//>>docs: https://api.jqueryui.com/labels/
4093
 
4094
 
4095
var labels = $.fn.labels = function() {
4096
	var ancestor, selector, id, labels, ancestors;
4097
 
4098
	if ( !this.length ) {
4099
		return this.pushStack( [] );
4100
	}
4101
 
4102
	// Check control.labels first
4103
	if ( this[ 0 ].labels && this[ 0 ].labels.length ) {
4104
		return this.pushStack( this[ 0 ].labels );
4105
	}
4106
 
4107
	// If `control.labels` is empty - e.g. inside of document fragments - find
4108
	// the labels manually
4109
	labels = this.eq( 0 ).parents( "label" );
4110
 
4111
	// Look for the label based on the id
4112
	id = this.attr( "id" );
4113
	if ( id ) {
4114
 
4115
		// We don't search against the document in case the element
4116
		// is disconnected from the DOM
4117
		ancestor = this.eq( 0 ).parents().last();
4118
 
4119
		// Get a full set of top level ancestors
4120
		ancestors = ancestor.add( ancestor.length ? ancestor.siblings() : this.siblings() );
4121
 
4122
		// Create a selector for the label based on the id
4123
		selector = "label[for='" + CSS.escape( id ) + "']";
4124
 
4125
		labels = labels.add( ancestors.find( selector ).addBack( selector ) );
4126
 
4127
	}
4128
 
4129
	// Return whatever we have found for labels
4130
	return this.pushStack( labels );
4131
};
4132
 
4133
 
4134
/*!
4135
 * jQuery UI Scroll Parent 1.14.1
4136
 * https://jqueryui.com
4137
 *
4138
 * Copyright OpenJS Foundation and other contributors
4139
 * Released under the MIT license.
4140
 * https://jquery.org/license
4141
 */
4142
 
4143
//>>label: scrollParent
4144
//>>group: Core
4145
//>>description: Get the closest ancestor element that is scrollable.
4146
//>>docs: https://api.jqueryui.com/scrollParent/
4147
 
4148
 
4149
var scrollParent = $.fn.scrollParent = function( includeHidden ) {
4150
	var position = this.css( "position" ),
4151
		excludeStaticParent = position === "absolute",
4152
		overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/,
4153
		scrollParent = this.parents().filter( function() {
4154
			var parent = $( this );
4155
			if ( excludeStaticParent && parent.css( "position" ) === "static" ) {
4156
				return false;
4157
			}
4158
			return overflowRegex.test( parent.css( "overflow" ) + parent.css( "overflow-y" ) +
4159
				parent.css( "overflow-x" ) );
4160
		} ).eq( 0 );
4161
 
4162
	return position === "fixed" || !scrollParent.length ?
4163
		$( this[ 0 ].ownerDocument || document ) :
4164
		scrollParent;
4165
};
4166
 
4167
 
4168
/*!
4169
 * jQuery UI Tabbable 1.14.1
4170
 * https://jqueryui.com
4171
 *
4172
 * Copyright OpenJS Foundation and other contributors
4173
 * Released under the MIT license.
4174
 * https://jquery.org/license
4175
 */
4176
 
4177
//>>label: :tabbable Selector
4178
//>>group: Core
4179
//>>description: Selects elements which can be tabbed to.
4180
//>>docs: https://api.jqueryui.com/tabbable-selector/
4181
 
4182
 
4183
var tabbable = $.extend( $.expr.pseudos, {
4184
	tabbable: function( element ) {
4185
		var tabIndex = $.attr( element, "tabindex" ),
4186
			hasTabindex = tabIndex != null;
4187
		return ( !hasTabindex || tabIndex >= 0 ) && $.ui.focusable( element, hasTabindex );
4188
	}
4189
} );
4190
 
4191
 
4192
/*!
4193
 * jQuery UI Unique ID 1.14.1
4194
 * https://jqueryui.com
4195
 *
4196
 * Copyright OpenJS Foundation and other contributors
4197
 * Released under the MIT license.
4198
 * https://jquery.org/license
4199
 */
4200
 
4201
//>>label: uniqueId
4202
//>>group: Core
4203
//>>description: Functions to generate and remove uniqueId's
4204
//>>docs: https://api.jqueryui.com/uniqueId/
4205
 
4206
 
4207
var uniqueId = $.fn.extend( {
4208
	uniqueId: ( function() {
4209
		var uuid = 0;
4210
 
4211
		return function() {
4212
			return this.each( function() {
4213
				if ( !this.id ) {
4214
					this.id = "ui-id-" + ( ++uuid );
4215
				}
4216
			} );
4217
		};
4218
	} )(),
4219
 
4220
	removeUniqueId: function() {
4221
		return this.each( function() {
4222
			if ( /^ui-id-\d+$/.test( this.id ) ) {
4223
				$( this ).removeAttr( "id" );
4224
			}
4225
		} );
4226
	}
4227
} );
4228
 
4229
 
4230
/*!
4231
 * jQuery UI Accordion 1.14.1
4232
 * https://jqueryui.com
4233
 *
4234
 * Copyright OpenJS Foundation and other contributors
4235
 * Released under the MIT license.
4236
 * https://jquery.org/license
4237
 */
4238
 
4239
//>>label: Accordion
4240
//>>group: Widgets
4241
/* eslint-disable max-len */
4242
//>>description: Displays collapsible content panels for presenting information in a limited amount of space.
4243
/* eslint-enable max-len */
4244
//>>docs: https://api.jqueryui.com/accordion/
4245
//>>demos: https://jqueryui.com/accordion/
4246
//>>css.structure: ../../themes/base/core.css
4247
//>>css.structure: ../../themes/base/accordion.css
4248
//>>css.theme: ../../themes/base/theme.css
4249
 
4250
 
4251
var widgetsAccordion = $.widget( "ui.accordion", {
4252
	version: "1.14.1",
4253
	options: {
4254
		active: 0,
4255
		animate: {},
4256
		classes: {
4257
			"ui-accordion-header": "ui-corner-top",
4258
			"ui-accordion-header-collapsed": "ui-corner-all",
4259
			"ui-accordion-content": "ui-corner-bottom"
4260
		},
4261
		collapsible: false,
4262
		event: "click",
4263
		header: function( elem ) {
4264
			return elem
4265
				.find( "> li > :first-child" )
4266
				.add(
4267
					elem.find( "> :not(li)" )
4268
 
4269
						// Support: jQuery <3.5 only
4270
						// We could use `.even()` but that's unavailable in older jQuery.
4271
						.filter( function( i ) {
4272
							return i % 2 === 0;
4273
						} )
4274
				);
4275
		},
4276
		heightStyle: "auto",
4277
		icons: {
4278
			activeHeader: "ui-icon-triangle-1-s",
4279
			header: "ui-icon-triangle-1-e"
4280
		},
4281
 
4282
		// Callbacks
4283
		activate: null,
4284
		beforeActivate: null
4285
	},
4286
 
4287
	hideProps: {
4288
		borderTopWidth: "hide",
4289
		borderBottomWidth: "hide",
4290
		paddingTop: "hide",
4291
		paddingBottom: "hide",
4292
		height: "hide"
4293
	},
4294
 
4295
	showProps: {
4296
		borderTopWidth: "show",
4297
		borderBottomWidth: "show",
4298
		paddingTop: "show",
4299
		paddingBottom: "show",
4300
		height: "show"
4301
	},
4302
 
4303
	_create: function() {
4304
		var options = this.options;
4305
 
4306
		this.prevShow = this.prevHide = $();
4307
		this._addClass( "ui-accordion", "ui-widget ui-helper-reset" );
4308
		this.element.attr( "role", "tablist" );
4309
 
4310
		// Don't allow collapsible: false and active: false / null
4311
		if ( !options.collapsible && ( options.active === false || options.active == null ) ) {
4312
			options.active = 0;
4313
		}
4314
 
4315
		this._processPanels();
4316
 
4317
		// handle negative values
4318
		if ( options.active < 0 ) {
4319
			options.active += this.headers.length;
4320
		}
4321
		this._refresh();
4322
	},
4323
 
4324
	_getCreateEventData: function() {
4325
		return {
4326
			header: this.active,
4327
			panel: !this.active.length ? $() : this.active.next()
4328
		};
4329
	},
4330
 
4331
	_createIcons: function() {
4332
		var icon, children,
4333
			icons = this.options.icons;
4334
 
4335
		if ( icons ) {
4336
			icon = $( "<span>" );
4337
			this._addClass( icon, "ui-accordion-header-icon", "ui-icon " + icons.header );
4338
			icon.prependTo( this.headers );
4339
			children = this.active.children( ".ui-accordion-header-icon" );
4340
			this._removeClass( children, icons.header )
4341
				._addClass( children, null, icons.activeHeader )
4342
				._addClass( this.headers, "ui-accordion-icons" );
4343
		}
4344
	},
4345
 
4346
	_destroyIcons: function() {
4347
		this._removeClass( this.headers, "ui-accordion-icons" );
4348
		this.headers.children( ".ui-accordion-header-icon" ).remove();
4349
	},
4350
 
4351
	_destroy: function() {
4352
		var contents;
4353
 
4354
		// Clean up main element
4355
		this.element.removeAttr( "role" );
4356
 
4357
		// Clean up headers
4358
		this.headers
4359
			.removeAttr( "role aria-expanded aria-selected aria-controls tabIndex" )
4360
			.removeUniqueId();
4361
 
4362
		this._destroyIcons();
4363
 
4364
		// Clean up content panels
4365
		contents = this.headers.next()
4366
			.css( "display", "" )
4367
			.removeAttr( "role aria-hidden aria-labelledby" )
4368
			.removeUniqueId();
4369
 
4370
		if ( this.options.heightStyle !== "content" ) {
4371
			contents.css( "height", "" );
4372
		}
4373
	},
4374
 
4375
	_setOption: function( key, value ) {
4376
		if ( key === "active" ) {
4377
 
4378
			// _activate() will handle invalid values and update this.options
4379
			this._activate( value );
4380
			return;
4381
		}
4382
 
4383
		if ( key === "event" ) {
4384
			if ( this.options.event ) {
4385
				this._off( this.headers, this.options.event );
4386
			}
4387
			this._setupEvents( value );
4388
		}
4389
 
4390
		this._super( key, value );
4391
 
4392
		// Setting collapsible: false while collapsed; open first panel
4393
		if ( key === "collapsible" && !value && this.options.active === false ) {
4394
			this._activate( 0 );
4395
		}
4396
 
4397
		if ( key === "icons" ) {
4398
			this._destroyIcons();
4399
			if ( value ) {
4400
				this._createIcons();
4401
			}
4402
		}
4403
	},
4404
 
4405
	_setOptionDisabled: function( value ) {
4406
		this._super( value );
4407
 
4408
		this.element.attr( "aria-disabled", value );
4409
		this._toggleClass( null, "ui-state-disabled", !!value );
4410
	},
4411
 
4412
	_keydown: function( event ) {
4413
		if ( event.altKey || event.ctrlKey ) {
4414
			return;
4415
		}
4416
 
4417
		var keyCode = $.ui.keyCode,
4418
			length = this.headers.length,
4419
			currentIndex = this.headers.index( event.target ),
4420
			toFocus = false;
4421
 
4422
		switch ( event.keyCode ) {
4423
		case keyCode.RIGHT:
4424
		case keyCode.DOWN:
4425
			toFocus = this.headers[ ( currentIndex + 1 ) % length ];
4426
			break;
4427
		case keyCode.LEFT:
4428
		case keyCode.UP:
4429
			toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
4430
			break;
4431
		case keyCode.SPACE:
4432
		case keyCode.ENTER:
4433
			this._eventHandler( event );
4434
			break;
4435
		case keyCode.HOME:
4436
			toFocus = this.headers[ 0 ];
4437
			break;
4438
		case keyCode.END:
4439
			toFocus = this.headers[ length - 1 ];
4440
			break;
4441
		}
4442
 
4443
		if ( toFocus ) {
4444
			$( event.target ).attr( "tabIndex", -1 );
4445
			$( toFocus ).attr( "tabIndex", 0 );
4446
			$( toFocus ).trigger( "focus" );
4447
			event.preventDefault();
4448
		}
4449
	},
4450
 
4451
	_panelKeyDown: function( event ) {
4452
		if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) {
4453
			$( event.currentTarget ).prev().trigger( "focus" );
4454
		}
4455
	},
4456
 
4457
	refresh: function() {
4458
		var options = this.options;
4459
		this._processPanels();
4460
 
4461
		// Was collapsed or no panel
4462
		if ( ( options.active === false && options.collapsible === true ) ||
4463
				!this.headers.length ) {
4464
			options.active = false;
4465
			this.active = $();
4466
 
4467
		// active false only when collapsible is true
4468
		} else if ( options.active === false ) {
4469
			this._activate( 0 );
4470
 
4471
		// was active, but active panel is gone
4472
		} else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
4473
 
4474
			// all remaining panel are disabled
4475
			if ( this.headers.length === this.headers.find( ".ui-state-disabled" ).length ) {
4476
				options.active = false;
4477
				this.active = $();
4478
 
4479
			// activate previous panel
4480
			} else {
4481
				this._activate( Math.max( 0, options.active - 1 ) );
4482
			}
4483
 
4484
		// was active, active panel still exists
4485
		} else {
4486
 
4487
			// make sure active index is correct
4488
			options.active = this.headers.index( this.active );
4489
		}
4490
 
4491
		this._destroyIcons();
4492
 
4493
		this._refresh();
4494
	},
4495
 
4496
	_processPanels: function() {
4497
		var prevHeaders = this.headers,
4498
			prevPanels = this.panels;
4499
 
4500
		if ( typeof this.options.header === "function" ) {
4501
			this.headers = this.options.header( this.element );
4502
		} else {
4503
			this.headers = this.element.find( this.options.header );
4504
		}
4505
		this._addClass( this.headers, "ui-accordion-header ui-accordion-header-collapsed",
4506
			"ui-state-default" );
4507
 
4508
		this.panels = this.headers.next().filter( ":not(.ui-accordion-content-active)" ).hide();
4509
		this._addClass( this.panels, "ui-accordion-content", "ui-helper-reset ui-widget-content" );
4510
 
4511
		// Avoid memory leaks (#10056)
4512
		if ( prevPanels ) {
4513
			this._off( prevHeaders.not( this.headers ) );
4514
			this._off( prevPanels.not( this.panels ) );
4515
		}
4516
	},
4517
 
4518
	_refresh: function() {
4519
		var maxHeight,
4520
			options = this.options,
4521
			heightStyle = options.heightStyle,
4522
			parent = this.element.parent();
4523
 
4524
		this.active = this._findActive( options.active );
4525
		this._addClass( this.active, "ui-accordion-header-active", "ui-state-active" )
4526
			._removeClass( this.active, "ui-accordion-header-collapsed" );
4527
		this._addClass( this.active.next(), "ui-accordion-content-active" );
4528
		this.active.next().show();
4529
 
4530
		this.headers
4531
			.attr( "role", "tab" )
4532
			.each( function() {
4533
				var header = $( this ),
4534
					headerId = header.uniqueId().attr( "id" ),
4535
					panel = header.next(),
4536
					panelId = panel.uniqueId().attr( "id" );
4537
				header.attr( "aria-controls", panelId );
4538
				panel.attr( "aria-labelledby", headerId );
4539
			} )
4540
			.next()
4541
				.attr( "role", "tabpanel" );
4542
 
4543
		this.headers
4544
			.not( this.active )
4545
				.attr( {
4546
					"aria-selected": "false",
4547
					"aria-expanded": "false",
4548
					tabIndex: -1
4549
				} )
4550
				.next()
4551
					.attr( {
4552
						"aria-hidden": "true"
4553
					} )
4554
					.hide();
4555
 
4556
		// Make sure at least one header is in the tab order
4557
		if ( !this.active.length ) {
4558
			this.headers.eq( 0 ).attr( "tabIndex", 0 );
4559
		} else {
4560
			this.active.attr( {
4561
				"aria-selected": "true",
4562
				"aria-expanded": "true",
4563
				tabIndex: 0
4564
			} )
4565
				.next()
4566
					.attr( {
4567
						"aria-hidden": "false"
4568
					} );
4569
		}
4570
 
4571
		this._createIcons();
4572
 
4573
		this._setupEvents( options.event );
4574
 
4575
		if ( heightStyle === "fill" ) {
4576
			maxHeight = parent.height();
4577
			this.element.siblings( ":visible" ).each( function() {
4578
				var elem = $( this ),
4579
					position = elem.css( "position" );
4580
 
4581
				if ( position === "absolute" || position === "fixed" ) {
4582
					return;
4583
				}
4584
				maxHeight -= elem.outerHeight( true );
4585
			} );
4586
 
4587
			this.headers.each( function() {
4588
				maxHeight -= $( this ).outerHeight( true );
4589
			} );
4590
 
4591
			this.headers.next()
4592
				.each( function() {
4593
					$( this ).height( Math.max( 0, maxHeight -
4594
						$( this ).innerHeight() + $( this ).height() ) );
4595
				} )
4596
				.css( "overflow", "auto" );
4597
		} else if ( heightStyle === "auto" ) {
4598
			maxHeight = 0;
4599
			this.headers.next()
4600
				.each( function() {
4601
					var isVisible = $( this ).is( ":visible" );
4602
					if ( !isVisible ) {
4603
						$( this ).show();
4604
					}
4605
					maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() );
4606
					if ( !isVisible ) {
4607
						$( this ).hide();
4608
					}
4609
				} )
4610
				.height( maxHeight );
4611
		}
4612
	},
4613
 
4614
	_activate: function( index ) {
4615
		var active = this._findActive( index )[ 0 ];
4616
 
4617
		// Trying to activate the already active panel
4618
		if ( active === this.active[ 0 ] ) {
4619
			return;
4620
		}
4621
 
4622
		// Trying to collapse, simulate a click on the currently active header
4623
		active = active || this.active[ 0 ];
4624
 
4625
		this._eventHandler( {
4626
			target: active,
4627
			currentTarget: active,
4628
			preventDefault: $.noop
4629
		} );
4630
	},
4631
 
4632
	_findActive: function( selector ) {
4633
		return typeof selector === "number" ? this.headers.eq( selector ) : $();
4634
	},
4635
 
4636
	_setupEvents: function( event ) {
4637
		var events = {
4638
			keydown: "_keydown"
4639
		};
4640
		if ( event ) {
4641
			$.each( event.split( " " ), function( index, eventName ) {
4642
				events[ eventName ] = "_eventHandler";
4643
			} );
4644
		}
4645
 
4646
		this._off( this.headers.add( this.headers.next() ) );
4647
		this._on( this.headers, events );
4648
		this._on( this.headers.next(), { keydown: "_panelKeyDown" } );
4649
		this._hoverable( this.headers );
4650
		this._focusable( this.headers );
4651
	},
4652
 
4653
	_eventHandler: function( event ) {
4654
		var activeChildren, clickedChildren,
4655
			options = this.options,
4656
			active = this.active,
4657
			clicked = $( event.currentTarget ),
4658
			clickedIsActive = clicked[ 0 ] === active[ 0 ],
4659
			collapsing = clickedIsActive && options.collapsible,
4660
			toShow = collapsing ? $() : clicked.next(),
4661
			toHide = active.next(),
4662
			eventData = {
4663
				oldHeader: active,
4664
				oldPanel: toHide,
4665
				newHeader: collapsing ? $() : clicked,
4666
				newPanel: toShow
4667
			};
4668
 
4669
		event.preventDefault();
4670
 
4671
		if (
4672
 
4673
				// click on active header, but not collapsible
4674
				( clickedIsActive && !options.collapsible ) ||
4675
 
4676
				// allow canceling activation
4677
				( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
4678
			return;
4679
		}
4680
 
4681
		options.active = collapsing ? false : this.headers.index( clicked );
4682
 
4683
		// When the call to ._toggle() comes after the class changes
4684
		// it causes a very odd bug in IE 8 (see #6720)
4685
		this.active = clickedIsActive ? $() : clicked;
4686
		this._toggle( eventData );
4687
 
4688
		// Switch classes
4689
		// corner classes on the previously active header stay after the animation
4690
		this._removeClass( active, "ui-accordion-header-active", "ui-state-active" );
4691
		if ( options.icons ) {
4692
			activeChildren = active.children( ".ui-accordion-header-icon" );
4693
			this._removeClass( activeChildren, null, options.icons.activeHeader )
4694
				._addClass( activeChildren, null, options.icons.header );
4695
		}
4696
 
4697
		if ( !clickedIsActive ) {
4698
			this._removeClass( clicked, "ui-accordion-header-collapsed" )
4699
				._addClass( clicked, "ui-accordion-header-active", "ui-state-active" );
4700
			if ( options.icons ) {
4701
				clickedChildren = clicked.children( ".ui-accordion-header-icon" );
4702
				this._removeClass( clickedChildren, null, options.icons.header )
4703
					._addClass( clickedChildren, null, options.icons.activeHeader );
4704
			}
4705
 
4706
			this._addClass( clicked.next(), "ui-accordion-content-active" );
4707
		}
4708
	},
4709
 
4710
	_toggle: function( data ) {
4711
		var toShow = data.newPanel,
4712
			toHide = this.prevShow.length ? this.prevShow : data.oldPanel;
4713
 
4714
		// Handle activating a panel during the animation for another activation
4715
		this.prevShow.add( this.prevHide ).stop( true, true );
4716
		this.prevShow = toShow;
4717
		this.prevHide = toHide;
4718
 
4719
		if ( this.options.animate ) {
4720
			this._animate( toShow, toHide, data );
4721
		} else {
4722
			toHide.hide();
4723
			toShow.show();
4724
			this._toggleComplete( data );
4725
		}
4726
 
4727
		toHide.attr( {
4728
			"aria-hidden": "true"
4729
		} );
4730
		toHide.prev().attr( {
4731
			"aria-selected": "false",
4732
			"aria-expanded": "false"
4733
		} );
4734
 
4735
		// if we're switching panels, remove the old header from the tab order
4736
		// if we're opening from collapsed state, remove the previous header from the tab order
4737
		// if we're collapsing, then keep the collapsing header in the tab order
4738
		if ( toShow.length && toHide.length ) {
4739
			toHide.prev().attr( {
4740
				"tabIndex": -1,
4741
				"aria-expanded": "false"
4742
			} );
4743
		} else if ( toShow.length ) {
4744
			this.headers.filter( function() {
4745
				return parseInt( $( this ).attr( "tabIndex" ), 10 ) === 0;
4746
			} )
4747
				.attr( "tabIndex", -1 );
4748
		}
4749
 
4750
		toShow
4751
			.attr( "aria-hidden", "false" )
4752
			.prev()
4753
				.attr( {
4754
					"aria-selected": "true",
4755
					"aria-expanded": "true",
4756
					tabIndex: 0
4757
				} );
4758
	},
4759
 
4760
	_animate: function( toShow, toHide, data ) {
4761
		var total, easing, duration,
4762
			that = this,
4763
			adjust = 0,
4764
			boxSizing = toShow.css( "box-sizing" ),
4765
			down = toShow.length &&
4766
				( !toHide.length || ( toShow.index() < toHide.index() ) ),
4767
			animate = this.options.animate || {},
4768
			options = down && animate.down || animate,
4769
			complete = function() {
4770
				that._toggleComplete( data );
4771
			};
4772
 
4773
		if ( typeof options === "number" ) {
4774
			duration = options;
4775
		}
4776
		if ( typeof options === "string" ) {
4777
			easing = options;
4778
		}
4779
 
4780
		// fall back from options to animation in case of partial down settings
4781
		easing = easing || options.easing || animate.easing;
4782
		duration = duration || options.duration || animate.duration;
4783
 
4784
		if ( !toHide.length ) {
4785
			return toShow.animate( this.showProps, duration, easing, complete );
4786
		}
4787
		if ( !toShow.length ) {
4788
			return toHide.animate( this.hideProps, duration, easing, complete );
4789
		}
4790
 
4791
		total = toShow.show().outerHeight();
4792
		toHide.animate( this.hideProps, {
4793
			duration: duration,
4794
			easing: easing,
4795
			step: function( now, fx ) {
4796
				fx.now = Math.round( now );
4797
			}
4798
		} );
4799
		toShow
4800
			.hide()
4801
			.animate( this.showProps, {
4802
				duration: duration,
4803
				easing: easing,
4804
				complete: complete,
4805
				step: function( now, fx ) {
4806
					fx.now = Math.round( now );
4807
					if ( fx.prop !== "height" ) {
4808
						if ( boxSizing === "content-box" ) {
4809
							adjust += fx.now;
4810
						}
4811
					} else if ( that.options.heightStyle !== "content" ) {
4812
						fx.now = Math.round( total - toHide.outerHeight() - adjust );
4813
						adjust = 0;
4814
					}
4815
				}
4816
			} );
4817
	},
4818
 
4819
	_toggleComplete: function( data ) {
4820
		var toHide = data.oldPanel,
4821
			prev = toHide.prev();
4822
 
4823
		this._removeClass( toHide, "ui-accordion-content-active" );
4824
		this._removeClass( prev, "ui-accordion-header-active" )
4825
			._addClass( prev, "ui-accordion-header-collapsed" );
4826
 
4827
		this._trigger( "activate", null, data );
4828
	}
4829
} );
4830
 
4831
 
4832
/*!
4833
 * jQuery UI Menu 1.14.1
4834
 * https://jqueryui.com
4835
 *
4836
 * Copyright OpenJS Foundation and other contributors
4837
 * Released under the MIT license.
4838
 * https://jquery.org/license
4839
 */
4840
 
4841
//>>label: Menu
4842
//>>group: Widgets
4843
//>>description: Creates nestable menus.
4844
//>>docs: https://api.jqueryui.com/menu/
4845
//>>demos: https://jqueryui.com/menu/
4846
//>>css.structure: ../../themes/base/core.css
4847
//>>css.structure: ../../themes/base/menu.css
4848
//>>css.theme: ../../themes/base/theme.css
4849
 
4850
 
4851
var widgetsMenu = $.widget( "ui.menu", {
4852
	version: "1.14.1",
4853
	defaultElement: "<ul>",
4854
	delay: 300,
4855
	options: {
4856
		icons: {
4857
			submenu: "ui-icon-caret-1-e"
4858
		},
4859
		items: "> *",
4860
		menus: "ul",
4861
		position: {
4862
			my: "left top",
4863
			at: "right top"
4864
		},
4865
		role: "menu",
4866
 
4867
		// Callbacks
4868
		blur: null,
4869
		focus: null,
4870
		select: null
4871
	},
4872
 
4873
	_create: function() {
4874
		this.activeMenu = this.element;
4875
 
4876
		// Flag used to prevent firing of the click handler
4877
		// as the event bubbles up through nested menus
4878
		this.mouseHandled = false;
4879
		this.lastMousePosition = { x: null, y: null };
4880
		this.element
4881
			.uniqueId()
4882
			.attr( {
4883
				role: this.options.role,
4884
				tabIndex: 0
4885
			} );
4886
 
4887
		this._addClass( "ui-menu", "ui-widget ui-widget-content" );
4888
		this._on( {
4889
 
4890
			// Prevent focus from sticking to links inside menu after clicking
4891
			// them (focus should always stay on UL during navigation).
4892
			"mousedown .ui-menu-item": function( event ) {
4893
				event.preventDefault();
4894
 
4895
				this._activateItem( event );
4896
			},
4897
			"click .ui-menu-item": function( event ) {
4898
				var target = $( event.target );
4899
				var active = $( this.document[ 0 ].activeElement );
4900
				if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) {
4901
					this.select( event );
4902
 
4903
					// Only set the mouseHandled flag if the event will bubble, see #9469.
4904
					if ( !event.isPropagationStopped() ) {
4905
						this.mouseHandled = true;
4906
					}
4907
 
4908
					// Open submenu on click
4909
					if ( target.has( ".ui-menu" ).length ) {
4910
						this.expand( event );
4911
					} else if ( !this.element.is( ":focus" ) &&
4912
							active.closest( ".ui-menu" ).length ) {
4913
 
4914
						// Redirect focus to the menu
4915
						this.element.trigger( "focus", [ true ] );
4916
 
4917
						// If the active item is on the top level, let it stay active.
4918
						// Otherwise, blur the active item since it is no longer visible.
4919
						if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) {
4920
							clearTimeout( this.timer );
4921
						}
4922
					}
4923
				}
4924
			},
4925
			"mouseenter .ui-menu-item": "_activateItem",
4926
			"mousemove .ui-menu-item": "_activateItem",
4927
			mouseleave: "collapseAll",
4928
			"mouseleave .ui-menu": "collapseAll",
4929
			focus: function( event, keepActiveItem ) {
4930
 
4931
				// If there's already an active item, keep it active
4932
				// If not, activate the first item
4933
				var item = this.active || this._menuItems().first();
4934
 
4935
				if ( !keepActiveItem ) {
4936
					this.focus( event, item );
4937
				}
4938
			},
4939
			blur: function( event ) {
4940
				this._delay( function() {
4941
					var notContained = !$.contains(
4942
						this.element[ 0 ],
4943
						this.document[ 0 ].activeElement
4944
					);
4945
					if ( notContained ) {
4946
						this.collapseAll( event );
4947
					}
4948
				} );
4949
			},
4950
			keydown: "_keydown"
4951
		} );
4952
 
4953
		this.refresh();
4954
 
4955
		// Clicks outside of a menu collapse any open menus
4956
		this._on( this.document, {
4957
			click: function( event ) {
4958
				if ( this._closeOnDocumentClick( event ) ) {
4959
					this.collapseAll( event, true );
4960
				}
4961
 
4962
				// Reset the mouseHandled flag
4963
				this.mouseHandled = false;
4964
			}
4965
		} );
4966
	},
4967
 
4968
	_activateItem: function( event ) {
4969
 
4970
		// Ignore mouse events while typeahead is active, see #10458.
4971
		// Prevents focusing the wrong item when typeahead causes a scroll while the mouse
4972
		// is over an item in the menu
4973
		if ( this.previousFilter ) {
4974
			return;
4975
		}
4976
 
4977
		// If the mouse didn't actually move, but the page was scrolled, ignore the event (#9356)
4978
		if ( event.clientX === this.lastMousePosition.x &&
4979
				event.clientY === this.lastMousePosition.y ) {
4980
			return;
4981
		}
4982
 
4983
		this.lastMousePosition = {
4984
			x: event.clientX,
4985
			y: event.clientY
4986
		};
4987
 
4988
		var actualTarget = $( event.target ).closest( ".ui-menu-item" ),
4989
			target = $( event.currentTarget );
4990
 
4991
		// Ignore bubbled events on parent items, see #11641
4992
		if ( actualTarget[ 0 ] !== target[ 0 ] ) {
4993
			return;
4994
		}
4995
 
4996
		// If the item is already active, there's nothing to do
4997
		if ( target.is( ".ui-state-active" ) ) {
4998
			return;
4999
		}
5000
 
5001
		// Remove ui-state-active class from siblings of the newly focused menu item
5002
		// to avoid a jump caused by adjacent elements both having a class with a border
5003
		this._removeClass( target.siblings().children( ".ui-state-active" ),
5004
			null, "ui-state-active" );
5005
		this.focus( event, target );
5006
	},
5007
 
5008
	_destroy: function() {
5009
		var items = this.element.find( ".ui-menu-item" )
5010
				.removeAttr( "role aria-disabled" ),
5011
			submenus = items.children( ".ui-menu-item-wrapper" )
5012
				.removeUniqueId()
5013
				.removeAttr( "tabIndex role aria-haspopup" );
5014
 
5015
		// Destroy (sub)menus
5016
		this.element
5017
			.removeAttr( "aria-activedescendant" )
5018
			.find( ".ui-menu" ).addBack()
5019
				.removeAttr( "role aria-labelledby aria-expanded aria-hidden aria-disabled " +
5020
					"tabIndex" )
5021
				.removeUniqueId()
5022
				.show();
5023
 
5024
		submenus.children().each( function() {
5025
			var elem = $( this );
5026
			if ( elem.data( "ui-menu-submenu-caret" ) ) {
5027
				elem.remove();
5028
			}
5029
		} );
5030
	},
5031
 
5032
	_keydown: function( event ) {
5033
		var match, prev, character, skip,
5034
			preventDefault = true;
5035
 
5036
		switch ( event.keyCode ) {
5037
		case $.ui.keyCode.PAGE_UP:
5038
			this.previousPage( event );
5039
			break;
5040
		case $.ui.keyCode.PAGE_DOWN:
5041
			this.nextPage( event );
5042
			break;
5043
		case $.ui.keyCode.HOME:
5044
			this._move( "first", "first", event );
5045
			break;
5046
		case $.ui.keyCode.END:
5047
			this._move( "last", "last", event );
5048
			break;
5049
		case $.ui.keyCode.UP:
5050
			this.previous( event );
5051
			break;
5052
		case $.ui.keyCode.DOWN:
5053
			this.next( event );
5054
			break;
5055
		case $.ui.keyCode.LEFT:
5056
			this.collapse( event );
5057
			break;
5058
		case $.ui.keyCode.RIGHT:
5059
			if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
5060
				this.expand( event );
5061
			}
5062
			break;
5063
		case $.ui.keyCode.ENTER:
5064
		case $.ui.keyCode.SPACE:
5065
			this._activate( event );
5066
			break;
5067
		case $.ui.keyCode.ESCAPE:
5068
			this.collapse( event );
5069
			break;
5070
		default:
5071
			preventDefault = false;
5072
			prev = this.previousFilter || "";
5073
			skip = false;
5074
 
5075
			// Support number pad values
5076
			character = event.keyCode >= 96 && event.keyCode <= 105 ?
5077
				( event.keyCode - 96 ).toString() : String.fromCharCode( event.keyCode );
5078
 
5079
			clearTimeout( this.filterTimer );
5080
 
5081
			if ( character === prev ) {
5082
				skip = true;
5083
			} else {
5084
				character = prev + character;
5085
			}
5086
 
5087
			match = this._filterMenuItems( character );
5088
			match = skip && match.index( this.active.next() ) !== -1 ?
5089
				this.active.nextAll( ".ui-menu-item" ) :
5090
				match;
5091
 
5092
			// If no matches on the current filter, reset to the last character pressed
5093
			// to move down the menu to the first item that starts with that character
5094
			if ( !match.length ) {
5095
				character = String.fromCharCode( event.keyCode );
5096
				match = this._filterMenuItems( character );
5097
			}
5098
 
5099
			if ( match.length ) {
5100
				this.focus( event, match );
5101
				this.previousFilter = character;
5102
				this.filterTimer = this._delay( function() {
5103
					delete this.previousFilter;
5104
				}, 1000 );
5105
			} else {
5106
				delete this.previousFilter;
5107
			}
5108
		}
5109
 
5110
		if ( preventDefault ) {
5111
			event.preventDefault();
5112
		}
5113
	},
5114
 
5115
	_activate: function( event ) {
5116
		if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
5117
			if ( this.active.children( "[aria-haspopup='true']" ).length ) {
5118
				this.expand( event );
5119
			} else {
5120
				this.select( event );
5121
			}
5122
		}
5123
	},
5124
 
5125
	refresh: function() {
5126
		var menus, items, newSubmenus, newItems, newWrappers,
5127
			that = this,
5128
			icon = this.options.icons.submenu,
5129
			submenus = this.element.find( this.options.menus );
5130
 
5131
		this._toggleClass( "ui-menu-icons", null, !!this.element.find( ".ui-icon" ).length );
5132
 
5133
		// Initialize nested menus
5134
		newSubmenus = submenus.filter( ":not(.ui-menu)" )
5135
			.hide()
5136
			.attr( {
5137
				role: this.options.role,
5138
				"aria-hidden": "true",
5139
				"aria-expanded": "false"
5140
			} )
5141
			.each( function() {
5142
				var menu = $( this ),
5143
					item = menu.prev(),
5144
					submenuCaret = $( "<span>" ).data( "ui-menu-submenu-caret", true );
5145
 
5146
				that._addClass( submenuCaret, "ui-menu-icon", "ui-icon " + icon );
5147
				item
5148
					.attr( "aria-haspopup", "true" )
5149
					.prepend( submenuCaret );
5150
				menu.attr( "aria-labelledby", item.attr( "id" ) );
5151
			} );
5152
 
5153
		this._addClass( newSubmenus, "ui-menu", "ui-widget ui-widget-content ui-front" );
5154
 
5155
		menus = submenus.add( this.element );
5156
		items = menus.find( this.options.items );
5157
 
5158
		// Initialize menu-items containing spaces and/or dashes only as dividers
5159
		items.not( ".ui-menu-item" ).each( function() {
5160
			var item = $( this );
5161
			if ( that._isDivider( item ) ) {
5162
				that._addClass( item, "ui-menu-divider", "ui-widget-content" );
5163
			}
5164
		} );
5165
 
5166
		// Don't refresh list items that are already adapted
5167
		newItems = items.not( ".ui-menu-item, .ui-menu-divider" );
5168
		newWrappers = newItems.children()
5169
			.not( ".ui-menu" )
5170
				.uniqueId()
5171
				.attr( {
5172
					tabIndex: -1,
5173
					role: this._itemRole()
5174
				} );
5175
		this._addClass( newItems, "ui-menu-item" )
5176
			._addClass( newWrappers, "ui-menu-item-wrapper" );
5177
 
5178
		// Add aria-disabled attribute to any disabled menu item
5179
		items.filter( ".ui-state-disabled" ).attr( "aria-disabled", "true" );
5180
 
5181
		// If the active item has been removed, blur the menu
5182
		if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
5183
			this.blur();
5184
		}
5185
	},
5186
 
5187
	_itemRole: function() {
5188
		return {
5189
			menu: "menuitem",
5190
			listbox: "option"
5191
		}[ this.options.role ];
5192
	},
5193
 
5194
	_setOption: function( key, value ) {
5195
		if ( key === "icons" ) {
5196
			var icons = this.element.find( ".ui-menu-icon" );
5197
			this._removeClass( icons, null, this.options.icons.submenu )
5198
				._addClass( icons, null, value.submenu );
5199
		}
5200
		this._super( key, value );
5201
	},
5202
 
5203
	_setOptionDisabled: function( value ) {
5204
		this._super( value );
5205
 
5206
		this.element.attr( "aria-disabled", String( value ) );
5207
		this._toggleClass( null, "ui-state-disabled", !!value );
5208
	},
5209
 
5210
	focus: function( event, item ) {
5211
		var nested, focused, activeParent;
5212
		this.blur( event, event && event.type === "focus" );
5213
 
5214
		this._scrollIntoView( item );
5215
 
5216
		this.active = item.first();
5217
 
5218
		focused = this.active.children( ".ui-menu-item-wrapper" );
5219
		this._addClass( focused, null, "ui-state-active" );
5220
 
5221
		// Only update aria-activedescendant if there's a role
5222
		// otherwise we assume focus is managed elsewhere
5223
		if ( this.options.role ) {
5224
			this.element.attr( "aria-activedescendant", focused.attr( "id" ) );
5225
		}
5226
 
5227
		// Highlight active parent menu item, if any
5228
		activeParent = this.active
5229
			.parent()
5230
				.closest( ".ui-menu-item" )
5231
					.children( ".ui-menu-item-wrapper" );
5232
		this._addClass( activeParent, null, "ui-state-active" );
5233
 
5234
		if ( event && event.type === "keydown" ) {
5235
			this._close();
5236
		} else {
5237
			this.timer = this._delay( function() {
5238
				this._close();
5239
			}, this.delay );
5240
		}
5241
 
5242
		nested = item.children( ".ui-menu" );
5243
		if ( nested.length && event && ( /^mouse/.test( event.type ) ) ) {
5244
			this._startOpening( nested );
5245
		}
5246
		this.activeMenu = item.parent();
5247
 
5248
		this._trigger( "focus", event, { item: item } );
5249
	},
5250
 
5251
	_scrollIntoView: function( item ) {
5252
		var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight;
5253
		if ( this._hasScroll() ) {
5254
			borderTop = parseFloat( $.css( this.activeMenu[ 0 ], "borderTopWidth" ) ) || 0;
5255
			paddingTop = parseFloat( $.css( this.activeMenu[ 0 ], "paddingTop" ) ) || 0;
5256
			offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop;
5257
			scroll = this.activeMenu.scrollTop();
5258
			elementHeight = this.activeMenu.height();
5259
			itemHeight = item.outerHeight();
5260
 
5261
			if ( offset < 0 ) {
5262
				this.activeMenu.scrollTop( scroll + offset );
5263
			} else if ( offset + itemHeight > elementHeight ) {
5264
				this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight );
5265
			}
5266
		}
5267
	},
5268
 
5269
	blur: function( event, fromFocus ) {
5270
		if ( !fromFocus ) {
5271
			clearTimeout( this.timer );
5272
		}
5273
 
5274
		if ( !this.active ) {
5275
			return;
5276
		}
5277
 
5278
		this._removeClass( this.active.children( ".ui-menu-item-wrapper" ),
5279
			null, "ui-state-active" );
5280
 
5281
		this._trigger( "blur", event, { item: this.active } );
5282
		this.active = null;
5283
	},
5284
 
5285
	_startOpening: function( submenu ) {
5286
		clearTimeout( this.timer );
5287
 
5288
		// Don't open if already open fixes a Firefox bug that caused a .5 pixel
5289
		// shift in the submenu position when mousing over the caret icon
5290
		if ( submenu.attr( "aria-hidden" ) !== "true" ) {
5291
			return;
5292
		}
5293
 
5294
		this.timer = this._delay( function() {
5295
			this._close();
5296
			this._open( submenu );
5297
		}, this.delay );
5298
	},
5299
 
5300
	_open: function( submenu ) {
5301
		var position = $.extend( {
5302
			of: this.active
5303
		}, this.options.position );
5304
 
5305
		clearTimeout( this.timer );
5306
		this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) )
5307
			.hide()
5308
			.attr( "aria-hidden", "true" );
5309
 
5310
		submenu
5311
			.show()
5312
			.removeAttr( "aria-hidden" )
5313
			.attr( "aria-expanded", "true" )
5314
			.position( position );
5315
	},
5316
 
5317
	collapseAll: function( event, all ) {
5318
		clearTimeout( this.timer );
5319
		this.timer = this._delay( function() {
5320
 
5321
			// If we were passed an event, look for the submenu that contains the event
5322
			var currentMenu = all ? this.element :
5323
				$( event && event.target ).closest( this.element.find( ".ui-menu" ) );
5324
 
5325
			// If we found no valid submenu ancestor, use the main menu to close all
5326
			// sub menus anyway
5327
			if ( !currentMenu.length ) {
5328
				currentMenu = this.element;
5329
			}
5330
 
5331
			this._close( currentMenu );
5332
 
5333
			this.blur( event );
5334
 
5335
			// Work around active item staying active after menu is blurred
5336
			this._removeClass( currentMenu.find( ".ui-state-active" ), null, "ui-state-active" );
5337
 
5338
			this.activeMenu = currentMenu;
5339
		}, all ? 0 : this.delay );
5340
	},
5341
 
5342
	// With no arguments, closes the currently active menu - if nothing is active
5343
	// it closes all menus.  If passed an argument, it will search for menus BELOW
5344
	_close: function( startMenu ) {
5345
		if ( !startMenu ) {
5346
			startMenu = this.active ? this.active.parent() : this.element;
5347
		}
5348
 
5349
		startMenu.find( ".ui-menu" )
5350
			.hide()
5351
			.attr( "aria-hidden", "true" )
5352
			.attr( "aria-expanded", "false" );
5353
	},
5354
 
5355
	_closeOnDocumentClick: function( event ) {
5356
		return !$( event.target ).closest( ".ui-menu" ).length;
5357
	},
5358
 
5359
	_isDivider: function( item ) {
5360
 
5361
		// Match hyphen, em dash, en dash
5362
		return !/[^\-\u2014\u2013\s]/.test( item.text() );
5363
	},
5364
 
5365
	collapse: function( event ) {
5366
		var newItem = this.active &&
5367
			this.active.parent().closest( ".ui-menu-item", this.element );
5368
		if ( newItem && newItem.length ) {
5369
			this._close();
5370
			this.focus( event, newItem );
5371
		}
5372
	},
5373
 
5374
	expand: function( event ) {
5375
		var newItem = this.active && this._menuItems( this.active.children( ".ui-menu" ) ).first();
5376
 
5377
		if ( newItem && newItem.length ) {
5378
			this._open( newItem.parent() );
5379
 
5380
			// Delay so Firefox will not hide activedescendant change in expanding submenu from AT
5381
			this._delay( function() {
5382
				this.focus( event, newItem );
5383
			} );
5384
		}
5385
	},
5386
 
5387
	next: function( event ) {
5388
		this._move( "next", "first", event );
5389
	},
5390
 
5391
	previous: function( event ) {
5392
		this._move( "prev", "last", event );
5393
	},
5394
 
5395
	isFirstItem: function() {
5396
		return this.active && !this.active.prevAll( ".ui-menu-item" ).length;
5397
	},
5398
 
5399
	isLastItem: function() {
5400
		return this.active && !this.active.nextAll( ".ui-menu-item" ).length;
5401
	},
5402
 
5403
	_menuItems: function( menu ) {
5404
		return ( menu || this.element )
5405
			.find( this.options.items )
5406
			.filter( ".ui-menu-item" );
5407
	},
5408
 
5409
	_move: function( direction, filter, event ) {
5410
		var next;
5411
		if ( this.active ) {
5412
			if ( direction === "first" || direction === "last" ) {
5413
				next = this.active
5414
					[ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" )
5415
					.last();
5416
			} else {
5417
				next = this.active
5418
					[ direction + "All" ]( ".ui-menu-item" )
5419
					.first();
5420
			}
5421
		}
5422
		if ( !next || !next.length || !this.active ) {
5423
			next = this._menuItems( this.activeMenu )[ filter ]();
5424
		}
5425
 
5426
		this.focus( event, next );
5427
	},
5428
 
5429
	nextPage: function( event ) {
5430
		var item, base, height;
5431
 
5432
		if ( !this.active ) {
5433
			this.next( event );
5434
			return;
5435
		}
5436
		if ( this.isLastItem() ) {
5437
			return;
5438
		}
5439
		if ( this._hasScroll() ) {
5440
			base = this.active.offset().top;
5441
			height = this.element.innerHeight();
5442
 
5443
			// jQuery 3.2 doesn't include scrollbars in innerHeight, add it back.
5444
			if ( $.fn.jquery.indexOf( "3.2." ) === 0 ) {
5445
				height += this.element[ 0 ].offsetHeight - this.element.outerHeight();
5446
			}
5447
 
5448
			this.active.nextAll( ".ui-menu-item" ).each( function() {
5449
				item = $( this );
5450
				return item.offset().top - base - height < 0;
5451
			} );
5452
 
5453
			this.focus( event, item );
5454
		} else {
5455
			this.focus( event, this._menuItems( this.activeMenu )
5456
				[ !this.active ? "first" : "last" ]() );
5457
		}
5458
	},
5459
 
5460
	previousPage: function( event ) {
5461
		var item, base, height;
5462
		if ( !this.active ) {
5463
			this.next( event );
5464
			return;
5465
		}
5466
		if ( this.isFirstItem() ) {
5467
			return;
5468
		}
5469
		if ( this._hasScroll() ) {
5470
			base = this.active.offset().top;
5471
			height = this.element.innerHeight();
5472
 
5473
			// jQuery 3.2 doesn't include scrollbars in innerHeight, add it back.
5474
			if ( $.fn.jquery.indexOf( "3.2." ) === 0 ) {
5475
				height += this.element[ 0 ].offsetHeight - this.element.outerHeight();
5476
			}
5477
 
5478
			this.active.prevAll( ".ui-menu-item" ).each( function() {
5479
				item = $( this );
5480
				return item.offset().top - base + height > 0;
5481
			} );
5482
 
5483
			this.focus( event, item );
5484
		} else {
5485
			this.focus( event, this._menuItems( this.activeMenu ).first() );
5486
		}
5487
	},
5488
 
5489
	_hasScroll: function() {
5490
		return this.element.outerHeight() < this.element.prop( "scrollHeight" );
5491
	},
5492
 
5493
	select: function( event ) {
5494
 
5495
		// TODO: It should never be possible to not have an active item at this
5496
		// point, but the tests don't trigger mouseenter before click.
5497
		this.active = this.active || $( event.target ).closest( ".ui-menu-item" );
5498
		var ui = { item: this.active };
5499
		if ( !this.active.has( ".ui-menu" ).length ) {
5500
			this.collapseAll( event, true );
5501
		}
5502
		this._trigger( "select", event, ui );
5503
	},
5504
 
5505
	_filterMenuItems: function( character ) {
5506
		var escapedCharacter = character.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ),
5507
			regex = new RegExp( "^" + escapedCharacter, "i" );
5508
 
5509
		return this.activeMenu
5510
			.find( this.options.items )
5511
 
5512
				// Only match on items, not dividers or other content (#10571)
5513
				.filter( ".ui-menu-item" )
5514
					.filter( function() {
5515
						return regex.test(
5516
							String.prototype.trim.call(
5517
								$( this ).children( ".ui-menu-item-wrapper" ).text() ) );
5518
					} );
5519
	}
5520
} );
5521
 
5522
 
5523
/*!
5524
 * jQuery UI Autocomplete 1.14.1
5525
 * https://jqueryui.com
5526
 *
5527
 * Copyright OpenJS Foundation and other contributors
5528
 * Released under the MIT license.
5529
 * https://jquery.org/license
5530
 */
5531
 
5532
//>>label: Autocomplete
5533
//>>group: Widgets
5534
//>>description: Lists suggested words as the user is typing.
5535
//>>docs: https://api.jqueryui.com/autocomplete/
5536
//>>demos: https://jqueryui.com/autocomplete/
5537
//>>css.structure: ../../themes/base/core.css
5538
//>>css.structure: ../../themes/base/autocomplete.css
5539
//>>css.theme: ../../themes/base/theme.css
5540
 
5541
 
5542
$.widget( "ui.autocomplete", {
5543
	version: "1.14.1",
5544
	defaultElement: "<input>",
5545
	options: {
5546
		appendTo: null,
5547
		autoFocus: false,
5548
		delay: 300,
5549
		minLength: 1,
5550
		position: {
5551
			my: "left top",
5552
			at: "left bottom",
5553
			collision: "none"
5554
		},
5555
		source: null,
5556
 
5557
		// Callbacks
5558
		change: null,
5559
		close: null,
5560
		focus: null,
5561
		open: null,
5562
		response: null,
5563
		search: null,
5564
		select: null
5565
	},
5566
 
5567
	requestIndex: 0,
5568
	pending: 0,
5569
	liveRegionTimer: null,
5570
 
5571
	_create: function() {
5572
 
5573
		// Some browsers only repeat keydown events, not keypress events,
5574
		// so we use the suppressKeyPress flag to determine if we've already
5575
		// handled the keydown event. #7269
5576
		// Unfortunately the code for & in keypress is the same as the up arrow,
5577
		// so we use the suppressKeyPressRepeat flag to avoid handling keypress
5578
		// events when we know the keydown event was used to modify the
5579
		// search term. #7799
5580
		var suppressKeyPress, suppressKeyPressRepeat, suppressInput,
5581
			nodeName = this.element[ 0 ].nodeName.toLowerCase(),
5582
			isTextarea = nodeName === "textarea",
5583
			isInput = nodeName === "input";
5584
 
5585
		// Textareas are always multi-line
5586
		// Inputs are always single-line, even if inside a contentEditable element
5587
		// All other element types are determined by whether they're contentEditable
5588
		this.isMultiLine = isTextarea ||
5589
			!isInput && this.element.prop( "contentEditable" ) === "true";
5590
 
5591
		this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ];
5592
		this.isNewMenu = true;
5593
 
5594
		this._addClass( "ui-autocomplete-input" );
5595
		this.element.attr( "autocomplete", "off" );
5596
 
5597
		this._on( this.element, {
5598
			keydown: function( event ) {
5599
				if ( this.element.prop( "readOnly" ) ) {
5600
					suppressKeyPress = true;
5601
					suppressInput = true;
5602
					suppressKeyPressRepeat = true;
5603
					return;
5604
				}
5605
 
5606
				suppressKeyPress = false;
5607
				suppressInput = false;
5608
				suppressKeyPressRepeat = false;
5609
				var keyCode = $.ui.keyCode;
5610
				switch ( event.keyCode ) {
5611
				case keyCode.PAGE_UP:
5612
					suppressKeyPress = true;
5613
					this._move( "previousPage", event );
5614
					break;
5615
				case keyCode.PAGE_DOWN:
5616
					suppressKeyPress = true;
5617
					this._move( "nextPage", event );
5618
					break;
5619
				case keyCode.UP:
5620
					suppressKeyPress = true;
5621
					this._keyEvent( "previous", event );
5622
					break;
5623
				case keyCode.DOWN:
5624
					suppressKeyPress = true;
5625
					this._keyEvent( "next", event );
5626
					break;
5627
				case keyCode.ENTER:
5628
 
5629
					// when menu is open and has focus
5630
					if ( this.menu.active ) {
5631
 
5632
						// #6055 - Opera still allows the keypress to occur
5633
						// which causes forms to submit
5634
						suppressKeyPress = true;
5635
						event.preventDefault();
5636
						this.menu.select( event );
5637
					}
5638
					break;
5639
				case keyCode.TAB:
5640
					if ( this.menu.active ) {
5641
						this.menu.select( event );
5642
					}
5643
					break;
5644
				case keyCode.ESCAPE:
5645
					if ( this.menu.element.is( ":visible" ) ) {
5646
						if ( !this.isMultiLine ) {
5647
							this._value( this.term );
5648
						}
5649
						this.close( event );
5650
 
5651
						// Different browsers have different default behavior for escape
5652
						// Single press can mean undo or clear
5653
						event.preventDefault();
5654
					}
5655
					break;
5656
				default:
5657
					suppressKeyPressRepeat = true;
5658
 
5659
					// search timeout should be triggered before the input value is changed
5660
					this._searchTimeout( event );
5661
					break;
5662
				}
5663
			},
5664
			keypress: function( event ) {
5665
				if ( suppressKeyPress ) {
5666
					suppressKeyPress = false;
5667
					if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
5668
						event.preventDefault();
5669
					}
5670
					return;
5671
				}
5672
				if ( suppressKeyPressRepeat ) {
5673
					return;
5674
				}
5675
 
5676
				// Replicate some key handlers to allow them to repeat in Firefox and Opera
5677
				var keyCode = $.ui.keyCode;
5678
				switch ( event.keyCode ) {
5679
				case keyCode.PAGE_UP:
5680
					this._move( "previousPage", event );
5681
					break;
5682
				case keyCode.PAGE_DOWN:
5683
					this._move( "nextPage", event );
5684
					break;
5685
				case keyCode.UP:
5686
					this._keyEvent( "previous", event );
5687
					break;
5688
				case keyCode.DOWN:
5689
					this._keyEvent( "next", event );
5690
					break;
5691
				}
5692
			},
5693
			input: function( event ) {
5694
				if ( suppressInput ) {
5695
					suppressInput = false;
5696
					event.preventDefault();
5697
					return;
5698
				}
5699
				this._searchTimeout( event );
5700
			},
5701
			focus: function() {
5702
				this.selectedItem = null;
5703
				this.previous = this._value();
5704
			},
5705
			blur: function( event ) {
5706
				clearTimeout( this.searching );
5707
				this.close( event );
5708
				this._change( event );
5709
			}
5710
		} );
5711
 
5712
		this._initSource();
5713
		this.menu = $( "<ul>" )
5714
			.appendTo( this._appendTo() )
5715
			.menu( {
5716
 
5717
				// disable ARIA support, the live region takes care of that
5718
				role: null
5719
			} )
5720
			.hide()
5721
			.menu( "instance" );
5722
 
5723
		this._addClass( this.menu.element, "ui-autocomplete", "ui-front" );
5724
		this._on( this.menu.element, {
5725
			mousedown: function( event ) {
5726
 
5727
				// Prevent moving focus out of the text field
5728
				event.preventDefault();
5729
			},
5730
			menufocus: function( event, ui ) {
5731
				var label, item;
5732
 
5733
				// Support: Firefox
5734
				// Prevent accidental activation of menu items in Firefox (#7024 #9118)
5735
				if ( this.isNewMenu ) {
5736
					this.isNewMenu = false;
5737
					if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) {
5738
						this.menu.blur();
5739
 
5740
						this.document.one( "mousemove", function() {
5741
							$( event.target ).trigger( event.originalEvent );
5742
						} );
5743
 
5744
						return;
5745
					}
5746
				}
5747
 
5748
				item = ui.item.data( "ui-autocomplete-item" );
5749
				if ( false !== this._trigger( "focus", event, { item: item } ) ) {
5750
 
5751
					// use value to match what will end up in the input, if it was a key event
5752
					if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) {
5753
						this._value( item.value );
5754
					}
5755
				}
5756
 
5757
				// Announce the value in the liveRegion
5758
				label = ui.item.attr( "aria-label" ) || item.value;
5759
				if ( label && String.prototype.trim.call( label ).length ) {
5760
					clearTimeout( this.liveRegionTimer );
5761
					this.liveRegionTimer = this._delay( function() {
5762
						this.liveRegion.html( $( "<div>" ).text( label ) );
5763
					}, 100 );
5764
				}
5765
			},
5766
			menuselect: function( event, ui ) {
5767
				var item = ui.item.data( "ui-autocomplete-item" ),
5768
					previous = this.previous;
5769
 
5770
				// Only trigger when focus was lost (click on menu)
5771
				if ( this.element[ 0 ] !== this.document[ 0 ].activeElement ) {
5772
					this.element.trigger( "focus" );
5773
					this.previous = previous;
5774
				}
5775
 
5776
				if ( false !== this._trigger( "select", event, { item: item } ) ) {
5777
					this._value( item.value );
5778
				}
5779
 
5780
				// reset the term after the select event
5781
				// this allows custom select handling to work properly
5782
				this.term = this._value();
5783
 
5784
				this.close( event );
5785
				this.selectedItem = item;
5786
			}
5787
		} );
5788
 
5789
		this.liveRegion = $( "<div>", {
5790
			role: "status",
5791
			"aria-live": "assertive",
5792
			"aria-relevant": "additions"
5793
		} )
5794
			.appendTo( this.document[ 0 ].body );
5795
 
5796
		this._addClass( this.liveRegion, null, "ui-helper-hidden-accessible" );
5797
 
5798
		// Turning off autocomplete prevents the browser from remembering the
5799
		// value when navigating through history, so we re-enable autocomplete
5800
		// if the page is unloaded before the widget is destroyed. #7790
5801
		this._on( this.window, {
5802
			beforeunload: function() {
5803
				this.element.removeAttr( "autocomplete" );
5804
			}
5805
		} );
5806
	},
5807
 
5808
	_destroy: function() {
5809
		clearTimeout( this.searching );
5810
		this.element.removeAttr( "autocomplete" );
5811
		this.menu.element.remove();
5812
		this.liveRegion.remove();
5813
	},
5814
 
5815
	_setOption: function( key, value ) {
5816
		this._super( key, value );
5817
		if ( key === "source" ) {
5818
			this._initSource();
5819
		}
5820
		if ( key === "appendTo" ) {
5821
			this.menu.element.appendTo( this._appendTo() );
5822
		}
5823
		if ( key === "disabled" && value && this.xhr ) {
5824
			this.xhr.abort();
5825
		}
5826
	},
5827
 
5828
	_isEventTargetInWidget: function( event ) {
5829
		var menuElement = this.menu.element[ 0 ];
5830
 
5831
		return event.target === this.element[ 0 ] ||
5832
			event.target === menuElement ||
5833
			$.contains( menuElement, event.target );
5834
	},
5835
 
5836
	_closeOnClickOutside: function( event ) {
5837
		if ( !this._isEventTargetInWidget( event ) ) {
5838
			this.close();
5839
		}
5840
	},
5841
 
5842
	_appendTo: function() {
5843
		var element = this.options.appendTo;
5844
 
5845
		if ( element ) {
5846
			element = element.jquery || element.nodeType ?
5847
				$( element ) :
5848
				this.document.find( element ).eq( 0 );
5849
		}
5850
 
5851
		if ( !element || !element[ 0 ] ) {
5852
			element = this.element.closest( ".ui-front, dialog" );
5853
		}
5854
 
5855
		if ( !element.length ) {
5856
			element = this.document[ 0 ].body;
5857
		}
5858
 
5859
		return element;
5860
	},
5861
 
5862
	_initSource: function() {
5863
		var array, url,
5864
			that = this;
5865
		if ( Array.isArray( this.options.source ) ) {
5866
			array = this.options.source;
5867
			this.source = function( request, response ) {
5868
				response( $.ui.autocomplete.filter( array, request.term ) );
5869
			};
5870
		} else if ( typeof this.options.source === "string" ) {
5871
			url = this.options.source;
5872
			this.source = function( request, response ) {
5873
				if ( that.xhr ) {
5874
					that.xhr.abort();
5875
				}
5876
				that.xhr = $.ajax( {
5877
					url: url,
5878
					data: request,
5879
					dataType: "json",
5880
					success: function( data ) {
5881
						response( data );
5882
					},
5883
					error: function() {
5884
						response( [] );
5885
					}
5886
				} );
5887
			};
5888
		} else {
5889
			this.source = this.options.source;
5890
		}
5891
	},
5892
 
5893
	_searchTimeout: function( event ) {
5894
		clearTimeout( this.searching );
5895
		this.searching = this._delay( function() {
5896
 
5897
			// Search if the value has changed, or if the user retypes the same value (see #7434)
5898
			var equalValues = this.term === this._value(),
5899
				menuVisible = this.menu.element.is( ":visible" ),
5900
				modifierKey = event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;
5901
 
5902
			if ( !equalValues || ( equalValues && !menuVisible && !modifierKey ) ) {
5903
				this.selectedItem = null;
5904
				this.search( null, event );
5905
			}
5906
		}, this.options.delay );
5907
	},
5908
 
5909
	search: function( value, event ) {
5910
		value = value != null ? value : this._value();
5911
 
5912
		// Always save the actual value, not the one passed as an argument
5913
		this.term = this._value();
5914
 
5915
		if ( value.length < this.options.minLength ) {
5916
			return this.close( event );
5917
		}
5918
 
5919
		if ( this._trigger( "search", event ) === false ) {
5920
			return;
5921
		}
5922
 
5923
		return this._search( value );
5924
	},
5925
 
5926
	_search: function( value ) {
5927
		this.pending++;
5928
		this._addClass( "ui-autocomplete-loading" );
5929
		this.cancelSearch = false;
5930
 
5931
		this.source( { term: value }, this._response() );
5932
	},
5933
 
5934
	_response: function() {
5935
		var index = ++this.requestIndex;
5936
 
5937
		return function( content ) {
5938
			if ( index === this.requestIndex ) {
5939
				this.__response( content );
5940
			}
5941
 
5942
			this.pending--;
5943
			if ( !this.pending ) {
5944
				this._removeClass( "ui-autocomplete-loading" );
5945
			}
5946
		}.bind( this );
5947
	},
5948
 
5949
	__response: function( content ) {
5950
		if ( content ) {
5951
			content = this._normalize( content );
5952
		}
5953
		this._trigger( "response", null, { content: content } );
5954
		if ( !this.options.disabled && content && content.length && !this.cancelSearch ) {
5955
			this._suggest( content );
5956
			this._trigger( "open" );
5957
		} else {
5958
 
5959
			// use ._close() instead of .close() so we don't cancel future searches
5960
			this._close();
5961
		}
5962
	},
5963
 
5964
	close: function( event ) {
5965
		this.cancelSearch = true;
5966
		this._close( event );
5967
	},
5968
 
5969
	_close: function( event ) {
5970
 
5971
		// Remove the handler that closes the menu on outside clicks
5972
		this._off( this.document, "mousedown" );
5973
 
5974
		if ( this.menu.element.is( ":visible" ) ) {
5975
			this.menu.element.hide();
5976
			this.menu.blur();
5977
			this.isNewMenu = true;
5978
			this._trigger( "close", event );
5979
		}
5980
	},
5981
 
5982
	_change: function( event ) {
5983
		if ( this.previous !== this._value() ) {
5984
			this._trigger( "change", event, { item: this.selectedItem } );
5985
		}
5986
	},
5987
 
5988
	_normalize: function( items ) {
5989
 
5990
		// assume all items have the right format when the first item is complete
5991
		if ( items.length && items[ 0 ].label && items[ 0 ].value ) {
5992
			return items;
5993
		}
5994
		return $.map( items, function( item ) {
5995
			if ( typeof item === "string" ) {
5996
				return {
5997
					label: item,
5998
					value: item
5999
				};
6000
			}
6001
			return $.extend( {}, item, {
6002
				label: item.label || item.value,
6003
				value: item.value || item.label
6004
			} );
6005
		} );
6006
	},
6007
 
6008
	_suggest: function( items ) {
6009
		var ul = this.menu.element.empty();
6010
		this._renderMenu( ul, items );
6011
		this.isNewMenu = true;
6012
		this.menu.refresh();
6013
 
6014
		// Size and position menu
6015
		ul.show();
6016
		this._resizeMenu();
6017
		ul.position( $.extend( {
6018
			of: this.element
6019
		}, this.options.position ) );
6020
 
6021
		if ( this.options.autoFocus ) {
6022
			this.menu.next();
6023
		}
6024
 
6025
		// Listen for interactions outside of the widget (#6642)
6026
		this._on( this.document, {
6027
			mousedown: "_closeOnClickOutside"
6028
		} );
6029
	},
6030
 
6031
	_resizeMenu: function() {
6032
		var ul = this.menu.element;
6033
		ul.outerWidth( Math.max(
6034
 
6035
			// Firefox wraps long text (possibly a rounding bug)
6036
			// so we add 1px to avoid the wrapping (#7513)
6037
			ul.width( "" ).outerWidth() + 1,
6038
			this.element.outerWidth()
6039
		) );
6040
	},
6041
 
6042
	_renderMenu: function( ul, items ) {
6043
		var that = this;
6044
		$.each( items, function( index, item ) {
6045
			that._renderItemData( ul, item );
6046
		} );
6047
	},
6048
 
6049
	_renderItemData: function( ul, item ) {
6050
		return this._renderItem( ul, item ).data( "ui-autocomplete-item", item );
6051
	},
6052
 
6053
	_renderItem: function( ul, item ) {
6054
		return $( "<li>" )
6055
			.append( $( "<div>" ).text( item.label ) )
6056
			.appendTo( ul );
6057
	},
6058
 
6059
	_move: function( direction, event ) {
6060
		if ( !this.menu.element.is( ":visible" ) ) {
6061
			this.search( null, event );
6062
			return;
6063
		}
6064
		if ( this.menu.isFirstItem() && /^previous/.test( direction ) ||
6065
				this.menu.isLastItem() && /^next/.test( direction ) ) {
6066
 
6067
			if ( !this.isMultiLine ) {
6068
				this._value( this.term );
6069
			}
6070
 
6071
			this.menu.blur();
6072
			return;
6073
		}
6074
		this.menu[ direction ]( event );
6075
	},
6076
 
6077
	widget: function() {
6078
		return this.menu.element;
6079
	},
6080
 
6081
	_value: function() {
6082
		return this.valueMethod.apply( this.element, arguments );
6083
	},
6084
 
6085
	_keyEvent: function( keyEvent, event ) {
6086
		if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
6087
			this._move( keyEvent, event );
6088
 
6089
			// Prevents moving cursor to beginning/end of the text field in some browsers
6090
			event.preventDefault();
6091
		}
6092
	}
6093
} );
6094
 
6095
$.extend( $.ui.autocomplete, {
6096
	escapeRegex: function( value ) {
6097
		return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" );
6098
	},
6099
	filter: function( array, term ) {
6100
		var matcher = new RegExp( $.ui.autocomplete.escapeRegex( term ), "i" );
6101
		return $.grep( array, function( value ) {
6102
			return matcher.test( value.label || value.value || value );
6103
		} );
6104
	}
6105
} );
6106
 
6107
// Live region extension, adding a `messages` option
6108
// NOTE: This is an experimental API. We are still investigating
6109
// a full solution for string manipulation and internationalization.
6110
$.widget( "ui.autocomplete", $.ui.autocomplete, {
6111
	options: {
6112
		messages: {
6113
			noResults: "No search results.",
6114
			results: function( amount ) {
6115
				return amount + ( amount > 1 ? " results are" : " result is" ) +
6116
					" available, use up and down arrow keys to navigate.";
6117
			}
6118
		}
6119
	},
6120
 
6121
	__response: function( content ) {
6122
		var message;
6123
		this._superApply( arguments );
6124
		if ( this.options.disabled || this.cancelSearch ) {
6125
			return;
6126
		}
6127
		if ( content && content.length ) {
6128
			message = this.options.messages.results( content.length );
6129
		} else {
6130
			message = this.options.messages.noResults;
6131
		}
6132
		clearTimeout( this.liveRegionTimer );
6133
		this.liveRegionTimer = this._delay( function() {
6134
			this.liveRegion.html( $( "<div>" ).text( message ) );
6135
		}, 100 );
6136
	}
6137
} );
6138
 
6139
var widgetsAutocomplete = $.ui.autocomplete;
6140
 
6141
 
6142
/*!
6143
 * jQuery UI Controlgroup 1.14.1
6144
 * https://jqueryui.com
6145
 *
6146
 * Copyright OpenJS Foundation and other contributors
6147
 * Released under the MIT license.
6148
 * https://jquery.org/license
6149
 */
6150
 
6151
//>>label: Controlgroup
6152
//>>group: Widgets
6153
//>>description: Visually groups form control widgets
6154
//>>docs: https://api.jqueryui.com/controlgroup/
6155
//>>demos: https://jqueryui.com/controlgroup/
6156
//>>css.structure: ../../themes/base/core.css
6157
//>>css.structure: ../../themes/base/controlgroup.css
6158
//>>css.theme: ../../themes/base/theme.css
6159
 
6160
 
6161
var controlgroupCornerRegex = /ui-corner-([a-z]){2,6}/g;
6162
 
6163
var widgetsControlgroup = $.widget( "ui.controlgroup", {
6164
	version: "1.14.1",
6165
	defaultElement: "<div>",
6166
	options: {
6167
		direction: "horizontal",
6168
		disabled: null,
6169
		onlyVisible: true,
6170
		items: {
6171
			"button": "input[type=button], input[type=submit], input[type=reset], button, a",
6172
			"controlgroupLabel": ".ui-controlgroup-label",
6173
			"checkboxradio": "input[type='checkbox'], input[type='radio']",
6174
			"selectmenu": "select",
6175
			"spinner": ".ui-spinner-input"
6176
		}
6177
	},
6178
 
6179
	_create: function() {
6180
		this._enhance();
6181
	},
6182
 
6183
	// To support the enhanced option in jQuery Mobile, we isolate DOM manipulation
6184
	_enhance: function() {
6185
		this.element.attr( "role", "toolbar" );
6186
		this.refresh();
6187
	},
6188
 
6189
	_destroy: function() {
6190
		this._callChildMethod( "destroy" );
6191
		this.childWidgets.removeData( "ui-controlgroup-data" );
6192
		this.element.removeAttr( "role" );
6193
		if ( this.options.items.controlgroupLabel ) {
6194
			this.element
6195
				.find( this.options.items.controlgroupLabel )
6196
				.find( ".ui-controlgroup-label-contents" )
6197
				.contents().unwrap();
6198
		}
6199
	},
6200
 
6201
	_initWidgets: function() {
6202
		var that = this,
6203
			childWidgets = [];
6204
 
6205
		// First we iterate over each of the items options
6206
		$.each( this.options.items, function( widget, selector ) {
6207
			var labels;
6208
			var options = {};
6209
 
6210
			// Make sure the widget has a selector set
6211
			if ( !selector ) {
6212
				return;
6213
			}
6214
 
6215
			if ( widget === "controlgroupLabel" ) {
6216
				labels = that.element.find( selector );
6217
				labels.each( function() {
6218
					var element = $( this );
6219
 
6220
					if ( element.children( ".ui-controlgroup-label-contents" ).length ) {
6221
						return;
6222
					}
6223
					element.contents()
6224
						.wrapAll( "<span class='ui-controlgroup-label-contents'></span>" );
6225
				} );
6226
				that._addClass( labels, null, "ui-widget ui-widget-content ui-state-default" );
6227
				childWidgets = childWidgets.concat( labels.get() );
6228
				return;
6229
			}
6230
 
6231
			// Make sure the widget actually exists
6232
			if ( !$.fn[ widget ] ) {
6233
				return;
6234
			}
6235
 
6236
			// We assume everything is in the middle to start because we can't determine
6237
			// first / last elements until all enhancments are done.
6238
			if ( that[ "_" + widget + "Options" ] ) {
6239
				options = that[ "_" + widget + "Options" ]( "middle" );
6240
			} else {
6241
				options = { classes: {} };
6242
			}
6243
 
6244
			// Find instances of this widget inside controlgroup and init them
6245
			that.element
6246
				.find( selector )
6247
				.each( function() {
6248
					var element = $( this );
6249
					var instance = element[ widget ]( "instance" );
6250
 
6251
					// We need to clone the default options for this type of widget to avoid
6252
					// polluting the variable options which has a wider scope than a single widget.
6253
					var instanceOptions = $.widget.extend( {}, options );
6254
 
6255
					// If the button is the child of a spinner ignore it
6256
					// TODO: Find a more generic solution
6257
					if ( widget === "button" && element.parent( ".ui-spinner" ).length ) {
6258
						return;
6259
					}
6260
 
6261
					// Create the widget if it doesn't exist
6262
					if ( !instance ) {
6263
						instance = element[ widget ]()[ widget ]( "instance" );
6264
					}
6265
					if ( instance ) {
6266
						instanceOptions.classes =
6267
							that._resolveClassesValues( instanceOptions.classes, instance );
6268
					}
6269
					element[ widget ]( instanceOptions );
6270
 
6271
					// Store an instance of the controlgroup to be able to reference
6272
					// from the outermost element for changing options and refresh
6273
					var widgetElement = element[ widget ]( "widget" );
6274
					$.data( widgetElement[ 0 ], "ui-controlgroup-data",
6275
						instance ? instance : element[ widget ]( "instance" ) );
6276
 
6277
					childWidgets.push( widgetElement[ 0 ] );
6278
				} );
6279
		} );
6280
 
6281
		this.childWidgets = $( $.uniqueSort( childWidgets ) );
6282
		this._addClass( this.childWidgets, "ui-controlgroup-item" );
6283
	},
6284
 
6285
	_callChildMethod: function( method ) {
6286
		this.childWidgets.each( function() {
6287
			var element = $( this ),
6288
				data = element.data( "ui-controlgroup-data" );
6289
			if ( data && data[ method ] ) {
6290
				data[ method ]();
6291
			}
6292
		} );
6293
	},
6294
 
6295
	_updateCornerClass: function( element, position ) {
6296
		var remove = "ui-corner-top ui-corner-bottom ui-corner-left ui-corner-right ui-corner-all";
6297
		var add = this._buildSimpleOptions( position, "label" ).classes.label;
6298
 
6299
		this._removeClass( element, null, remove );
6300
		this._addClass( element, null, add );
6301
	},
6302
 
6303
	_buildSimpleOptions: function( position, key ) {
6304
		var direction = this.options.direction === "vertical";
6305
		var result = {
6306
			classes: {}
6307
		};
6308
		result.classes[ key ] = {
6309
			"middle": "",
6310
			"first": "ui-corner-" + ( direction ? "top" : "left" ),
6311
			"last": "ui-corner-" + ( direction ? "bottom" : "right" ),
6312
			"only": "ui-corner-all"
6313
		}[ position ];
6314
 
6315
		return result;
6316
	},
6317
 
6318
	_spinnerOptions: function( position ) {
6319
		var options = this._buildSimpleOptions( position, "ui-spinner" );
6320
 
6321
		options.classes[ "ui-spinner-up" ] = "";
6322
		options.classes[ "ui-spinner-down" ] = "";
6323
 
6324
		return options;
6325
	},
6326
 
6327
	_buttonOptions: function( position ) {
6328
		return this._buildSimpleOptions( position, "ui-button" );
6329
	},
6330
 
6331
	_checkboxradioOptions: function( position ) {
6332
		return this._buildSimpleOptions( position, "ui-checkboxradio-label" );
6333
	},
6334
 
6335
	_selectmenuOptions: function( position ) {
6336
		var direction = this.options.direction === "vertical";
6337
		return {
6338
			width: direction ? "auto" : false,
6339
			classes: {
6340
				middle: {
6341
					"ui-selectmenu-button-open": "",
6342
					"ui-selectmenu-button-closed": ""
6343
				},
6344
				first: {
6345
					"ui-selectmenu-button-open": "ui-corner-" + ( direction ? "top" : "tl" ),
6346
					"ui-selectmenu-button-closed": "ui-corner-" + ( direction ? "top" : "left" )
6347
				},
6348
				last: {
6349
					"ui-selectmenu-button-open": direction ? "" : "ui-corner-tr",
6350
					"ui-selectmenu-button-closed": "ui-corner-" + ( direction ? "bottom" : "right" )
6351
				},
6352
				only: {
6353
					"ui-selectmenu-button-open": "ui-corner-top",
6354
					"ui-selectmenu-button-closed": "ui-corner-all"
6355
				}
6356
 
6357
			}[ position ]
6358
		};
6359
	},
6360
 
6361
	_resolveClassesValues: function( classes, instance ) {
6362
		var result = {};
6363
		$.each( classes, function( key ) {
6364
			var current = instance.options.classes[ key ] || "";
6365
			current = String.prototype.trim.call( current.replace( controlgroupCornerRegex, "" ) );
6366
			result[ key ] = ( current + " " + classes[ key ] ).replace( /\s+/g, " " );
6367
		} );
6368
		return result;
6369
	},
6370
 
6371
	_setOption: function( key, value ) {
6372
		if ( key === "direction" ) {
6373
			this._removeClass( "ui-controlgroup-" + this.options.direction );
6374
		}
6375
 
6376
		this._super( key, value );
6377
		if ( key === "disabled" ) {
6378
			this._callChildMethod( value ? "disable" : "enable" );
6379
			return;
6380
		}
6381
 
6382
		this.refresh();
6383
	},
6384
 
6385
	refresh: function() {
6386
		var children,
6387
			that = this;
6388
 
6389
		this._addClass( "ui-controlgroup ui-controlgroup-" + this.options.direction );
6390
 
6391
		if ( this.options.direction === "horizontal" ) {
6392
			this._addClass( null, "ui-helper-clearfix" );
6393
		}
6394
		this._initWidgets();
6395
 
6396
		children = this.childWidgets;
6397
 
6398
		// We filter here because we need to track all childWidgets not just the visible ones
6399
		if ( this.options.onlyVisible ) {
6400
			children = children.filter( ":visible" );
6401
		}
6402
 
6403
		if ( children.length ) {
6404
 
6405
			// We do this last because we need to make sure all enhancment is done
6406
			// before determining first and last
6407
			$.each( [ "first", "last" ], function( index, value ) {
6408
				var instance = children[ value ]().data( "ui-controlgroup-data" );
6409
 
6410
				if ( instance && that[ "_" + instance.widgetName + "Options" ] ) {
6411
					var options = that[ "_" + instance.widgetName + "Options" ](
6412
						children.length === 1 ? "only" : value
6413
					);
6414
					options.classes = that._resolveClassesValues( options.classes, instance );
6415
					instance.element[ instance.widgetName ]( options );
6416
				} else {
6417
					that._updateCornerClass( children[ value ](), value );
6418
				}
6419
			} );
6420
 
6421
			// Finally call the refresh method on each of the child widgets.
6422
			this._callChildMethod( "refresh" );
6423
		}
6424
	}
6425
} );
6426
 
6427
/*!
6428
 * jQuery UI Checkboxradio 1.14.1
6429
 * https://jqueryui.com
6430
 *
6431
 * Copyright OpenJS Foundation and other contributors
6432
 * Released under the MIT license.
6433
 * https://jquery.org/license
6434
 */
6435
 
6436
//>>label: Checkboxradio
6437
//>>group: Widgets
6438
//>>description: Enhances a form with multiple themeable checkboxes or radio buttons.
6439
//>>docs: https://api.jqueryui.com/checkboxradio/
6440
//>>demos: https://jqueryui.com/checkboxradio/
6441
//>>css.structure: ../../themes/base/core.css
6442
//>>css.structure: ../../themes/base/button.css
6443
//>>css.structure: ../../themes/base/checkboxradio.css
6444
//>>css.theme: ../../themes/base/theme.css
6445
 
6446
 
6447
$.widget( "ui.checkboxradio", [ $.ui.formResetMixin, {
6448
	version: "1.14.1",
6449
	options: {
6450
		disabled: null,
6451
		label: null,
6452
		icon: true,
6453
		classes: {
6454
			"ui-checkboxradio-label": "ui-corner-all",
6455
			"ui-checkboxradio-icon": "ui-corner-all"
6456
		}
6457
	},
6458
 
6459
	_getCreateOptions: function() {
6460
		var disabled, labels, labelContents;
6461
		var options = this._super() || {};
6462
 
6463
		// We read the type here, because it makes more sense to throw a element type error first,
6464
		// rather then the error for lack of a label. Often if its the wrong type, it
6465
		// won't have a label (e.g. calling on a div, btn, etc)
6466
		this._readType();
6467
 
6468
		labels = this.element.labels();
6469
 
6470
		// If there are multiple labels, use the last one
6471
		this.label = $( labels[ labels.length - 1 ] );
6472
		if ( !this.label.length ) {
6473
			$.error( "No label found for checkboxradio widget" );
6474
		}
6475
 
6476
		this.originalLabel = "";
6477
 
6478
		// We need to get the label text but this may also need to make sure it does not contain the
6479
		// input itself.
6480
		// The label contents could be text, html, or a mix. We wrap all elements
6481
		// and read the wrapper's `innerHTML` to get a string representation of
6482
		// the label, without the input as part of it.
6483
		labelContents = this.label.contents().not( this.element[ 0 ] );
6484
 
6485
		if ( labelContents.length ) {
6486
			this.originalLabel += labelContents
6487
				.clone()
6488
				.wrapAll( "<div></div>" )
6489
				.parent()
6490
				.html();
6491
		}
6492
 
6493
		// Set the label option if we found label text
6494
		if ( this.originalLabel ) {
6495
			options.label = this.originalLabel;
6496
		}
6497
 
6498
		disabled = this.element[ 0 ].disabled;
6499
		if ( disabled != null ) {
6500
			options.disabled = disabled;
6501
		}
6502
		return options;
6503
	},
6504
 
6505
	_create: function() {
6506
		var checked = this.element[ 0 ].checked;
6507
 
6508
		this._bindFormResetHandler();
6509
 
6510
		if ( this.options.disabled == null ) {
6511
			this.options.disabled = this.element[ 0 ].disabled;
6512
		}
6513
 
6514
		this._setOption( "disabled", this.options.disabled );
6515
		this._addClass( "ui-checkboxradio", "ui-helper-hidden-accessible" );
6516
		this._addClass( this.label, "ui-checkboxradio-label", "ui-button ui-widget" );
6517
 
6518
		if ( this.type === "radio" ) {
6519
			this._addClass( this.label, "ui-checkboxradio-radio-label" );
6520
		}
6521
 
6522
		if ( this.options.label && this.options.label !== this.originalLabel ) {
6523
			this._updateLabel();
6524
		} else if ( this.originalLabel ) {
6525
			this.options.label = this.originalLabel;
6526
		}
6527
 
6528
		this._enhance();
6529
 
6530
		if ( checked ) {
6531
			this._addClass( this.label, "ui-checkboxradio-checked", "ui-state-active" );
6532
		}
6533
 
6534
		this._on( {
6535
			change: "_toggleClasses",
6536
			focus: function() {
6537
				this._addClass( this.label, null, "ui-state-focus ui-visual-focus" );
6538
			},
6539
			blur: function() {
6540
				this._removeClass( this.label, null, "ui-state-focus ui-visual-focus" );
6541
			}
6542
		} );
6543
	},
6544
 
6545
	_readType: function() {
6546
		var nodeName = this.element[ 0 ].nodeName.toLowerCase();
6547
		this.type = this.element[ 0 ].type;
6548
		if ( nodeName !== "input" || !/radio|checkbox/.test( this.type ) ) {
6549
			$.error( "Can't create checkboxradio on element.nodeName=" + nodeName +
6550
				" and element.type=" + this.type );
6551
		}
6552
	},
6553
 
6554
	// Support jQuery Mobile enhanced option
6555
	_enhance: function() {
6556
		this._updateIcon( this.element[ 0 ].checked );
6557
	},
6558
 
6559
	widget: function() {
6560
		return this.label;
6561
	},
6562
 
6563
	_getRadioGroup: function() {
6564
		var group;
6565
		var name = this.element[ 0 ].name;
6566
		var nameSelector = "input[name='" + CSS.escape( name ) + "']";
6567
 
6568
		if ( !name ) {
6569
			return $( [] );
6570
		}
6571
 
6572
		if ( this.form.length ) {
6573
			group = $( this.form[ 0 ].elements ).filter( nameSelector );
6574
		} else {
6575
 
6576
			// Not inside a form, check all inputs that also are not inside a form
6577
			group = $( nameSelector ).filter( function() {
6578
				return $( $( this ).prop( "form" ) ).length === 0;
6579
			} );
6580
		}
6581
 
6582
		return group.not( this.element );
6583
	},
6584
 
6585
	_toggleClasses: function() {
6586
		var checked = this.element[ 0 ].checked;
6587
		this._toggleClass( this.label, "ui-checkboxradio-checked", "ui-state-active", checked );
6588
 
6589
		if ( this.options.icon && this.type === "checkbox" ) {
6590
			this._toggleClass( this.icon, null, "ui-icon-check ui-state-checked", checked )
6591
				._toggleClass( this.icon, null, "ui-icon-blank", !checked );
6592
		}
6593
 
6594
		if ( this.type === "radio" ) {
6595
			this._getRadioGroup()
6596
				.each( function() {
6597
					var instance = $( this ).checkboxradio( "instance" );
6598
 
6599
					if ( instance ) {
6600
						instance._removeClass( instance.label,
6601
							"ui-checkboxradio-checked", "ui-state-active" );
6602
					}
6603
				} );
6604
		}
6605
	},
6606
 
6607
	_destroy: function() {
6608
		this._unbindFormResetHandler();
6609
 
6610
		if ( this.icon ) {
6611
			this.icon.remove();
6612
			this.iconSpace.remove();
6613
		}
6614
	},
6615
 
6616
	_setOption: function( key, value ) {
6617
 
6618
		// We don't allow the value to be set to nothing
6619
		if ( key === "label" && !value ) {
6620
			return;
6621
		}
6622
 
6623
		this._super( key, value );
6624
 
6625
		if ( key === "disabled" ) {
6626
			this._toggleClass( this.label, null, "ui-state-disabled", value );
6627
			this.element[ 0 ].disabled = value;
6628
 
6629
			// Don't refresh when setting disabled
6630
			return;
6631
		}
6632
		this.refresh();
6633
	},
6634
 
6635
	_updateIcon: function( checked ) {
6636
		var toAdd = "ui-icon ui-icon-background ";
6637
 
6638
		if ( this.options.icon ) {
6639
			if ( !this.icon ) {
6640
				this.icon = $( "<span>" );
6641
				this.iconSpace = $( "<span> </span>" );
6642
				this._addClass( this.iconSpace, "ui-checkboxradio-icon-space" );
6643
			}
6644
 
6645
			if ( this.type === "checkbox" ) {
6646
				toAdd += checked ? "ui-icon-check ui-state-checked" : "ui-icon-blank";
6647
				this._removeClass( this.icon, null, checked ? "ui-icon-blank" : "ui-icon-check" );
6648
			} else {
6649
				toAdd += "ui-icon-blank";
6650
			}
6651
			this._addClass( this.icon, "ui-checkboxradio-icon", toAdd );
6652
			if ( !checked ) {
6653
				this._removeClass( this.icon, null, "ui-icon-check ui-state-checked" );
6654
			}
6655
			this.icon.prependTo( this.label ).after( this.iconSpace );
6656
		} else if ( this.icon !== undefined ) {
6657
			this.icon.remove();
6658
			this.iconSpace.remove();
6659
			delete this.icon;
6660
		}
6661
	},
6662
 
6663
	_updateLabel: function() {
6664
 
6665
		// Remove the contents of the label ( minus the icon, icon space, and input )
6666
		var contents = this.label.contents().not( this.element[ 0 ] );
6667
		if ( this.icon ) {
6668
			contents = contents.not( this.icon[ 0 ] );
6669
		}
6670
		if ( this.iconSpace ) {
6671
			contents = contents.not( this.iconSpace[ 0 ] );
6672
		}
6673
		contents.remove();
6674
 
6675
		this.label.append( this.options.label );
6676
	},
6677
 
6678
	refresh: function() {
6679
		var checked = this.element[ 0 ].checked,
6680
			isDisabled = this.element[ 0 ].disabled;
6681
 
6682
		this._updateIcon( checked );
6683
		this._toggleClass( this.label, "ui-checkboxradio-checked", "ui-state-active", checked );
6684
		if ( this.options.label !== null ) {
6685
			this._updateLabel();
6686
		}
6687
 
6688
		if ( isDisabled !== this.options.disabled ) {
6689
			this._setOptions( { "disabled": isDisabled } );
6690
		}
6691
	}
6692
 
6693
} ] );
6694
 
6695
var widgetsCheckboxradio = $.ui.checkboxradio;
6696
 
6697
 
6698
/*!
6699
 * jQuery UI Button 1.14.1
6700
 * https://jqueryui.com
6701
 *
6702
 * Copyright OpenJS Foundation and other contributors
6703
 * Released under the MIT license.
6704
 * https://jquery.org/license
6705
 */
6706
 
6707
//>>label: Button
6708
//>>group: Widgets
6709
//>>description: Enhances a form with themeable buttons.
6710
//>>docs: https://api.jqueryui.com/button/
6711
//>>demos: https://jqueryui.com/button/
6712
//>>css.structure: ../../themes/base/core.css
6713
//>>css.structure: ../../themes/base/button.css
6714
//>>css.theme: ../../themes/base/theme.css
6715
 
6716
 
6717
$.widget( "ui.button", {
6718
	version: "1.14.1",
6719
	defaultElement: "<button>",
6720
	options: {
6721
		classes: {
6722
			"ui-button": "ui-corner-all"
6723
		},
6724
		disabled: null,
6725
		icon: null,
6726
		iconPosition: "beginning",
6727
		label: null,
6728
		showLabel: true
6729
	},
6730
 
6731
	_getCreateOptions: function() {
6732
		var disabled,
6733
 
6734
			// This is to support cases like in jQuery Mobile where the base widget does have
6735
			// an implementation of _getCreateOptions
6736
			options = this._super() || {};
6737
 
6738
		this.isInput = this.element.is( "input" );
6739
 
6740
		disabled = this.element[ 0 ].disabled;
6741
		if ( disabled != null ) {
6742
			options.disabled = disabled;
6743
		}
6744
 
6745
		this.originalLabel = this.isInput ? this.element.val() : this.element.html();
6746
		if ( this.originalLabel ) {
6747
			options.label = this.originalLabel;
6748
		}
6749
 
6750
		return options;
6751
	},
6752
 
6753
	_create: function() {
6754
		if ( !this.option.showLabel & !this.options.icon ) {
6755
			this.options.showLabel = true;
6756
		}
6757
 
6758
		// We have to check the option again here even though we did in _getCreateOptions,
6759
		// because null may have been passed on init which would override what was set in
6760
		// _getCreateOptions
6761
		if ( this.options.disabled == null ) {
6762
			this.options.disabled = this.element[ 0 ].disabled || false;
6763
		}
6764
 
6765
		this.hasTitle = !!this.element.attr( "title" );
6766
 
6767
		// Check to see if the label needs to be set or if its already correct
6768
		if ( this.options.label && this.options.label !== this.originalLabel ) {
6769
			if ( this.isInput ) {
6770
				this.element.val( this.options.label );
6771
			} else {
6772
				this.element.html( this.options.label );
6773
			}
6774
		}
6775
		this._addClass( "ui-button", "ui-widget" );
6776
		this._setOption( "disabled", this.options.disabled );
6777
		this._enhance();
6778
 
6779
		if ( this.element.is( "a" ) ) {
6780
			this._on( {
6781
				"keyup": function( event ) {
6782
					if ( event.keyCode === $.ui.keyCode.SPACE ) {
6783
						event.preventDefault();
6784
 
6785
						// If a native click is available use it, so we
6786
						// actually cause navigation. Otherwise, just trigger
6787
						// a click event.
6788
						if ( this.element[ 0 ].click ) {
6789
							this.element[ 0 ].click();
6790
						} else {
6791
							this.element.trigger( "click" );
6792
						}
6793
					}
6794
				}
6795
			} );
6796
		}
6797
	},
6798
 
6799
	_enhance: function() {
6800
		if ( !this.element.is( "button" ) ) {
6801
			this.element.attr( "role", "button" );
6802
		}
6803
 
6804
		if ( this.options.icon ) {
6805
			this._updateIcon( "icon", this.options.icon );
6806
			this._updateTooltip();
6807
		}
6808
	},
6809
 
6810
	_updateTooltip: function() {
6811
		this.title = this.element.attr( "title" );
6812
 
6813
		if ( !this.options.showLabel && !this.title ) {
6814
			this.element.attr( "title", this.options.label );
6815
		}
6816
	},
6817
 
6818
	_updateIcon: function( option, value ) {
6819
		var icon = option !== "iconPosition",
6820
			position = icon ? this.options.iconPosition : value,
6821
			displayBlock = position === "top" || position === "bottom";
6822
 
6823
		// Create icon
6824
		if ( !this.icon ) {
6825
			this.icon = $( "<span>" );
6826
 
6827
			this._addClass( this.icon, "ui-button-icon", "ui-icon" );
6828
 
6829
			if ( !this.options.showLabel ) {
6830
				this._addClass( "ui-button-icon-only" );
6831
			}
6832
		} else if ( icon ) {
6833
 
6834
			// If we are updating the icon remove the old icon class
6835
			this._removeClass( this.icon, null, this.options.icon );
6836
		}
6837
 
6838
		// If we are updating the icon add the new icon class
6839
		if ( icon ) {
6840
			this._addClass( this.icon, null, value );
6841
		}
6842
 
6843
		this._attachIcon( position );
6844
 
6845
		// If the icon is on top or bottom we need to add the ui-widget-icon-block class and remove
6846
		// the iconSpace if there is one.
6847
		if ( displayBlock ) {
6848
			this._addClass( this.icon, null, "ui-widget-icon-block" );
6849
			if ( this.iconSpace ) {
6850
				this.iconSpace.remove();
6851
			}
6852
		} else {
6853
 
6854
			// Position is beginning or end so remove the ui-widget-icon-block class and add the
6855
			// space if it does not exist
6856
			if ( !this.iconSpace ) {
6857
				this.iconSpace = $( "<span> </span>" );
6858
				this._addClass( this.iconSpace, "ui-button-icon-space" );
6859
			}
6860
			this._removeClass( this.icon, null, "ui-wiget-icon-block" );
6861
			this._attachIconSpace( position );
6862
		}
6863
	},
6864
 
6865
	_destroy: function() {
6866
		this.element.removeAttr( "role" );
6867
 
6868
		if ( this.icon ) {
6869
			this.icon.remove();
6870
		}
6871
		if ( this.iconSpace ) {
6872
			this.iconSpace.remove();
6873
		}
6874
		if ( !this.hasTitle ) {
6875
			this.element.removeAttr( "title" );
6876
		}
6877
	},
6878
 
6879
	_attachIconSpace: function( iconPosition ) {
6880
		this.icon[ /^(?:end|bottom)/.test( iconPosition ) ? "before" : "after" ]( this.iconSpace );
6881
	},
6882
 
6883
	_attachIcon: function( iconPosition ) {
6884
		this.element[ /^(?:end|bottom)/.test( iconPosition ) ? "append" : "prepend" ]( this.icon );
6885
	},
6886
 
6887
	_setOptions: function( options ) {
6888
		var newShowLabel = options.showLabel === undefined ?
6889
				this.options.showLabel :
6890
				options.showLabel,
6891
			newIcon = options.icon === undefined ? this.options.icon : options.icon;
6892
 
6893
		if ( !newShowLabel && !newIcon ) {
6894
			options.showLabel = true;
6895
		}
6896
		this._super( options );
6897
	},
6898
 
6899
	_setOption: function( key, value ) {
6900
		if ( key === "icon" ) {
6901
			if ( value ) {
6902
				this._updateIcon( key, value );
6903
			} else if ( this.icon ) {
6904
				this.icon.remove();
6905
				if ( this.iconSpace ) {
6906
					this.iconSpace.remove();
6907
				}
6908
			}
6909
		}
6910
 
6911
		if ( key === "iconPosition" ) {
6912
			this._updateIcon( key, value );
6913
		}
6914
 
6915
		// Make sure we can't end up with a button that has neither text nor icon
6916
		if ( key === "showLabel" ) {
6917
				this._toggleClass( "ui-button-icon-only", null, !value );
6918
				this._updateTooltip();
6919
		}
6920
 
6921
		if ( key === "label" ) {
6922
			if ( this.isInput ) {
6923
				this.element.val( value );
6924
			} else {
6925
 
6926
				// If there is an icon, append it, else nothing then append the value
6927
				// this avoids removal of the icon when setting label text
6928
				this.element.html( value );
6929
				if ( this.icon ) {
6930
					this._attachIcon( this.options.iconPosition );
6931
					this._attachIconSpace( this.options.iconPosition );
6932
				}
6933
			}
6934
		}
6935
 
6936
		this._super( key, value );
6937
 
6938
		if ( key === "disabled" ) {
6939
			this._toggleClass( null, "ui-state-disabled", value );
6940
			this.element[ 0 ].disabled = value;
6941
			if ( value ) {
6942
				this.element.trigger( "blur" );
6943
			}
6944
		}
6945
	},
6946
 
6947
	refresh: function() {
6948
 
6949
		// Make sure to only check disabled if its an element that supports this otherwise
6950
		// check for the disabled class to determine state
6951
		var isDisabled = this.element.is( "input, button" ) ?
6952
			this.element[ 0 ].disabled : this.element.hasClass( "ui-button-disabled" );
6953
 
6954
		if ( isDisabled !== this.options.disabled ) {
6955
			this._setOptions( { disabled: isDisabled } );
6956
		}
6957
 
6958
		this._updateTooltip();
6959
	}
6960
} );
6961
 
6962
// DEPRECATED
6963
if ( $.uiBackCompat === true ) {
6964
 
6965
	// Text and Icons options
6966
	$.widget( "ui.button", $.ui.button, {
6967
		options: {
6968
			text: true,
6969
			icons: {
6970
				primary: null,
6971
				secondary: null
6972
			}
6973
		},
6974
 
6975
		_create: function() {
6976
			if ( this.options.showLabel && !this.options.text ) {
6977
				this.options.showLabel = this.options.text;
6978
			}
6979
			if ( !this.options.showLabel && this.options.text ) {
6980
				this.options.text = this.options.showLabel;
6981
			}
6982
			if ( !this.options.icon && ( this.options.icons.primary ||
6983
					this.options.icons.secondary ) ) {
6984
				if ( this.options.icons.primary ) {
6985
					this.options.icon = this.options.icons.primary;
6986
				} else {
6987
					this.options.icon = this.options.icons.secondary;
6988
					this.options.iconPosition = "end";
6989
				}
6990
			} else if ( this.options.icon ) {
6991
				this.options.icons.primary = this.options.icon;
6992
			}
6993
			this._super();
6994
		},
6995
 
6996
		_setOption: function( key, value ) {
6997
			if ( key === "text" ) {
6998
				this._super( "showLabel", value );
6999
				return;
7000
			}
7001
			if ( key === "showLabel" ) {
7002
				this.options.text = value;
7003
			}
7004
			if ( key === "icon" ) {
7005
				this.options.icons.primary = value;
7006
			}
7007
			if ( key === "icons" ) {
7008
				if ( value.primary ) {
7009
					this._super( "icon", value.primary );
7010
					this._super( "iconPosition", "beginning" );
7011
				} else if ( value.secondary ) {
7012
					this._super( "icon", value.secondary );
7013
					this._super( "iconPosition", "end" );
7014
				}
7015
			}
7016
			this._superApply( arguments );
7017
		}
7018
	} );
7019
 
7020
	$.fn.button = ( function( orig ) {
7021
		return function( options ) {
7022
			var isMethodCall = typeof options === "string";
7023
			var args = Array.prototype.slice.call( arguments, 1 );
7024
			var returnValue = this;
7025
 
7026
			if ( isMethodCall ) {
7027
 
7028
				// If this is an empty collection, we need to have the instance method
7029
				// return undefined instead of the jQuery instance
7030
				if ( !this.length && options === "instance" ) {
7031
					returnValue = undefined;
7032
				} else {
7033
					this.each( function() {
7034
						var methodValue;
7035
						var type = $( this ).attr( "type" );
7036
						var name = type !== "checkbox" && type !== "radio" ?
7037
							"button" :
7038
							"checkboxradio";
7039
						var instance = $.data( this, "ui-" + name );
7040
 
7041
						if ( options === "instance" ) {
7042
							returnValue = instance;
7043
							return false;
7044
						}
7045
 
7046
						if ( !instance ) {
7047
							return $.error( "cannot call methods on button" +
7048
								" prior to initialization; " +
7049
								"attempted to call method '" + options + "'" );
7050
						}
7051
 
7052
						if ( typeof instance[ options ] !== "function" ||
7053
							options.charAt( 0 ) === "_" ) {
7054
							return $.error( "no such method '" + options + "' for button" +
7055
								" widget instance" );
7056
						}
7057
 
7058
						methodValue = instance[ options ].apply( instance, args );
7059
 
7060
						if ( methodValue !== instance && methodValue !== undefined ) {
7061
							returnValue = methodValue && methodValue.jquery ?
7062
								returnValue.pushStack( methodValue.get() ) :
7063
								methodValue;
7064
							return false;
7065
						}
7066
					} );
7067
				}
7068
			} else {
7069
 
7070
				// Allow multiple hashes to be passed on init
7071
				if ( args.length ) {
7072
					options = $.widget.extend.apply( null, [ options ].concat( args ) );
7073
				}
7074
 
7075
				this.each( function() {
7076
					var type = $( this ).attr( "type" );
7077
					var name = type !== "checkbox" && type !== "radio" ? "button" : "checkboxradio";
7078
					var instance = $.data( this, "ui-" + name );
7079
 
7080
					if ( instance ) {
7081
						instance.option( options || {} );
7082
						if ( instance._init ) {
7083
							instance._init();
7084
						}
7085
					} else {
7086
						if ( name === "button" ) {
7087
							orig.call( $( this ), options );
7088
							return;
7089
						}
7090
 
7091
						$( this ).checkboxradio( $.extend( { icon: false }, options ) );
7092
					}
7093
				} );
7094
			}
7095
 
7096
			return returnValue;
7097
		};
7098
	} )( $.fn.button );
7099
 
7100
	$.fn.buttonset = function() {
7101
		if ( !$.ui.controlgroup ) {
7102
			$.error( "Controlgroup widget missing" );
7103
		}
7104
		if ( arguments[ 0 ] === "option" && arguments[ 1 ] === "items" && arguments[ 2 ] ) {
7105
			return this.controlgroup.apply( this,
7106
				[ arguments[ 0 ], "items.button", arguments[ 2 ] ] );
7107
		}
7108
		if ( arguments[ 0 ] === "option" && arguments[ 1 ] === "items" ) {
7109
			return this.controlgroup.apply( this, [ arguments[ 0 ], "items.button" ] );
7110
		}
7111
		if ( typeof arguments[ 0 ] === "object" && arguments[ 0 ].items ) {
7112
			arguments[ 0 ].items = {
7113
				button: arguments[ 0 ].items
7114
			};
7115
		}
7116
		return this.controlgroup.apply( this, arguments );
7117
	};
7118
}
7119
 
7120
var widgetsButton = $.ui.button;
7121
 
7122
 
7123
/* eslint-disable max-len, camelcase */
7124
/*!
7125
 * jQuery UI Datepicker 1.14.1
7126
 * https://jqueryui.com
7127
 *
7128
 * Copyright OpenJS Foundation and other contributors
7129
 * Released under the MIT license.
7130
 * https://jquery.org/license
7131
 */
7132
 
7133
//>>label: Datepicker
7134
//>>group: Widgets
7135
//>>description: Displays a calendar from an input or inline for selecting dates.
7136
//>>docs: https://api.jqueryui.com/datepicker/
7137
//>>demos: https://jqueryui.com/datepicker/
7138
//>>css.structure: ../../themes/base/core.css
7139
//>>css.structure: ../../themes/base/datepicker.css
7140
//>>css.theme: ../../themes/base/theme.css
7141
 
7142
 
7143
$.extend( $.ui, { datepicker: { version: "1.14.1" } } );
7144
 
7145
var datepicker_instActive;
7146
 
7147
function datepicker_getZindex( elem ) {
7148
	var position, value;
7149
	while ( elem.length && elem[ 0 ] !== document ) {
7150
 
7151
		// Ignore z-index if position is set to a value where z-index is ignored by the browser
7152
		// This makes behavior of this function consistent across browsers
7153
		// WebKit always returns auto if the element is positioned
7154
		position = elem.css( "position" );
7155
		if ( position === "absolute" || position === "relative" || position === "fixed" ) {
7156
 
7157
			// IE returns 0 when zIndex is not specified
7158
			// other browsers return a string
7159
			// we ignore the case of nested elements with an explicit value of 0
7160
			// <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
7161
			value = parseInt( elem.css( "zIndex" ), 10 );
7162
			if ( !isNaN( value ) && value !== 0 ) {
7163
				return value;
7164
			}
7165
		}
7166
		elem = elem.parent();
7167
	}
7168
 
7169
	return 0;
7170
}
7171
 
7172
/* Date picker manager.
7173
   Use the singleton instance of this class, $.datepicker, to interact with the date picker.
7174
   Settings for (groups of) date pickers are maintained in an instance object,
7175
   allowing multiple different settings on the same page. */
7176
 
7177
function Datepicker() {
7178
	this._curInst = null; // The current instance in use
7179
	this._keyEvent = false; // If the last event was a key event
7180
	this._disabledInputs = []; // List of date picker inputs that have been disabled
7181
	this._datepickerShowing = false; // True if the popup picker is showing , false if not
7182
	this._inDialog = false; // True if showing within a "dialog", false if not
7183
	this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division
7184
	this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class
7185
	this._appendClass = "ui-datepicker-append"; // The name of the append marker class
7186
	this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class
7187
	this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class
7188
	this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class
7189
	this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class
7190
	this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class
7191
	this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class
7192
	this.regional = []; // Available regional settings, indexed by language code
7193
	this.regional[ "" ] = { // Default regional settings
7194
		closeText: "Done", // Display text for close link
7195
		prevText: "Prev", // Display text for previous month link
7196
		nextText: "Next", // Display text for next month link
7197
		currentText: "Today", // Display text for current month link
7198
		monthNames: [ "January", "February", "March", "April", "May", "June",
7199
			"July", "August", "September", "October", "November", "December" ], // Names of months for drop-down and formatting
7200
		monthNamesShort: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ], // For formatting
7201
		dayNames: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ], // For formatting
7202
		dayNamesShort: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ], // For formatting
7203
		dayNamesMin: [ "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa" ], // Column headings for days starting at Sunday
7204
		weekHeader: "Wk", // Column header for week of the year
7205
		dateFormat: "mm/dd/yy", // See format options on parseDate
7206
		firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
7207
		isRTL: false, // True if right-to-left language, false if left-to-right
7208
		showMonthAfterYear: false, // True if the year select precedes month, false for month then year
7209
		yearSuffix: "", // Additional text to append to the year in the month headers,
7210
		selectMonthLabel: "Select month", // Invisible label for month selector
7211
		selectYearLabel: "Select year" // Invisible label for year selector
7212
	};
7213
	this._defaults = { // Global defaults for all the date picker instances
7214
		showOn: "focus", // "focus" for popup on focus,
7215
			// "button" for trigger button, or "both" for either
7216
		showAnim: "fadeIn", // Name of jQuery animation for popup
7217
		showOptions: {}, // Options for enhanced animations
7218
		defaultDate: null, // Used when field is blank: actual date,
7219
			// +/-number for offset from today, null for today
7220
		appendText: "", // Display text following the input box, e.g. showing the format
7221
		buttonText: "...", // Text for trigger button
7222
		buttonImage: "", // URL for trigger button image
7223
		buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
7224
		hideIfNoPrevNext: false, // True to hide next/previous month links
7225
			// if not applicable, false to just disable them
7226
		navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
7227
		gotoCurrent: false, // True if today link goes back to current selection instead
7228
		changeMonth: false, // True if month can be selected directly, false if only prev/next
7229
		changeYear: false, // True if year can be selected directly, false if only prev/next
7230
		yearRange: "c-10:c+10", // Range of years to display in drop-down,
7231
			// either relative to today's year (-nn:+nn), relative to currently displayed year
7232
			// (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
7233
		showOtherMonths: false, // True to show dates in other months, false to leave blank
7234
		selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
7235
		showWeek: false, // True to show week of the year, false to not show it
7236
		calculateWeek: this.iso8601Week, // How to calculate the week of the year,
7237
			// takes a Date and returns the number of the week for it
7238
		shortYearCutoff: "+10", // Short year values < this are in the current century,
7239
			// > this are in the previous century,
7240
			// string value starting with "+" for current year + value
7241
		minDate: null, // The earliest selectable date, or null for no limit
7242
		maxDate: null, // The latest selectable date, or null for no limit
7243
		duration: "fast", // Duration of display/closure
7244
		beforeShowDay: null, // Function that takes a date and returns an array with
7245
			// [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "",
7246
			// [2] = cell title (optional), e.g. $.datepicker.noWeekends
7247
		beforeShow: null, // Function that takes an input field and
7248
			// returns a set of custom settings for the date picker
7249
		onSelect: null, // Define a callback function when a date is selected
7250
		onChangeMonthYear: null, // Define a callback function when the month or year is changed
7251
		onClose: null, // Define a callback function when the datepicker is closed
7252
		onUpdateDatepicker: null, // Define a callback function when the datepicker is updated
7253
		numberOfMonths: 1, // Number of months to show at a time
7254
		showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
7255
		stepMonths: 1, // Number of months to step back/forward
7256
		stepBigMonths: 12, // Number of months to step back/forward for the big links
7257
		altField: "", // Selector for an alternate field to store selected dates into
7258
		altFormat: "", // The date format to use for the alternate field
7259
		constrainInput: true, // The input is constrained by the current date format
7260
		showButtonPanel: false, // True to show button panel, false to not show it
7261
		autoSize: false, // True to size the input for the date format, false to leave as is
7262
		disabled: false // The initial disabled state
7263
	};
7264
	$.extend( this._defaults, this.regional[ "" ] );
7265
	this.regional.en = $.extend( true, {}, this.regional[ "" ] );
7266
	this.regional[ "en-US" ] = $.extend( true, {}, this.regional.en );
7267
	this.dpDiv = datepicker_bindHover( $( "<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>" ) );
7268
}
7269
 
7270
$.extend( Datepicker.prototype, {
7271
 
7272
	/* Class name added to elements to indicate already configured with a date picker. */
7273
	markerClassName: "hasDatepicker",
7274
 
7275
	//Keep track of the maximum number of rows displayed (see #7043)
7276
	maxRows: 4,
7277
 
7278
	// TODO rename to "widget" when switching to widget factory
7279
	_widgetDatepicker: function() {
7280
		return this.dpDiv;
7281
	},
7282
 
7283
	/* Override the default settings for all instances of the date picker.
7284
	 * @param  settings  object - the new settings to use as defaults (anonymous object)
7285
	 * @return the manager object
7286
	 */
7287
	setDefaults: function( settings ) {
7288
		datepicker_extendRemove( this._defaults, settings || {} );
7289
		return this;
7290
	},
7291
 
7292
	/* Attach the date picker to a jQuery selection.
7293
	 * @param  target	element - the target input field or division or span
7294
	 * @param  settings  object - the new settings to use for this date picker instance (anonymous)
7295
	 */
7296
	_attachDatepicker: function( target, settings ) {
7297
		var nodeName, inline, inst;
7298
		nodeName = target.nodeName.toLowerCase();
7299
		inline = ( nodeName === "div" || nodeName === "span" );
7300
		if ( !target.id ) {
7301
			this.uuid += 1;
7302
			target.id = "dp" + this.uuid;
7303
		}
7304
		inst = this._newInst( $( target ), inline );
7305
		inst.settings = $.extend( {}, settings || {} );
7306
		if ( nodeName === "input" ) {
7307
			this._connectDatepicker( target, inst );
7308
		} else if ( inline ) {
7309
			this._inlineDatepicker( target, inst );
7310
		}
7311
	},
7312
 
7313
	/* Create a new instance object. */
7314
	_newInst: function( target, inline ) {
7315
		var id = target[ 0 ].id.replace( /([^A-Za-z0-9_\-])/g, "\\\\$1" ); // escape jQuery meta chars
7316
		return { id: id, input: target, // associated target
7317
			selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
7318
			drawMonth: 0, drawYear: 0, // month being drawn
7319
			inline: inline, // is datepicker inline or not
7320
			dpDiv: ( !inline ? this.dpDiv : // presentation div
7321
			datepicker_bindHover( $( "<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>" ) ) ) };
7322
	},
7323
 
7324
	/* Attach the date picker to an input field. */
7325
	_connectDatepicker: function( target, inst ) {
7326
		var input = $( target );
7327
		inst.append = $( [] );
7328
		inst.trigger = $( [] );
7329
		if ( input.hasClass( this.markerClassName ) ) {
7330
			return;
7331
		}
7332
		this._attachments( input, inst );
7333
		input.addClass( this.markerClassName ).on( "keydown", this._doKeyDown ).
7334
			on( "keypress", this._doKeyPress ).on( "keyup", this._doKeyUp );
7335
		this._autoSize( inst );
7336
		$.data( target, "datepicker", inst );
7337
 
7338
		//If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
7339
		if ( inst.settings.disabled ) {
7340
			this._disableDatepicker( target );
7341
		}
7342
	},
7343
 
7344
	/* Make attachments based on settings. */
7345
	_attachments: function( input, inst ) {
7346
		var showOn, buttonText, buttonImage,
7347
			appendText = this._get( inst, "appendText" ),
7348
			isRTL = this._get( inst, "isRTL" );
7349
 
7350
		if ( inst.append ) {
7351
			inst.append.remove();
7352
		}
7353
		if ( appendText ) {
7354
			inst.append = $( "<span>" )
7355
				.addClass( this._appendClass )
7356
				.text( appendText );
7357
			input[ isRTL ? "before" : "after" ]( inst.append );
7358
		}
7359
 
7360
		input.off( "focus", this._showDatepicker );
7361
 
7362
		if ( inst.trigger ) {
7363
			inst.trigger.remove();
7364
		}
7365
 
7366
		showOn = this._get( inst, "showOn" );
7367
		if ( showOn === "focus" || showOn === "both" ) { // pop-up date picker when in the marked field
7368
			input.on( "focus", this._showDatepicker );
7369
		}
7370
		if ( showOn === "button" || showOn === "both" ) { // pop-up date picker when button clicked
7371
			buttonText = this._get( inst, "buttonText" );
7372
			buttonImage = this._get( inst, "buttonImage" );
7373
 
7374
			if ( this._get( inst, "buttonImageOnly" ) ) {
7375
				inst.trigger = $( "<img>" )
7376
					.addClass( this._triggerClass )
7377
					.attr( {
7378
						src: buttonImage,
7379
						alt: buttonText,
7380
						title: buttonText
7381
					} );
7382
			} else {
7383
				inst.trigger = $( "<button type='button'>" )
7384
					.addClass( this._triggerClass );
7385
				if ( buttonImage ) {
7386
					inst.trigger.html(
7387
						$( "<img>" )
7388
							.attr( {
7389
								src: buttonImage,
7390
								alt: buttonText,
7391
								title: buttonText
7392
							} )
7393
					);
7394
				} else {
7395
					inst.trigger.text( buttonText );
7396
				}
7397
			}
7398
 
7399
			input[ isRTL ? "before" : "after" ]( inst.trigger );
7400
			inst.trigger.on( "click", function() {
7401
				if ( $.datepicker._datepickerShowing && $.datepicker._lastInput === input[ 0 ] ) {
7402
					$.datepicker._hideDatepicker();
7403
				} else if ( $.datepicker._datepickerShowing && $.datepicker._lastInput !== input[ 0 ] ) {
7404
					$.datepicker._hideDatepicker();
7405
					$.datepicker._showDatepicker( input[ 0 ] );
7406
				} else {
7407
					$.datepicker._showDatepicker( input[ 0 ] );
7408
				}
7409
				return false;
7410
			} );
7411
		}
7412
	},
7413
 
7414
	/* Apply the maximum length for the date format. */
7415
	_autoSize: function( inst ) {
7416
		if ( this._get( inst, "autoSize" ) && !inst.inline ) {
7417
			var findMax, max, maxI, i,
7418
				date = new Date( 2009, 12 - 1, 20 ), // Ensure double digits
7419
				dateFormat = this._get( inst, "dateFormat" );
7420
 
7421
			if ( dateFormat.match( /[DM]/ ) ) {
7422
				findMax = function( names ) {
7423
					max = 0;
7424
					maxI = 0;
7425
					for ( i = 0; i < names.length; i++ ) {
7426
						if ( names[ i ].length > max ) {
7427
							max = names[ i ].length;
7428
							maxI = i;
7429
						}
7430
					}
7431
					return maxI;
7432
				};
7433
				date.setMonth( findMax( this._get( inst, ( dateFormat.match( /MM/ ) ?
7434
					"monthNames" : "monthNamesShort" ) ) ) );
7435
				date.setDate( findMax( this._get( inst, ( dateFormat.match( /DD/ ) ?
7436
					"dayNames" : "dayNamesShort" ) ) ) + 20 - date.getDay() );
7437
			}
7438
			inst.input.attr( "size", this._formatDate( inst, date ).length );
7439
		}
7440
	},
7441
 
7442
	/* Attach an inline date picker to a div. */
7443
	_inlineDatepicker: function( target, inst ) {
7444
		var divSpan = $( target );
7445
		if ( divSpan.hasClass( this.markerClassName ) ) {
7446
			return;
7447
		}
7448
		divSpan.addClass( this.markerClassName ).append( inst.dpDiv );
7449
		$.data( target, "datepicker", inst );
7450
		this._setDate( inst, this._getDefaultDate( inst ), true );
7451
		this._updateDatepicker( inst );
7452
		this._updateAlternate( inst );
7453
 
7454
		//If disabled option is true, disable the datepicker before showing it (see ticket #5665)
7455
		if ( inst.settings.disabled ) {
7456
			this._disableDatepicker( target );
7457
		}
7458
 
7459
		// Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
7460
		// https://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
7461
		inst.dpDiv.css( "display", "block" );
7462
	},
7463
 
7464
	/* Pop-up the date picker in a "dialog" box.
7465
	 * @param  input element - ignored
7466
	 * @param  date	string or Date - the initial date to display
7467
	 * @param  onSelect  function - the function to call when a date is selected
7468
	 * @param  settings  object - update the dialog date picker instance's settings (anonymous object)
7469
	 * @param  pos int[2] - coordinates for the dialog's position within the screen or
7470
	 *					event - with x/y coordinates or
7471
	 *					leave empty for default (screen centre)
7472
	 * @return the manager object
7473
	 */
7474
	_dialogDatepicker: function( input, date, onSelect, settings, pos ) {
7475
		var id, browserWidth, browserHeight, scrollX, scrollY,
7476
			inst = this._dialogInst; // internal instance
7477
 
7478
		if ( !inst ) {
7479
			this.uuid += 1;
7480
			id = "dp" + this.uuid;
7481
			this._dialogInput = $( "<input type='text' id='" + id +
7482
				"' style='position: absolute; top: -100px; width: 0px;'/>" );
7483
			this._dialogInput.on( "keydown", this._doKeyDown );
7484
			$( "body" ).append( this._dialogInput );
7485
			inst = this._dialogInst = this._newInst( this._dialogInput, false );
7486
			inst.settings = {};
7487
			$.data( this._dialogInput[ 0 ], "datepicker", inst );
7488
		}
7489
		datepicker_extendRemove( inst.settings, settings || {} );
7490
		date = ( date && date.constructor === Date ? this._formatDate( inst, date ) : date );
7491
		this._dialogInput.val( date );
7492
 
7493
		this._pos = ( pos ? ( pos.length ? pos : [ pos.pageX, pos.pageY ] ) : null );
7494
		if ( !this._pos ) {
7495
			browserWidth = document.documentElement.clientWidth;
7496
			browserHeight = document.documentElement.clientHeight;
7497
			scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
7498
			scrollY = document.documentElement.scrollTop || document.body.scrollTop;
7499
			this._pos = // should use actual width/height below
7500
				[ ( browserWidth / 2 ) - 100 + scrollX, ( browserHeight / 2 ) - 150 + scrollY ];
7501
		}
7502
 
7503
		// Move input on screen for focus, but hidden behind dialog
7504
		this._dialogInput.css( "left", ( this._pos[ 0 ] + 20 ) + "px" ).css( "top", this._pos[ 1 ] + "px" );
7505
		inst.settings.onSelect = onSelect;
7506
		this._inDialog = true;
7507
		this.dpDiv.addClass( this._dialogClass );
7508
		this._showDatepicker( this._dialogInput[ 0 ] );
7509
		if ( $.blockUI ) {
7510
			$.blockUI( this.dpDiv );
7511
		}
7512
		$.data( this._dialogInput[ 0 ], "datepicker", inst );
7513
		return this;
7514
	},
7515
 
7516
	/* Detach a datepicker from its control.
7517
	 * @param  target	element - the target input field or division or span
7518
	 */
7519
	_destroyDatepicker: function( target ) {
7520
		var nodeName,
7521
			$target = $( target ),
7522
			inst = $.data( target, "datepicker" );
7523
 
7524
		if ( !$target.hasClass( this.markerClassName ) ) {
7525
			return;
7526
		}
7527
 
7528
		nodeName = target.nodeName.toLowerCase();
7529
		$.removeData( target, "datepicker" );
7530
		if ( nodeName === "input" ) {
7531
			inst.append.remove();
7532
			inst.trigger.remove();
7533
			$target.removeClass( this.markerClassName ).
7534
				off( "focus", this._showDatepicker ).
7535
				off( "keydown", this._doKeyDown ).
7536
				off( "keypress", this._doKeyPress ).
7537
				off( "keyup", this._doKeyUp );
7538
		} else if ( nodeName === "div" || nodeName === "span" ) {
7539
			$target.removeClass( this.markerClassName ).empty();
7540
		}
7541
 
7542
		$.datepicker._hideDatepicker();
7543
		if ( datepicker_instActive === inst ) {
7544
			datepicker_instActive = null;
7545
			this._curInst = null;
7546
		}
7547
	},
7548
 
7549
	/* Enable the date picker to a jQuery selection.
7550
	 * @param  target	element - the target input field or division or span
7551
	 */
7552
	_enableDatepicker: function( target ) {
7553
		var nodeName, inline,
7554
			$target = $( target ),
7555
			inst = $.data( target, "datepicker" );
7556
 
7557
		if ( !$target.hasClass( this.markerClassName ) ) {
7558
			return;
7559
		}
7560
 
7561
		nodeName = target.nodeName.toLowerCase();
7562
		if ( nodeName === "input" ) {
7563
			target.disabled = false;
7564
			inst.trigger.filter( "button" ).
7565
				each( function() {
7566
					this.disabled = false;
7567
				} ).end().
7568
				filter( "img" ).css( { opacity: "1.0", cursor: "" } );
7569
		} else if ( nodeName === "div" || nodeName === "span" ) {
7570
			inline = $target.children( "." + this._inlineClass );
7571
			inline.children().removeClass( "ui-state-disabled" );
7572
			inline.find( "select.ui-datepicker-month, select.ui-datepicker-year" ).
7573
				prop( "disabled", false );
7574
		}
7575
		this._disabledInputs = $.map( this._disabledInputs,
7576
 
7577
			// Delete entry
7578
			function( value ) {
7579
				return ( value === target ? null : value );
7580
			} );
7581
	},
7582
 
7583
	/* Disable the date picker to a jQuery selection.
7584
	 * @param  target	element - the target input field or division or span
7585
	 */
7586
	_disableDatepicker: function( target ) {
7587
		var nodeName, inline,
7588
			$target = $( target ),
7589
			inst = $.data( target, "datepicker" );
7590
 
7591
		if ( !$target.hasClass( this.markerClassName ) ) {
7592
			return;
7593
		}
7594
 
7595
		nodeName = target.nodeName.toLowerCase();
7596
		if ( nodeName === "input" ) {
7597
			target.disabled = true;
7598
			inst.trigger.filter( "button" ).
7599
				each( function() {
7600
					this.disabled = true;
7601
				} ).end().
7602
				filter( "img" ).css( { opacity: "0.5", cursor: "default" } );
7603
		} else if ( nodeName === "div" || nodeName === "span" ) {
7604
			inline = $target.children( "." + this._inlineClass );
7605
			inline.children().addClass( "ui-state-disabled" );
7606
			inline.find( "select.ui-datepicker-month, select.ui-datepicker-year" ).
7607
				prop( "disabled", true );
7608
		}
7609
		this._disabledInputs = $.map( this._disabledInputs,
7610
 
7611
			// Delete entry
7612
			function( value ) {
7613
				return ( value === target ? null : value );
7614
			} );
7615
		this._disabledInputs[ this._disabledInputs.length ] = target;
7616
	},
7617
 
7618
	/* Is the first field in a jQuery collection disabled as a datepicker?
7619
	 * @param  target	element - the target input field or division or span
7620
	 * @return boolean - true if disabled, false if enabled
7621
	 */
7622
	_isDisabledDatepicker: function( target ) {
7623
		if ( !target ) {
7624
			return false;
7625
		}
7626
		for ( var i = 0; i < this._disabledInputs.length; i++ ) {
7627
			if ( this._disabledInputs[ i ] === target ) {
7628
				return true;
7629
			}
7630
		}
7631
		return false;
7632
	},
7633
 
7634
	/* Retrieve the instance data for the target control.
7635
	 * @param  target  element - the target input field or division or span
7636
	 * @return  object - the associated instance data
7637
	 * @throws  error if a jQuery problem getting data
7638
	 */
7639
	_getInst: function( target ) {
7640
		try {
7641
			return $.data( target, "datepicker" );
7642
		} catch ( err ) {
7643
			throw "Missing instance data for this datepicker";
7644
		}
7645
	},
7646
 
7647
	/* Update or retrieve the settings for a date picker attached to an input field or division.
7648
	 * @param  target  element - the target input field or division or span
7649
	 * @param  name	object - the new settings to update or
7650
	 *				string - the name of the setting to change or retrieve,
7651
	 *				when retrieving also "all" for all instance settings or
7652
	 *				"defaults" for all global defaults
7653
	 * @param  value   any - the new value for the setting
7654
	 *				(omit if above is an object or to retrieve a value)
7655
	 */
7656
	_optionDatepicker: function( target, name, value ) {
7657
		var settings, date, minDate, maxDate,
7658
			inst = this._getInst( target );
7659
 
7660
		if ( arguments.length === 2 && typeof name === "string" ) {
7661
			return ( name === "defaults" ? $.extend( {}, $.datepicker._defaults ) :
7662
				( inst ? ( name === "all" ? $.extend( {}, inst.settings ) :
7663
				this._get( inst, name ) ) : null ) );
7664
		}
7665
 
7666
		settings = name || {};
7667
		if ( typeof name === "string" ) {
7668
			settings = {};
7669
			settings[ name ] = value;
7670
		}
7671
 
7672
		if ( inst ) {
7673
			if ( this._curInst === inst ) {
7674
				this._hideDatepicker();
7675
			}
7676
 
7677
			date = this._getDateDatepicker( target, true );
7678
			minDate = this._getMinMaxDate( inst, "min" );
7679
			maxDate = this._getMinMaxDate( inst, "max" );
7680
			datepicker_extendRemove( inst.settings, settings );
7681
 
7682
			// reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
7683
			if ( minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined ) {
7684
				inst.settings.minDate = this._formatDate( inst, minDate );
7685
			}
7686
			if ( maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined ) {
7687
				inst.settings.maxDate = this._formatDate( inst, maxDate );
7688
			}
7689
			if ( "disabled" in settings ) {
7690
				if ( settings.disabled ) {
7691
					this._disableDatepicker( target );
7692
				} else {
7693
					this._enableDatepicker( target );
7694
				}
7695
			}
7696
			this._attachments( $( target ), inst );
7697
			this._autoSize( inst );
7698
			this._setDate( inst, date );
7699
			this._updateAlternate( inst );
7700
			this._updateDatepicker( inst );
7701
		}
7702
	},
7703
 
7704
	// Change method deprecated
7705
	_changeDatepicker: function( target, name, value ) {
7706
		this._optionDatepicker( target, name, value );
7707
	},
7708
 
7709
	/* Redraw the date picker attached to an input field or division.
7710
	 * @param  target  element - the target input field or division or span
7711
	 */
7712
	_refreshDatepicker: function( target ) {
7713
		var inst = this._getInst( target );
7714
		if ( inst ) {
7715
			this._updateDatepicker( inst );
7716
		}
7717
	},
7718
 
7719
	/* Set the dates for a jQuery selection.
7720
	 * @param  target element - the target input field or division or span
7721
	 * @param  date	Date - the new date
7722
	 */
7723
	_setDateDatepicker: function( target, date ) {
7724
		var inst = this._getInst( target );
7725
		if ( inst ) {
7726
			this._setDate( inst, date );
7727
			this._updateDatepicker( inst );
7728
			this._updateAlternate( inst );
7729
		}
7730
	},
7731
 
7732
	/* Get the date(s) for the first entry in a jQuery selection.
7733
	 * @param  target element - the target input field or division or span
7734
	 * @param  noDefault boolean - true if no default date is to be used
7735
	 * @return Date - the current date
7736
	 */
7737
	_getDateDatepicker: function( target, noDefault ) {
7738
		var inst = this._getInst( target );
7739
		if ( inst && !inst.inline ) {
7740
			this._setDateFromField( inst, noDefault );
7741
		}
7742
		return ( inst ? this._getDate( inst ) : null );
7743
	},
7744
 
7745
	/* Handle keystrokes. */
7746
	_doKeyDown: function( event ) {
7747
		var onSelect, dateStr, sel,
7748
			inst = $.datepicker._getInst( event.target ),
7749
			handled = true,
7750
			isRTL = inst.dpDiv.is( ".ui-datepicker-rtl" );
7751
 
7752
		inst._keyEvent = true;
7753
		if ( $.datepicker._datepickerShowing ) {
7754
			switch ( event.keyCode ) {
7755
				case 9: $.datepicker._hideDatepicker();
7756
						handled = false;
7757
						break; // hide on tab out
7758
				case 13: sel = $( "td." + $.datepicker._dayOverClass + ":not(." +
7759
									$.datepicker._currentClass + ")", inst.dpDiv );
7760
						if ( sel[ 0 ] ) {
7761
							$.datepicker._selectDay( event.target, inst.selectedMonth, inst.selectedYear, sel[ 0 ] );
7762
						}
7763
 
7764
						onSelect = $.datepicker._get( inst, "onSelect" );
7765
						if ( onSelect ) {
7766
							dateStr = $.datepicker._formatDate( inst );
7767
 
7768
							// Trigger custom callback
7769
							onSelect.apply( ( inst.input ? inst.input[ 0 ] : null ), [ dateStr, inst ] );
7770
						} else {
7771
							$.datepicker._hideDatepicker();
7772
						}
7773
 
7774
						return false; // don't submit the form
7775
				case 27: $.datepicker._hideDatepicker();
7776
						break; // hide on escape
7777
				case 33: $.datepicker._adjustDate( event.target, ( event.ctrlKey ?
7778
							-$.datepicker._get( inst, "stepBigMonths" ) :
7779
							-$.datepicker._get( inst, "stepMonths" ) ), "M" );
7780
						break; // previous month/year on page up/+ ctrl
7781
				case 34: $.datepicker._adjustDate( event.target, ( event.ctrlKey ?
7782
							+$.datepicker._get( inst, "stepBigMonths" ) :
7783
							+$.datepicker._get( inst, "stepMonths" ) ), "M" );
7784
						break; // next month/year on page down/+ ctrl
7785
				case 35: if ( event.ctrlKey || event.metaKey ) {
7786
							$.datepicker._clearDate( event.target );
7787
						}
7788
						handled = event.ctrlKey || event.metaKey;
7789
						break; // clear on ctrl or command +end
7790
				case 36: if ( event.ctrlKey || event.metaKey ) {
7791
							$.datepicker._gotoToday( event.target );
7792
						}
7793
						handled = event.ctrlKey || event.metaKey;
7794
						break; // current on ctrl or command +home
7795
				case 37: if ( event.ctrlKey || event.metaKey ) {
7796
							$.datepicker._adjustDate( event.target, ( isRTL ? +1 : -1 ), "D" );
7797
						}
7798
						handled = event.ctrlKey || event.metaKey;
7799
 
7800
						// -1 day on ctrl or command +left
7801
						if ( event.originalEvent.altKey ) {
7802
							$.datepicker._adjustDate( event.target, ( event.ctrlKey ?
7803
								-$.datepicker._get( inst, "stepBigMonths" ) :
7804
								-$.datepicker._get( inst, "stepMonths" ) ), "M" );
7805
						}
7806
 
7807
						// next month/year on alt +left on Mac
7808
						break;
7809
				case 38: if ( event.ctrlKey || event.metaKey ) {
7810
							$.datepicker._adjustDate( event.target, -7, "D" );
7811
						}
7812
						handled = event.ctrlKey || event.metaKey;
7813
						break; // -1 week on ctrl or command +up
7814
				case 39: if ( event.ctrlKey || event.metaKey ) {
7815
							$.datepicker._adjustDate( event.target, ( isRTL ? -1 : +1 ), "D" );
7816
						}
7817
						handled = event.ctrlKey || event.metaKey;
7818
 
7819
						// +1 day on ctrl or command +right
7820
						if ( event.originalEvent.altKey ) {
7821
							$.datepicker._adjustDate( event.target, ( event.ctrlKey ?
7822
								+$.datepicker._get( inst, "stepBigMonths" ) :
7823
								+$.datepicker._get( inst, "stepMonths" ) ), "M" );
7824
						}
7825
 
7826
						// next month/year on alt +right
7827
						break;
7828
				case 40: if ( event.ctrlKey || event.metaKey ) {
7829
							$.datepicker._adjustDate( event.target, +7, "D" );
7830
						}
7831
						handled = event.ctrlKey || event.metaKey;
7832
						break; // +1 week on ctrl or command +down
7833
				default: handled = false;
7834
			}
7835
		} else if ( event.keyCode === 36 && event.ctrlKey ) { // display the date picker on ctrl+home
7836
			$.datepicker._showDatepicker( this );
7837
		} else {
7838
			handled = false;
7839
		}
7840
 
7841
		if ( handled ) {
7842
			event.preventDefault();
7843
			event.stopPropagation();
7844
		}
7845
	},
7846
 
7847
	/* Filter entered characters - based on date format. */
7848
	_doKeyPress: function( event ) {
7849
		var chars, chr,
7850
			inst = $.datepicker._getInst( event.target );
7851
 
7852
		if ( $.datepicker._get( inst, "constrainInput" ) ) {
7853
			chars = $.datepicker._possibleChars( $.datepicker._get( inst, "dateFormat" ) );
7854
			chr = String.fromCharCode( event.charCode == null ? event.keyCode : event.charCode );
7855
			return event.ctrlKey || event.metaKey || ( chr < " " || !chars || chars.indexOf( chr ) > -1 );
7856
		}
7857
	},
7858
 
7859
	/* Synchronise manual entry and field/alternate field. */
7860
	_doKeyUp: function( event ) {
7861
		var date,
7862
			inst = $.datepicker._getInst( event.target );
7863
 
7864
		if ( inst.input.val() !== inst.lastVal ) {
7865
			try {
7866
				date = $.datepicker.parseDate( $.datepicker._get( inst, "dateFormat" ),
7867
					( inst.input ? inst.input.val() : null ),
7868
					$.datepicker._getFormatConfig( inst ) );
7869
 
7870
				if ( date ) { // only if valid
7871
					$.datepicker._setDateFromField( inst );
7872
					$.datepicker._updateAlternate( inst );
7873
					$.datepicker._updateDatepicker( inst );
7874
				}
7875
			} catch ( err ) {
7876
			}
7877
		}
7878
		return true;
7879
	},
7880
 
7881
	/* Pop-up the date picker for a given input field.
7882
	 * If false returned from beforeShow event handler do not show.
7883
	 * @param  input  element - the input field attached to the date picker or
7884
	 *					event - if triggered by focus
7885
	 */
7886
	_showDatepicker: function( input ) {
7887
		input = input.target || input;
7888
		if ( input.nodeName.toLowerCase() !== "input" ) { // find from button/image trigger
7889
			input = $( "input", input.parentNode )[ 0 ];
7890
		}
7891
 
7892
		if ( $.datepicker._isDisabledDatepicker( input ) || $.datepicker._lastInput === input ) { // already here
7893
			return;
7894
		}
7895
 
7896
		var inst, beforeShow, beforeShowSettings, isFixed,
7897
			offset, showAnim, duration;
7898
 
7899
		inst = $.datepicker._getInst( input );
7900
		if ( $.datepicker._curInst && $.datepicker._curInst !== inst ) {
7901
			$.datepicker._curInst.dpDiv.stop( true, true );
7902
			if ( inst && $.datepicker._datepickerShowing ) {
7903
				$.datepicker._hideDatepicker( $.datepicker._curInst.input[ 0 ] );
7904
			}
7905
		}
7906
 
7907
		beforeShow = $.datepicker._get( inst, "beforeShow" );
7908
		beforeShowSettings = beforeShow ? beforeShow.apply( input, [ input, inst ] ) : {};
7909
		if ( beforeShowSettings === false ) {
7910
			return;
7911
		}
7912
		datepicker_extendRemove( inst.settings, beforeShowSettings );
7913
 
7914
		inst.lastVal = null;
7915
		$.datepicker._lastInput = input;
7916
		$.datepicker._setDateFromField( inst );
7917
 
7918
		if ( $.datepicker._inDialog ) { // hide cursor
7919
			input.value = "";
7920
		}
7921
		if ( !$.datepicker._pos ) { // position below input
7922
			$.datepicker._pos = $.datepicker._findPos( input );
7923
			$.datepicker._pos[ 1 ] += input.offsetHeight; // add the height
7924
		}
7925
 
7926
		isFixed = false;
7927
		$( input ).parents().each( function() {
7928
			isFixed |= $( this ).css( "position" ) === "fixed";
7929
			return !isFixed;
7930
		} );
7931
 
7932
		offset = { left: $.datepicker._pos[ 0 ], top: $.datepicker._pos[ 1 ] };
7933
		$.datepicker._pos = null;
7934
 
7935
		//to avoid flashes on Firefox
7936
		inst.dpDiv.empty();
7937
 
7938
		// determine sizing offscreen
7939
		inst.dpDiv.css( { position: "absolute", display: "block", top: "-1000px" } );
7940
		$.datepicker._updateDatepicker( inst );
7941
 
7942
		// fix width for dynamic number of date pickers
7943
		// and adjust position before showing
7944
		offset = $.datepicker._checkOffset( inst, offset, isFixed );
7945
		inst.dpDiv.css( { position: ( $.datepicker._inDialog && $.blockUI ?
7946
			"static" : ( isFixed ? "fixed" : "absolute" ) ), display: "none",
7947
			left: offset.left + "px", top: offset.top + "px" } );
7948
 
7949
		if ( !inst.inline ) {
7950
			showAnim = $.datepicker._get( inst, "showAnim" );
7951
			duration = $.datepicker._get( inst, "duration" );
7952
			inst.dpDiv.css( "z-index", datepicker_getZindex( $( input ) ) + 1 );
7953
			$.datepicker._datepickerShowing = true;
7954
 
7955
			if ( $.effects && $.effects.effect[ showAnim ] ) {
7956
				inst.dpDiv.show( showAnim, $.datepicker._get( inst, "showOptions" ), duration );
7957
			} else {
7958
				inst.dpDiv[ showAnim || "show" ]( showAnim ? duration : null );
7959
			}
7960
 
7961
			if ( $.datepicker._shouldFocusInput( inst ) ) {
7962
				inst.input.trigger( "focus" );
7963
			}
7964
 
7965
			$.datepicker._curInst = inst;
7966
		}
7967
	},
7968
 
7969
	/* Generate the date picker content. */
7970
	_updateDatepicker: function( inst ) {
7971
		this.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
7972
		datepicker_instActive = inst; // for delegate hover events
7973
		inst.dpDiv.empty().append( this._generateHTML( inst ) );
7974
		this._attachHandlers( inst );
7975
 
7976
		var origyearshtml,
7977
			numMonths = this._getNumberOfMonths( inst ),
7978
			cols = numMonths[ 1 ],
7979
			width = 17,
7980
			activeCell = inst.dpDiv.find( "." + this._dayOverClass + " a" ),
7981
			onUpdateDatepicker = $.datepicker._get( inst, "onUpdateDatepicker" );
7982
 
7983
		if ( activeCell.length > 0 ) {
7984
			datepicker_handleMouseover.apply( activeCell.get( 0 ) );
7985
		}
7986
 
7987
		inst.dpDiv.removeClass( "ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4" ).width( "" );
7988
		if ( cols > 1 ) {
7989
			inst.dpDiv.addClass( "ui-datepicker-multi-" + cols ).css( "width", ( width * cols ) + "em" );
7990
		}
7991
		inst.dpDiv[ ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ? "add" : "remove" ) +
7992
			"Class" ]( "ui-datepicker-multi" );
7993
		inst.dpDiv[ ( this._get( inst, "isRTL" ) ? "add" : "remove" ) +
7994
			"Class" ]( "ui-datepicker-rtl" );
7995
 
7996
		if ( inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) {
7997
			inst.input.trigger( "focus" );
7998
		}
7999
 
8000
		// Deffered render of the years select (to avoid flashes on Firefox)
8001
		if ( inst.yearshtml ) {
8002
			origyearshtml = inst.yearshtml;
8003
			setTimeout( function() {
8004
 
8005
				//assure that inst.yearshtml didn't change.
8006
				if ( origyearshtml === inst.yearshtml && inst.yearshtml ) {
8007
					inst.dpDiv.find( "select.ui-datepicker-year" ).first().replaceWith( inst.yearshtml );
8008
				}
8009
				origyearshtml = inst.yearshtml = null;
8010
			}, 0 );
8011
		}
8012
 
8013
		if ( onUpdateDatepicker ) {
8014
			onUpdateDatepicker.apply( ( inst.input ? inst.input[ 0 ] : null ), [ inst ] );
8015
		}
8016
	},
8017
 
8018
	_shouldFocusInput: function( inst ) {
8019
		return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" );
8020
	},
8021
 
8022
	/* Check positioning to remain on screen. */
8023
	_checkOffset: function( inst, offset, isFixed ) {
8024
		var dpWidth = inst.dpDiv.outerWidth(),
8025
			dpHeight = inst.dpDiv.outerHeight(),
8026
			inputWidth = inst.input ? inst.input.outerWidth() : 0,
8027
			inputHeight = inst.input ? inst.input.outerHeight() : 0,
8028
			viewWidth = document.documentElement.clientWidth + ( isFixed ? 0 : $( document ).scrollLeft() ),
8029
			viewHeight = document.documentElement.clientHeight + ( isFixed ? 0 : $( document ).scrollTop() );
8030
 
8031
		offset.left -= ( this._get( inst, "isRTL" ) ? ( dpWidth - inputWidth ) : 0 );
8032
		offset.left -= ( isFixed && offset.left === inst.input.offset().left ) ? $( document ).scrollLeft() : 0;
8033
		offset.top -= ( isFixed && offset.top === ( inst.input.offset().top + inputHeight ) ) ? $( document ).scrollTop() : 0;
8034
 
8035
		// Now check if datepicker is showing outside window viewport - move to a better place if so.
8036
		offset.left -= Math.min( offset.left, ( offset.left + dpWidth > viewWidth && viewWidth > dpWidth ) ?
8037
			Math.abs( offset.left + dpWidth - viewWidth ) : 0 );
8038
		offset.top -= Math.min( offset.top, ( offset.top + dpHeight > viewHeight && viewHeight > dpHeight ) ?
8039
			Math.abs( dpHeight + inputHeight ) : 0 );
8040
 
8041
		return offset;
8042
	},
8043
 
8044
	/* Find an object's position on the screen. */
8045
	_findPos: function( obj ) {
8046
		var position,
8047
			inst = this._getInst( obj ),
8048
			isRTL = this._get( inst, "isRTL" );
8049
 
8050
		while ( obj && ( obj.type === "hidden" || obj.nodeType !== 1 || $.expr.pseudos.hidden( obj ) ) ) {
8051
			obj = obj[ isRTL ? "previousSibling" : "nextSibling" ];
8052
		}
8053
 
8054
		position = $( obj ).offset();
8055
		return [ position.left, position.top ];
8056
	},
8057
 
8058
	/* Hide the date picker from view.
8059
	 * @param  input  element - the input field attached to the date picker
8060
	 */
8061
	_hideDatepicker: function( input ) {
8062
		var showAnim, duration, postProcess, onClose,
8063
			inst = this._curInst;
8064
 
8065
		if ( !inst || ( input && inst !== $.data( input, "datepicker" ) ) ) {
8066
			return;
8067
		}
8068
 
8069
		if ( this._datepickerShowing ) {
8070
			showAnim = this._get( inst, "showAnim" );
8071
			duration = this._get( inst, "duration" );
8072
			postProcess = function() {
8073
				$.datepicker._tidyDialog( inst );
8074
			};
8075
 
8076
			if ( $.effects && ( $.effects.effect[ showAnim ] ) ) {
8077
				inst.dpDiv.hide( showAnim, $.datepicker._get( inst, "showOptions" ), duration, postProcess );
8078
			} else {
8079
				inst.dpDiv[ ( showAnim === "slideDown" ? "slideUp" :
8080
					( showAnim === "fadeIn" ? "fadeOut" : "hide" ) ) ]( ( showAnim ? duration : null ), postProcess );
8081
			}
8082
 
8083
			if ( !showAnim ) {
8084
				postProcess();
8085
			}
8086
			this._datepickerShowing = false;
8087
 
8088
			onClose = this._get( inst, "onClose" );
8089
			if ( onClose ) {
8090
				onClose.apply( ( inst.input ? inst.input[ 0 ] : null ), [ ( inst.input ? inst.input.val() : "" ), inst ] );
8091
			}
8092
 
8093
			this._lastInput = null;
8094
			if ( this._inDialog ) {
8095
				this._dialogInput.css( { position: "absolute", left: "0", top: "-100px" } );
8096
				if ( $.blockUI ) {
8097
					$.unblockUI();
8098
					$( "body" ).append( this.dpDiv );
8099
				}
8100
			}
8101
			this._inDialog = false;
8102
		}
8103
	},
8104
 
8105
	/* Tidy up after a dialog display. */
8106
	_tidyDialog: function( inst ) {
8107
		inst.dpDiv.removeClass( this._dialogClass ).off( ".ui-datepicker-calendar" );
8108
	},
8109
 
8110
	/* Close date picker if clicked elsewhere. */
8111
	_checkExternalClick: function( event ) {
8112
		if ( !$.datepicker._curInst ) {
8113
			return;
8114
		}
8115
 
8116
		var $target = $( event.target ),
8117
			inst = $.datepicker._getInst( $target[ 0 ] );
8118
 
8119
		if ( ( ( $target[ 0 ].id !== $.datepicker._mainDivId &&
8120
				$target.parents( "#" + $.datepicker._mainDivId ).length === 0 &&
8121
				!$target.hasClass( $.datepicker.markerClassName ) &&
8122
				!$target.closest( "." + $.datepicker._triggerClass ).length &&
8123
				$.datepicker._datepickerShowing && !( $.datepicker._inDialog && $.blockUI ) ) ) ||
8124
			( $target.hasClass( $.datepicker.markerClassName ) && $.datepicker._curInst !== inst ) ) {
8125
				$.datepicker._hideDatepicker();
8126
		}
8127
	},
8128
 
8129
	/* Adjust one of the date sub-fields. */
8130
	_adjustDate: function( id, offset, period ) {
8131
		var target = $( id ),
8132
			inst = this._getInst( target[ 0 ] );
8133
 
8134
		if ( this._isDisabledDatepicker( target[ 0 ] ) ) {
8135
			return;
8136
		}
8137
		this._adjustInstDate( inst, offset, period );
8138
		this._updateDatepicker( inst );
8139
	},
8140
 
8141
	/* Action for current link. */
8142
	_gotoToday: function( id ) {
8143
		var date,
8144
			target = $( id ),
8145
			inst = this._getInst( target[ 0 ] );
8146
 
8147
		if ( this._get( inst, "gotoCurrent" ) && inst.currentDay ) {
8148
			inst.selectedDay = inst.currentDay;
8149
			inst.drawMonth = inst.selectedMonth = inst.currentMonth;
8150
			inst.drawYear = inst.selectedYear = inst.currentYear;
8151
		} else {
8152
			date = new Date();
8153
			inst.selectedDay = date.getDate();
8154
			inst.drawMonth = inst.selectedMonth = date.getMonth();
8155
			inst.drawYear = inst.selectedYear = date.getFullYear();
8156
		}
8157
		this._notifyChange( inst );
8158
		this._adjustDate( target );
8159
	},
8160
 
8161
	/* Action for selecting a new month/year. */
8162
	_selectMonthYear: function( id, select, period ) {
8163
		var target = $( id ),
8164
			inst = this._getInst( target[ 0 ] );
8165
 
8166
		inst[ "selected" + ( period === "M" ? "Month" : "Year" ) ] =
8167
		inst[ "draw" + ( period === "M" ? "Month" : "Year" ) ] =
8168
			parseInt( select.options[ select.selectedIndex ].value, 10 );
8169
 
8170
		this._notifyChange( inst );
8171
		this._adjustDate( target );
8172
	},
8173
 
8174
	/* Action for selecting a day. */
8175
	_selectDay: function( id, month, year, td ) {
8176
		var inst,
8177
			target = $( id );
8178
 
8179
		if ( $( td ).hasClass( this._unselectableClass ) || this._isDisabledDatepicker( target[ 0 ] ) ) {
8180
			return;
8181
		}
8182
 
8183
		inst = this._getInst( target[ 0 ] );
8184
		inst.selectedDay = inst.currentDay = parseInt( $( "a", td ).attr( "data-date" ) );
8185
		inst.selectedMonth = inst.currentMonth = month;
8186
		inst.selectedYear = inst.currentYear = year;
8187
		this._selectDate( id, this._formatDate( inst,
8188
			inst.currentDay, inst.currentMonth, inst.currentYear ) );
8189
	},
8190
 
8191
	/* Erase the input field and hide the date picker. */
8192
	_clearDate: function( id ) {
8193
		var target = $( id );
8194
		this._selectDate( target, "" );
8195
	},
8196
 
8197
	/* Update the input field with the selected date. */
8198
	_selectDate: function( id, dateStr ) {
8199
		var onSelect,
8200
			target = $( id ),
8201
			inst = this._getInst( target[ 0 ] );
8202
 
8203
		dateStr = ( dateStr != null ? dateStr : this._formatDate( inst ) );
8204
		if ( inst.input ) {
8205
			inst.input.val( dateStr );
8206
		}
8207
		this._updateAlternate( inst );
8208
 
8209
		onSelect = this._get( inst, "onSelect" );
8210
		if ( onSelect ) {
8211
			onSelect.apply( ( inst.input ? inst.input[ 0 ] : null ), [ dateStr, inst ] );  // trigger custom callback
8212
		} else if ( inst.input ) {
8213
			inst.input.trigger( "change" ); // fire the change event
8214
		}
8215
 
8216
		if ( inst.inline ) {
8217
			this._updateDatepicker( inst );
8218
		} else {
8219
			this._hideDatepicker();
8220
			this._lastInput = inst.input[ 0 ];
8221
			if ( typeof( inst.input[ 0 ] ) !== "object" ) {
8222
				inst.input.trigger( "focus" ); // restore focus
8223
			}
8224
			this._lastInput = null;
8225
		}
8226
	},
8227
 
8228
	/* Update any alternate field to synchronise with the main field. */
8229
	_updateAlternate: function( inst ) {
8230
		var altFormat, date, dateStr,
8231
			altField = this._get( inst, "altField" );
8232
 
8233
		if ( altField ) { // update alternate field too
8234
			altFormat = this._get( inst, "altFormat" ) || this._get( inst, "dateFormat" );
8235
			date = this._getDate( inst );
8236
			dateStr = this.formatDate( altFormat, date, this._getFormatConfig( inst ) );
8237
			$( document ).find( altField ).val( dateStr );
8238
		}
8239
	},
8240
 
8241
	/* Set as beforeShowDay function to prevent selection of weekends.
8242
	 * @param  date  Date - the date to customise
8243
	 * @return [boolean, string] - is this date selectable?, what is its CSS class?
8244
	 */
8245
	noWeekends: function( date ) {
8246
		var day = date.getDay();
8247
		return [ ( day > 0 && day < 6 ), "" ];
8248
	},
8249
 
8250
	/* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
8251
	 * @param  date  Date - the date to get the week for
8252
	 * @return  number - the number of the week within the year that contains this date
8253
	 */
8254
	iso8601Week: function( date ) {
8255
		var time,
8256
			checkDate = new Date( date.getTime() );
8257
 
8258
		// Find Thursday of this week starting on Monday
8259
		checkDate.setDate( checkDate.getDate() + 4 - ( checkDate.getDay() || 7 ) );
8260
 
8261
		time = checkDate.getTime();
8262
		checkDate.setMonth( 0 ); // Compare with Jan 1
8263
		checkDate.setDate( 1 );
8264
		return Math.floor( Math.round( ( time - checkDate ) / 86400000 ) / 7 ) + 1;
8265
	},
8266
 
8267
	/* Parse a string value into a date object.
8268
	 * See formatDate below for the possible formats.
8269
	 *
8270
	 * @param  format string - the expected format of the date
8271
	 * @param  value string - the date in the above format
8272
	 * @param  settings Object - attributes include:
8273
	 *					shortYearCutoff  number - the cutoff year for determining the century (optional)
8274
	 *					dayNamesShort	string[7] - abbreviated names of the days from Sunday (optional)
8275
	 *					dayNames		string[7] - names of the days from Sunday (optional)
8276
	 *					monthNamesShort string[12] - abbreviated names of the months (optional)
8277
	 *					monthNames		string[12] - names of the months (optional)
8278
	 * @return  Date - the extracted date value or null if value is blank
8279
	 */
8280
	parseDate: function( format, value, settings ) {
8281
		if ( format == null || value == null ) {
8282
			throw "Invalid arguments";
8283
		}
8284
 
8285
		value = ( typeof value === "object" ? value.toString() : value + "" );
8286
		if ( value === "" ) {
8287
			return null;
8288
		}
8289
 
8290
		var iFormat, dim, extra,
8291
			iValue = 0,
8292
			shortYearCutoffTemp = ( settings ? settings.shortYearCutoff : null ) || this._defaults.shortYearCutoff,
8293
			shortYearCutoff = ( typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp :
8294
				new Date().getFullYear() % 100 + parseInt( shortYearCutoffTemp, 10 ) ),
8295
			dayNamesShort = ( settings ? settings.dayNamesShort : null ) || this._defaults.dayNamesShort,
8296
			dayNames = ( settings ? settings.dayNames : null ) || this._defaults.dayNames,
8297
			monthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort,
8298
			monthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames,
8299
			year = -1,
8300
			month = -1,
8301
			day = -1,
8302
			doy = -1,
8303
			literal = false,
8304
			date,
8305
 
8306
			// Check whether a format character is doubled
8307
			lookAhead = function( match ) {
8308
				var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );
8309
				if ( matches ) {
8310
					iFormat++;
8311
				}
8312
				return matches;
8313
			},
8314
 
8315
			// Extract a number from the string value
8316
			getNumber = function( match ) {
8317
				var isDoubled = lookAhead( match ),
8318
					size = ( match === "@" ? 14 : ( match === "!" ? 20 :
8319
					( match === "y" && isDoubled ? 4 : ( match === "o" ? 3 : 2 ) ) ) ),
8320
					minSize = ( match === "y" ? size : 1 ),
8321
					digits = new RegExp( "^\\d{" + minSize + "," + size + "}" ),
8322
					num = value.substring( iValue ).match( digits );
8323
				if ( !num ) {
8324
					throw "Missing number at position " + iValue;
8325
				}
8326
				iValue += num[ 0 ].length;
8327
				return parseInt( num[ 0 ], 10 );
8328
			},
8329
 
8330
			// Extract a name from the string value and convert to an index
8331
			getName = function( match, shortNames, longNames ) {
8332
				var index = -1,
8333
					names = $.map( lookAhead( match ) ? longNames : shortNames, function( v, k ) {
8334
						return [ [ k, v ] ];
8335
					} ).sort( function( a, b ) {
8336
						return -( a[ 1 ].length - b[ 1 ].length );
8337
					} );
8338
 
8339
				$.each( names, function( i, pair ) {
8340
					var name = pair[ 1 ];
8341
					if ( value.substr( iValue, name.length ).toLowerCase() === name.toLowerCase() ) {
8342
						index = pair[ 0 ];
8343
						iValue += name.length;
8344
						return false;
8345
					}
8346
				} );
8347
				if ( index !== -1 ) {
8348
					return index + 1;
8349
				} else {
8350
					throw "Unknown name at position " + iValue;
8351
				}
8352
			},
8353
 
8354
			// Confirm that a literal character matches the string value
8355
			checkLiteral = function() {
8356
				if ( value.charAt( iValue ) !== format.charAt( iFormat ) ) {
8357
					throw "Unexpected literal at position " + iValue;
8358
				}
8359
				iValue++;
8360
			};
8361
 
8362
		for ( iFormat = 0; iFormat < format.length; iFormat++ ) {
8363
			if ( literal ) {
8364
				if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) {
8365
					literal = false;
8366
				} else {
8367
					checkLiteral();
8368
				}
8369
			} else {
8370
				switch ( format.charAt( iFormat ) ) {
8371
					case "d":
8372
						day = getNumber( "d" );
8373
						break;
8374
					case "D":
8375
						getName( "D", dayNamesShort, dayNames );
8376
						break;
8377
					case "o":
8378
						doy = getNumber( "o" );
8379
						break;
8380
					case "m":
8381
						month = getNumber( "m" );
8382
						break;
8383
					case "M":
8384
						month = getName( "M", monthNamesShort, monthNames );
8385
						break;
8386
					case "y":
8387
						year = getNumber( "y" );
8388
						break;
8389
					case "@":
8390
						date = new Date( getNumber( "@" ) );
8391
						year = date.getFullYear();
8392
						month = date.getMonth() + 1;
8393
						day = date.getDate();
8394
						break;
8395
					case "!":
8396
						date = new Date( ( getNumber( "!" ) - this._ticksTo1970 ) / 10000 );
8397
						year = date.getFullYear();
8398
						month = date.getMonth() + 1;
8399
						day = date.getDate();
8400
						break;
8401
					case "'":
8402
						if ( lookAhead( "'" ) ) {
8403
							checkLiteral();
8404
						} else {
8405
							literal = true;
8406
						}
8407
						break;
8408
					default:
8409
						checkLiteral();
8410
				}
8411
			}
8412
		}
8413
 
8414
		if ( iValue < value.length ) {
8415
			extra = value.substr( iValue );
8416
			if ( !/^\s+/.test( extra ) ) {
8417
				throw "Extra/unparsed characters found in date: " + extra;
8418
			}
8419
		}
8420
 
8421
		if ( year === -1 ) {
8422
			year = new Date().getFullYear();
8423
		} else if ( year < 100 ) {
8424
			year += new Date().getFullYear() - new Date().getFullYear() % 100 +
8425
				( year <= shortYearCutoff ? 0 : -100 );
8426
		}
8427
 
8428
		if ( doy > -1 ) {
8429
			month = 1;
8430
			day = doy;
8431
			do {
8432
				dim = this._getDaysInMonth( year, month - 1 );
8433
				if ( day <= dim ) {
8434
					break;
8435
				}
8436
				month++;
8437
				day -= dim;
8438
			} while ( true );
8439
		}
8440
 
8441
		date = this._daylightSavingAdjust( new Date( year, month - 1, day ) );
8442
		if ( date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day ) {
8443
			throw "Invalid date"; // E.g. 31/02/00
8444
		}
8445
		return date;
8446
	},
8447
 
8448
	/* Standard date formats. */
8449
	ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601)
8450
	COOKIE: "D, dd M yy",
8451
	ISO_8601: "yy-mm-dd",
8452
	RFC_822: "D, d M y",
8453
	RFC_850: "DD, dd-M-y",
8454
	RFC_1036: "D, d M y",
8455
	RFC_1123: "D, d M yy",
8456
	RFC_2822: "D, d M yy",
8457
	RSS: "D, d M y", // RFC 822
8458
	TICKS: "!",
8459
	TIMESTAMP: "@",
8460
	W3C: "yy-mm-dd", // ISO 8601
8461
 
8462
	_ticksTo1970: ( ( ( 1970 - 1 ) * 365 + Math.floor( 1970 / 4 ) - Math.floor( 1970 / 100 ) +
8463
		Math.floor( 1970 / 400 ) ) * 24 * 60 * 60 * 10000000 ),
8464
 
8465
	/* Format a date object into a string value.
8466
	 * The format can be combinations of the following:
8467
	 * d  - day of month (no leading zero)
8468
	 * dd - day of month (two digit)
8469
	 * o  - day of year (no leading zeros)
8470
	 * oo - day of year (three digit)
8471
	 * D  - day name short
8472
	 * DD - day name long
8473
	 * m  - month of year (no leading zero)
8474
	 * mm - month of year (two digit)
8475
	 * M  - month name short
8476
	 * MM - month name long
8477
	 * y  - year (two digit)
8478
	 * yy - year (four digit)
8479
	 * @ - Unix timestamp (ms since 01/01/1970)
8480
	 * ! - Windows ticks (100ns since 01/01/0001)
8481
	 * "..." - literal text
8482
	 * '' - single quote
8483
	 *
8484
	 * @param  format string - the desired format of the date
8485
	 * @param  date Date - the date value to format
8486
	 * @param  settings Object - attributes include:
8487
	 *					dayNamesShort	string[7] - abbreviated names of the days from Sunday (optional)
8488
	 *					dayNames		string[7] - names of the days from Sunday (optional)
8489
	 *					monthNamesShort string[12] - abbreviated names of the months (optional)
8490
	 *					monthNames		string[12] - names of the months (optional)
8491
	 * @return  string - the date in the above format
8492
	 */
8493
	formatDate: function( format, date, settings ) {
8494
		if ( !date ) {
8495
			return "";
8496
		}
8497
 
8498
		var iFormat,
8499
			dayNamesShort = ( settings ? settings.dayNamesShort : null ) || this._defaults.dayNamesShort,
8500
			dayNames = ( settings ? settings.dayNames : null ) || this._defaults.dayNames,
8501
			monthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort,
8502
			monthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames,
8503
 
8504
			// Check whether a format character is doubled
8505
			lookAhead = function( match ) {
8506
				var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );
8507
				if ( matches ) {
8508
					iFormat++;
8509
				}
8510
				return matches;
8511
			},
8512
 
8513
			// Format a number, with leading zero if necessary
8514
			formatNumber = function( match, value, len ) {
8515
				var num = "" + value;
8516
				if ( lookAhead( match ) ) {
8517
					while ( num.length < len ) {
8518
						num = "0" + num;
8519
					}
8520
				}
8521
				return num;
8522
			},
8523
 
8524
			// Format a name, short or long as requested
8525
			formatName = function( match, value, shortNames, longNames ) {
8526
				return ( lookAhead( match ) ? longNames[ value ] : shortNames[ value ] );
8527
			},
8528
			output = "",
8529
			literal = false;
8530
 
8531
		if ( date ) {
8532
			for ( iFormat = 0; iFormat < format.length; iFormat++ ) {
8533
				if ( literal ) {
8534
					if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) {
8535
						literal = false;
8536
					} else {
8537
						output += format.charAt( iFormat );
8538
					}
8539
				} else {
8540
					switch ( format.charAt( iFormat ) ) {
8541
						case "d":
8542
							output += formatNumber( "d", date.getDate(), 2 );
8543
							break;
8544
						case "D":
8545
							output += formatName( "D", date.getDay(), dayNamesShort, dayNames );
8546
							break;
8547
						case "o":
8548
							output += formatNumber( "o",
8549
								Math.round( ( new Date( date.getFullYear(), date.getMonth(), date.getDate() ).getTime() - new Date( date.getFullYear(), 0, 0 ).getTime() ) / 86400000 ), 3 );
8550
							break;
8551
						case "m":
8552
							output += formatNumber( "m", date.getMonth() + 1, 2 );
8553
							break;
8554
						case "M":
8555
							output += formatName( "M", date.getMonth(), monthNamesShort, monthNames );
8556
							break;
8557
						case "y":
8558
							output += ( lookAhead( "y" ) ? date.getFullYear() :
8559
								( date.getFullYear() % 100 < 10 ? "0" : "" ) + date.getFullYear() % 100 );
8560
							break;
8561
						case "@":
8562
							output += date.getTime();
8563
							break;
8564
						case "!":
8565
							output += date.getTime() * 10000 + this._ticksTo1970;
8566
							break;
8567
						case "'":
8568
							if ( lookAhead( "'" ) ) {
8569
								output += "'";
8570
							} else {
8571
								literal = true;
8572
							}
8573
							break;
8574
						default:
8575
							output += format.charAt( iFormat );
8576
					}
8577
				}
8578
			}
8579
		}
8580
		return output;
8581
	},
8582
 
8583
	/* Extract all possible characters from the date format. */
8584
	_possibleChars: function( format ) {
8585
		var iFormat,
8586
			chars = "",
8587
			literal = false,
8588
 
8589
			// Check whether a format character is doubled
8590
			lookAhead = function( match ) {
8591
				var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );
8592
				if ( matches ) {
8593
					iFormat++;
8594
				}
8595
				return matches;
8596
			};
8597
 
8598
		for ( iFormat = 0; iFormat < format.length; iFormat++ ) {
8599
			if ( literal ) {
8600
				if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) {
8601
					literal = false;
8602
				} else {
8603
					chars += format.charAt( iFormat );
8604
				}
8605
			} else {
8606
				switch ( format.charAt( iFormat ) ) {
8607
					case "d": case "m": case "y": case "@":
8608
						chars += "0123456789";
8609
						break;
8610
					case "D": case "M":
8611
						return null; // Accept anything
8612
					case "'":
8613
						if ( lookAhead( "'" ) ) {
8614
							chars += "'";
8615
						} else {
8616
							literal = true;
8617
						}
8618
						break;
8619
					default:
8620
						chars += format.charAt( iFormat );
8621
				}
8622
			}
8623
		}
8624
		return chars;
8625
	},
8626
 
8627
	/* Get a setting value, defaulting if necessary. */
8628
	_get: function( inst, name ) {
8629
		return inst.settings[ name ] !== undefined ?
8630
			inst.settings[ name ] : this._defaults[ name ];
8631
	},
8632
 
8633
	/* Parse existing date and initialise date picker. */
8634
	_setDateFromField: function( inst, noDefault ) {
8635
		if ( inst.input.val() === inst.lastVal ) {
8636
			return;
8637
		}
8638
 
8639
		var dateFormat = this._get( inst, "dateFormat" ),
8640
			dates = inst.lastVal = inst.input ? inst.input.val() : null,
8641
			defaultDate = this._getDefaultDate( inst ),
8642
			date = defaultDate,
8643
			settings = this._getFormatConfig( inst );
8644
 
8645
		try {
8646
			date = this.parseDate( dateFormat, dates, settings ) || defaultDate;
8647
		} catch ( event ) {
8648
			dates = ( noDefault ? "" : dates );
8649
		}
8650
		inst.selectedDay = date.getDate();
8651
		inst.drawMonth = inst.selectedMonth = date.getMonth();
8652
		inst.drawYear = inst.selectedYear = date.getFullYear();
8653
		inst.currentDay = ( dates ? date.getDate() : 0 );
8654
		inst.currentMonth = ( dates ? date.getMonth() : 0 );
8655
		inst.currentYear = ( dates ? date.getFullYear() : 0 );
8656
		this._adjustInstDate( inst );
8657
	},
8658
 
8659
	/* Retrieve the default date shown on opening. */
8660
	_getDefaultDate: function( inst ) {
8661
		return this._restrictMinMax( inst,
8662
			this._determineDate( inst, this._get( inst, "defaultDate" ), new Date() ) );
8663
	},
8664
 
8665
	/* A date may be specified as an exact value or a relative one. */
8666
	_determineDate: function( inst, date, defaultDate ) {
8667
		var offsetNumeric = function( offset ) {
8668
				var date = new Date();
8669
				date.setDate( date.getDate() + offset );
8670
				return date;
8671
			},
8672
			offsetString = function( offset ) {
8673
				try {
8674
					return $.datepicker.parseDate( $.datepicker._get( inst, "dateFormat" ),
8675
						offset, $.datepicker._getFormatConfig( inst ) );
8676
				} catch ( e ) {
8677
 
8678
					// Ignore
8679
				}
8680
 
8681
				var date = ( offset.toLowerCase().match( /^c/ ) ?
8682
					$.datepicker._getDate( inst ) : null ) || new Date(),
8683
					year = date.getFullYear(),
8684
					month = date.getMonth(),
8685
					day = date.getDate(),
8686
					pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,
8687
					matches = pattern.exec( offset );
8688
 
8689
				while ( matches ) {
8690
					switch ( matches[ 2 ] || "d" ) {
8691
						case "d" : case "D" :
8692
							day += parseInt( matches[ 1 ], 10 ); break;
8693
						case "w" : case "W" :
8694
							day += parseInt( matches[ 1 ], 10 ) * 7; break;
8695
						case "m" : case "M" :
8696
							month += parseInt( matches[ 1 ], 10 );
8697
							day = Math.min( day, $.datepicker._getDaysInMonth( year, month ) );
8698
							break;
8699
						case "y": case "Y" :
8700
							year += parseInt( matches[ 1 ], 10 );
8701
							day = Math.min( day, $.datepicker._getDaysInMonth( year, month ) );
8702
							break;
8703
					}
8704
					matches = pattern.exec( offset );
8705
				}
8706
				return new Date( year, month, day );
8707
			},
8708
			newDate = ( date == null || date === "" ? defaultDate : ( typeof date === "string" ? offsetString( date ) :
8709
				( typeof date === "number" ? ( isNaN( date ) ? defaultDate : offsetNumeric( date ) ) : new Date( date.getTime() ) ) ) );
8710
 
8711
		newDate = ( newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate );
8712
		if ( newDate ) {
8713
			newDate.setHours( 0 );
8714
			newDate.setMinutes( 0 );
8715
			newDate.setSeconds( 0 );
8716
			newDate.setMilliseconds( 0 );
8717
		}
8718
		return this._daylightSavingAdjust( newDate );
8719
	},
8720
 
8721
	/* Handle switch to/from daylight saving.
8722
	 * Hours may be non-zero on daylight saving cut-over:
8723
	 * > 12 when midnight changeover, but then cannot generate
8724
	 * midnight datetime, so jump to 1AM, otherwise reset.
8725
	 * @param  date  (Date) the date to check
8726
	 * @return  (Date) the corrected date
8727
	 */
8728
	_daylightSavingAdjust: function( date ) {
8729
		if ( !date ) {
8730
			return null;
8731
		}
8732
		date.setHours( date.getHours() > 12 ? date.getHours() + 2 : 0 );
8733
		return date;
8734
	},
8735
 
8736
	/* Set the date(s) directly. */
8737
	_setDate: function( inst, date, noChange ) {
8738
		var clear = !date,
8739
			origMonth = inst.selectedMonth,
8740
			origYear = inst.selectedYear,
8741
			newDate = this._restrictMinMax( inst, this._determineDate( inst, date, new Date() ) );
8742
 
8743
		inst.selectedDay = inst.currentDay = newDate.getDate();
8744
		inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
8745
		inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
8746
		if ( ( origMonth !== inst.selectedMonth || origYear !== inst.selectedYear ) && !noChange ) {
8747
			this._notifyChange( inst );
8748
		}
8749
		this._adjustInstDate( inst );
8750
		if ( inst.input ) {
8751
			inst.input.val( clear ? "" : this._formatDate( inst ) );
8752
		}
8753
	},
8754
 
8755
	/* Retrieve the date(s) directly. */
8756
	_getDate: function( inst ) {
8757
		var startDate = ( !inst.currentYear || ( inst.input && inst.input.val() === "" ) ? null :
8758
			this._daylightSavingAdjust( new Date(
8759
			inst.currentYear, inst.currentMonth, inst.currentDay ) ) );
8760
			return startDate;
8761
	},
8762
 
8763
	/* Attach the onxxx handlers.  These are declared statically so
8764
	 * they work with static code transformers like Caja.
8765
	 */
8766
	_attachHandlers: function( inst ) {
8767
		var stepMonths = this._get( inst, "stepMonths" ),
8768
			id = "#" + inst.id.replace( /\\\\/g, "\\" );
8769
		inst.dpDiv.find( "[data-handler]" ).map( function() {
8770
			var handler = {
8771
				prev: function() {
8772
					$.datepicker._adjustDate( id, -stepMonths, "M" );
8773
				},
8774
				next: function() {
8775
					$.datepicker._adjustDate( id, +stepMonths, "M" );
8776
				},
8777
				hide: function() {
8778
					$.datepicker._hideDatepicker();
8779
				},
8780
				today: function() {
8781
					$.datepicker._gotoToday( id );
8782
				},
8783
				selectDay: function() {
8784
					$.datepicker._selectDay( id, +this.getAttribute( "data-month" ), +this.getAttribute( "data-year" ), this );
8785
					return false;
8786
				},
8787
				selectMonth: function() {
8788
					$.datepicker._selectMonthYear( id, this, "M" );
8789
					return false;
8790
				},
8791
				selectYear: function() {
8792
					$.datepicker._selectMonthYear( id, this, "Y" );
8793
					return false;
8794
				}
8795
			};
8796
			$( this ).on( this.getAttribute( "data-event" ), handler[ this.getAttribute( "data-handler" ) ] );
8797
		} );
8798
	},
8799
 
8800
	/* Generate the HTML for the current state of the date picker. */
8801
	_generateHTML: function( inst ) {
8802
		var maxDraw, prevText, prev, nextText, next, currentText, gotoDate,
8803
			controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin,
8804
			monthNames, monthNamesShort, beforeShowDay, showOtherMonths,
8805
			selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate,
8806
			cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows,
8807
			printDate, dRow, tbody, daySettings, otherMonth, unselectable,
8808
			tempDate = new Date(),
8809
			today = this._daylightSavingAdjust(
8810
				new Date( tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate() ) ), // clear time
8811
			isRTL = this._get( inst, "isRTL" ),
8812
			showButtonPanel = this._get( inst, "showButtonPanel" ),
8813
			hideIfNoPrevNext = this._get( inst, "hideIfNoPrevNext" ),
8814
			navigationAsDateFormat = this._get( inst, "navigationAsDateFormat" ),
8815
			numMonths = this._getNumberOfMonths( inst ),
8816
			showCurrentAtPos = this._get( inst, "showCurrentAtPos" ),
8817
			stepMonths = this._get( inst, "stepMonths" ),
8818
			isMultiMonth = ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ),
8819
			currentDate = this._daylightSavingAdjust( ( !inst.currentDay ? new Date( 9999, 9, 9 ) :
8820
				new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) ),
8821
			minDate = this._getMinMaxDate( inst, "min" ),
8822
			maxDate = this._getMinMaxDate( inst, "max" ),
8823
			drawMonth = inst.drawMonth - showCurrentAtPos,
8824
			drawYear = inst.drawYear;
8825
 
8826
		if ( drawMonth < 0 ) {
8827
			drawMonth += 12;
8828
			drawYear--;
8829
		}
8830
		if ( maxDate ) {
8831
			maxDraw = this._daylightSavingAdjust( new Date( maxDate.getFullYear(),
8832
				maxDate.getMonth() - ( numMonths[ 0 ] * numMonths[ 1 ] ) + 1, maxDate.getDate() ) );
8833
			maxDraw = ( minDate && maxDraw < minDate ? minDate : maxDraw );
8834
			while ( this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 ) ) > maxDraw ) {
8835
				drawMonth--;
8836
				if ( drawMonth < 0 ) {
8837
					drawMonth = 11;
8838
					drawYear--;
8839
				}
8840
			}
8841
		}
8842
		inst.drawMonth = drawMonth;
8843
		inst.drawYear = drawYear;
8844
 
8845
		prevText = this._get( inst, "prevText" );
8846
		prevText = ( !navigationAsDateFormat ? prevText : this.formatDate( prevText,
8847
			this._daylightSavingAdjust( new Date( drawYear, drawMonth - stepMonths, 1 ) ),
8848
			this._getFormatConfig( inst ) ) );
8849
 
8850
		if ( this._canAdjustMonth( inst, -1, drawYear, drawMonth ) ) {
8851
			prev = $( "<a>" )
8852
				.attr( {
8853
					"class": "ui-datepicker-prev ui-corner-all",
8854
					"data-handler": "prev",
8855
					"data-event": "click",
8856
					title: prevText
8857
				} )
8858
				.append(
8859
					$( "<span>" )
8860
						.addClass( "ui-icon ui-icon-circle-triangle-" +
8861
							( isRTL ? "e" : "w" ) )
8862
						.text( prevText )
8863
				)[ 0 ].outerHTML;
8864
		} else if ( hideIfNoPrevNext ) {
8865
			prev = "";
8866
		} else {
8867
			prev = $( "<a>" )
8868
				.attr( {
8869
					"class": "ui-datepicker-prev ui-corner-all ui-state-disabled",
8870
					title: prevText
8871
				} )
8872
				.append(
8873
					$( "<span>" )
8874
						.addClass( "ui-icon ui-icon-circle-triangle-" +
8875
							( isRTL ? "e" : "w" ) )
8876
						.text( prevText )
8877
				)[ 0 ].outerHTML;
8878
		}
8879
 
8880
		nextText = this._get( inst, "nextText" );
8881
		nextText = ( !navigationAsDateFormat ? nextText : this.formatDate( nextText,
8882
			this._daylightSavingAdjust( new Date( drawYear, drawMonth + stepMonths, 1 ) ),
8883
			this._getFormatConfig( inst ) ) );
8884
 
8885
		if ( this._canAdjustMonth( inst, +1, drawYear, drawMonth ) ) {
8886
			next = $( "<a>" )
8887
				.attr( {
8888
					"class": "ui-datepicker-next ui-corner-all",
8889
					"data-handler": "next",
8890
					"data-event": "click",
8891
					title: nextText
8892
				} )
8893
				.append(
8894
					$( "<span>" )
8895
						.addClass( "ui-icon ui-icon-circle-triangle-" +
8896
							( isRTL ? "w" : "e" ) )
8897
						.text( nextText )
8898
				)[ 0 ].outerHTML;
8899
		} else if ( hideIfNoPrevNext ) {
8900
			next = "";
8901
		} else {
8902
			next = $( "<a>" )
8903
				.attr( {
8904
					"class": "ui-datepicker-next ui-corner-all ui-state-disabled",
8905
					title: nextText
8906
				} )
8907
				.append(
8908
					$( "<span>" )
8909
						.attr( "class", "ui-icon ui-icon-circle-triangle-" +
8910
							( isRTL ? "w" : "e" ) )
8911
						.text( nextText )
8912
				)[ 0 ].outerHTML;
8913
		}
8914
 
8915
		currentText = this._get( inst, "currentText" );
8916
		gotoDate = ( this._get( inst, "gotoCurrent" ) && inst.currentDay ? currentDate : today );
8917
		currentText = ( !navigationAsDateFormat ? currentText :
8918
			this.formatDate( currentText, gotoDate, this._getFormatConfig( inst ) ) );
8919
 
8920
		controls = "";
8921
		if ( !inst.inline ) {
8922
			controls = $( "<button>" )
8923
				.attr( {
8924
					type: "button",
8925
					"class": "ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all",
8926
					"data-handler": "hide",
8927
					"data-event": "click"
8928
				} )
8929
				.text( this._get( inst, "closeText" ) )[ 0 ].outerHTML;
8930
		}
8931
 
8932
		buttonPanel = "";
8933
		if ( showButtonPanel ) {
8934
			buttonPanel = $( "<div class='ui-datepicker-buttonpane ui-widget-content'>" )
8935
				.append( isRTL ? controls : "" )
8936
				.append( this._isInRange( inst, gotoDate ) ?
8937
					$( "<button>" )
8938
						.attr( {
8939
							type: "button",
8940
							"class": "ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all",
8941
							"data-handler": "today",
8942
							"data-event": "click"
8943
						} )
8944
						.text( currentText ) :
8945
					"" )
8946
				.append( isRTL ? "" : controls )[ 0 ].outerHTML;
8947
		}
8948
 
8949
		firstDay = parseInt( this._get( inst, "firstDay" ), 10 );
8950
		firstDay = ( isNaN( firstDay ) ? 0 : firstDay );
8951
 
8952
		showWeek = this._get( inst, "showWeek" );
8953
		dayNames = this._get( inst, "dayNames" );
8954
		dayNamesMin = this._get( inst, "dayNamesMin" );
8955
		monthNames = this._get( inst, "monthNames" );
8956
		monthNamesShort = this._get( inst, "monthNamesShort" );
8957
		beforeShowDay = this._get( inst, "beforeShowDay" );
8958
		showOtherMonths = this._get( inst, "showOtherMonths" );
8959
		selectOtherMonths = this._get( inst, "selectOtherMonths" );
8960
		defaultDate = this._getDefaultDate( inst );
8961
		html = "";
8962
 
8963
		for ( row = 0; row < numMonths[ 0 ]; row++ ) {
8964
			group = "";
8965
			this.maxRows = 4;
8966
			for ( col = 0; col < numMonths[ 1 ]; col++ ) {
8967
				selectedDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, inst.selectedDay ) );
8968
				cornerClass = " ui-corner-all";
8969
				calender = "";
8970
				if ( isMultiMonth ) {
8971
					calender += "<div class='ui-datepicker-group";
8972
					if ( numMonths[ 1 ] > 1 ) {
8973
						switch ( col ) {
8974
							case 0: calender += " ui-datepicker-group-first";
8975
								cornerClass = " ui-corner-" + ( isRTL ? "right" : "left" ); break;
8976
							case numMonths[ 1 ] - 1: calender += " ui-datepicker-group-last";
8977
								cornerClass = " ui-corner-" + ( isRTL ? "left" : "right" ); break;
8978
							default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break;
8979
						}
8980
					}
8981
					calender += "'>";
8982
				}
8983
				calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" +
8984
					( /all|left/.test( cornerClass ) && row === 0 ? ( isRTL ? next : prev ) : "" ) +
8985
					( /all|right/.test( cornerClass ) && row === 0 ? ( isRTL ? prev : next ) : "" ) +
8986
					this._generateMonthYearHeader( inst, drawMonth, drawYear, minDate, maxDate,
8987
					row > 0 || col > 0, monthNames, monthNamesShort ) + // draw month headers
8988
					"</div><table class='ui-datepicker-calendar'><thead>" +
8989
					"<tr>";
8990
				thead = ( showWeek ? "<th class='ui-datepicker-week-col'>" + this._get( inst, "weekHeader" ) + "</th>" : "" );
8991
				for ( dow = 0; dow < 7; dow++ ) { // days of the week
8992
					day = ( dow + firstDay ) % 7;
8993
					thead += "<th scope='col'" + ( ( dow + firstDay + 6 ) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "" ) + ">" +
8994
						"<span title='" + dayNames[ day ] + "'>" + dayNamesMin[ day ] + "</span></th>";
8995
				}
8996
				calender += thead + "</tr></thead><tbody>";
8997
				daysInMonth = this._getDaysInMonth( drawYear, drawMonth );
8998
				if ( drawYear === inst.selectedYear && drawMonth === inst.selectedMonth ) {
8999
					inst.selectedDay = Math.min( inst.selectedDay, daysInMonth );
9000
				}
9001
				leadDays = ( this._getFirstDayOfMonth( drawYear, drawMonth ) - firstDay + 7 ) % 7;
9002
				curRows = Math.ceil( ( leadDays + daysInMonth ) / 7 ); // calculate the number of rows to generate
9003
				numRows = ( isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows ); //If multiple months, use the higher number of rows (see #7043)
9004
				this.maxRows = numRows;
9005
				printDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 - leadDays ) );
9006
				for ( dRow = 0; dRow < numRows; dRow++ ) { // create date picker rows
9007
					calender += "<tr>";
9008
					tbody = ( !showWeek ? "" : "<td class='ui-datepicker-week-col'>" +
9009
						this._get( inst, "calculateWeek" )( printDate ) + "</td>" );
9010
					for ( dow = 0; dow < 7; dow++ ) { // create date picker days
9011
						daySettings = ( beforeShowDay ?
9012
							beforeShowDay.apply( ( inst.input ? inst.input[ 0 ] : null ), [ printDate ] ) : [ true, "" ] );
9013
						otherMonth = ( printDate.getMonth() !== drawMonth );
9014
						unselectable = ( otherMonth && !selectOtherMonths ) || !daySettings[ 0 ] ||
9015
							( minDate && printDate < minDate ) || ( maxDate && printDate > maxDate );
9016
						tbody += "<td class='" +
9017
							( ( dow + firstDay + 6 ) % 7 >= 5 ? " ui-datepicker-week-end" : "" ) + // highlight weekends
9018
							( otherMonth ? " ui-datepicker-other-month" : "" ) + // highlight days from other months
9019
							( ( printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent ) || // user pressed key
9020
							( defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime() ) ?
9021
 
9022
							// or defaultDate is current printedDate and defaultDate is selectedDate
9023
							" " + this._dayOverClass : "" ) + // highlight selected day
9024
							( unselectable ? " " + this._unselectableClass + " ui-state-disabled" : "" ) +  // highlight unselectable days
9025
							( otherMonth && !showOtherMonths ? "" : " " + daySettings[ 1 ] + // highlight custom dates
9026
							( printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "" ) + // highlight selected day
9027
							( printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "" ) ) + "'" + // highlight today (if different)
9028
							( ( !otherMonth || showOtherMonths ) && daySettings[ 2 ] ? " title='" + daySettings[ 2 ].replace( /'/g, "&#39;" ) + "'" : "" ) + // cell title
9029
							( unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'" ) + ">" + // actions
9030
							( otherMonth && !showOtherMonths ? "&#xa0;" : // display for other months
9031
							( unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" +
9032
							( printDate.getTime() === today.getTime() ? " ui-state-highlight" : "" ) +
9033
							( printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "" ) + // highlight selected day
9034
							( otherMonth ? " ui-priority-secondary" : "" ) + // distinguish dates from other months
9035
							"' href='#' aria-current='" + ( printDate.getTime() === currentDate.getTime() ? "true" : "false" ) + // mark date as selected for screen reader
9036
							"' data-date='" + printDate.getDate() + // store date as data
9037
							"'>" + printDate.getDate() + "</a>" ) ) + "</td>"; // display selectable date
9038
						printDate.setDate( printDate.getDate() + 1 );
9039
						printDate = this._daylightSavingAdjust( printDate );
9040
					}
9041
					calender += tbody + "</tr>";
9042
				}
9043
				drawMonth++;
9044
				if ( drawMonth > 11 ) {
9045
					drawMonth = 0;
9046
					drawYear++;
9047
				}
9048
				calender += "</tbody></table>" + ( isMultiMonth ? "</div>" +
9049
							( ( numMonths[ 0 ] > 0 && col === numMonths[ 1 ] - 1 ) ? "<div class='ui-datepicker-row-break'></div>" : "" ) : "" );
9050
				group += calender;
9051
			}
9052
			html += group;
9053
		}
9054
		html += buttonPanel;
9055
		inst._keyEvent = false;
9056
		return html;
9057
	},
9058
 
9059
	/* Generate the month and year header. */
9060
	_generateMonthYearHeader: function( inst, drawMonth, drawYear, minDate, maxDate,
9061
			secondary, monthNames, monthNamesShort ) {
9062
 
9063
		var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear,
9064
			changeMonth = this._get( inst, "changeMonth" ),
9065
			changeYear = this._get( inst, "changeYear" ),
9066
			showMonthAfterYear = this._get( inst, "showMonthAfterYear" ),
9067
			selectMonthLabel = this._get( inst, "selectMonthLabel" ),
9068
			selectYearLabel = this._get( inst, "selectYearLabel" ),
9069
			html = "<div class='ui-datepicker-title'>",
9070
			monthHtml = "";
9071
 
9072
		// Month selection
9073
		if ( secondary || !changeMonth ) {
9074
			monthHtml += "<span class='ui-datepicker-month'>" + monthNames[ drawMonth ] + "</span>";
9075
		} else {
9076
			inMinYear = ( minDate && minDate.getFullYear() === drawYear );
9077
			inMaxYear = ( maxDate && maxDate.getFullYear() === drawYear );
9078
			monthHtml += "<select class='ui-datepicker-month' aria-label='" + selectMonthLabel + "' data-handler='selectMonth' data-event='change'>";
9079
			for ( month = 0; month < 12; month++ ) {
9080
				if ( ( !inMinYear || month >= minDate.getMonth() ) && ( !inMaxYear || month <= maxDate.getMonth() ) ) {
9081
					monthHtml += "<option value='" + month + "'" +
9082
						( month === drawMonth ? " selected='selected'" : "" ) +
9083
						">" + monthNamesShort[ month ] + "</option>";
9084
				}
9085
			}
9086
			monthHtml += "</select>";
9087
		}
9088
 
9089
		if ( !showMonthAfterYear ) {
9090
			html += monthHtml + ( secondary || !( changeMonth && changeYear ) ? "&#xa0;" : "" );
9091
		}
9092
 
9093
		// Year selection
9094
		if ( !inst.yearshtml ) {
9095
			inst.yearshtml = "";
9096
			if ( secondary || !changeYear ) {
9097
				html += "<span class='ui-datepicker-year'>" + drawYear + "</span>";
9098
			} else {
9099
 
9100
				// determine range of years to display
9101
				years = this._get( inst, "yearRange" ).split( ":" );
9102
				thisYear = new Date().getFullYear();
9103
				determineYear = function( value ) {
9104
					var year = ( value.match( /c[+\-].*/ ) ? drawYear + parseInt( value.substring( 1 ), 10 ) :
9105
						( value.match( /[+\-].*/ ) ? thisYear + parseInt( value, 10 ) :
9106
						parseInt( value, 10 ) ) );
9107
					return ( isNaN( year ) ? thisYear : year );
9108
				};
9109
				year = determineYear( years[ 0 ] );
9110
				endYear = Math.max( year, determineYear( years[ 1 ] || "" ) );
9111
				year = ( minDate ? Math.max( year, minDate.getFullYear() ) : year );
9112
				endYear = ( maxDate ? Math.min( endYear, maxDate.getFullYear() ) : endYear );
9113
				inst.yearshtml += "<select class='ui-datepicker-year' aria-label='" + selectYearLabel + "' data-handler='selectYear' data-event='change'>";
9114
				for ( ; year <= endYear; year++ ) {
9115
					inst.yearshtml += "<option value='" + year + "'" +
9116
						( year === drawYear ? " selected='selected'" : "" ) +
9117
						">" + year + "</option>";
9118
				}
9119
				inst.yearshtml += "</select>";
9120
 
9121
				html += inst.yearshtml;
9122
				inst.yearshtml = null;
9123
			}
9124
		}
9125
 
9126
		html += this._get( inst, "yearSuffix" );
9127
		if ( showMonthAfterYear ) {
9128
			html += ( secondary || !( changeMonth && changeYear ) ? "&#xa0;" : "" ) + monthHtml;
9129
		}
9130
		html += "</div>"; // Close datepicker_header
9131
		return html;
9132
	},
9133
 
9134
	/* Adjust one of the date sub-fields. */
9135
	_adjustInstDate: function( inst, offset, period ) {
9136
		var year = inst.selectedYear + ( period === "Y" ? offset : 0 ),
9137
			month = inst.selectedMonth + ( period === "M" ? offset : 0 ),
9138
			day = Math.min( inst.selectedDay, this._getDaysInMonth( year, month ) ) + ( period === "D" ? offset : 0 ),
9139
			date = this._restrictMinMax( inst, this._daylightSavingAdjust( new Date( year, month, day ) ) );
9140
 
9141
		inst.selectedDay = date.getDate();
9142
		inst.drawMonth = inst.selectedMonth = date.getMonth();
9143
		inst.drawYear = inst.selectedYear = date.getFullYear();
9144
		if ( period === "M" || period === "Y" ) {
9145
			this._notifyChange( inst );
9146
		}
9147
	},
9148
 
9149
	/* Ensure a date is within any min/max bounds. */
9150
	_restrictMinMax: function( inst, date ) {
9151
		var minDate = this._getMinMaxDate( inst, "min" ),
9152
			maxDate = this._getMinMaxDate( inst, "max" ),
9153
			newDate = ( minDate && date < minDate ? minDate : date );
9154
		return ( maxDate && newDate > maxDate ? maxDate : newDate );
9155
	},
9156
 
9157
	/* Notify change of month/year. */
9158
	_notifyChange: function( inst ) {
9159
		var onChange = this._get( inst, "onChangeMonthYear" );
9160
		if ( onChange ) {
9161
			onChange.apply( ( inst.input ? inst.input[ 0 ] : null ),
9162
				[ inst.selectedYear, inst.selectedMonth + 1, inst ] );
9163
		}
9164
	},
9165
 
9166
	/* Determine the number of months to show. */
9167
	_getNumberOfMonths: function( inst ) {
9168
		var numMonths = this._get( inst, "numberOfMonths" );
9169
		return ( numMonths == null ? [ 1, 1 ] : ( typeof numMonths === "number" ? [ 1, numMonths ] : numMonths ) );
9170
	},
9171
 
9172
	/* Determine the current maximum date - ensure no time components are set. */
9173
	_getMinMaxDate: function( inst, minMax ) {
9174
		return this._determineDate( inst, this._get( inst, minMax + "Date" ), null );
9175
	},
9176
 
9177
	/* Find the number of days in a given month. */
9178
	_getDaysInMonth: function( year, month ) {
9179
		return 32 - this._daylightSavingAdjust( new Date( year, month, 32 ) ).getDate();
9180
	},
9181
 
9182
	/* Find the day of the week of the first of a month. */
9183
	_getFirstDayOfMonth: function( year, month ) {
9184
		return new Date( year, month, 1 ).getDay();
9185
	},
9186
 
9187
	/* Determines if we should allow a "next/prev" month display change. */
9188
	_canAdjustMonth: function( inst, offset, curYear, curMonth ) {
9189
		var numMonths = this._getNumberOfMonths( inst ),
9190
			date = this._daylightSavingAdjust( new Date( curYear,
9191
			curMonth + ( offset < 0 ? offset : numMonths[ 0 ] * numMonths[ 1 ] ), 1 ) );
9192
 
9193
		if ( offset < 0 ) {
9194
			date.setDate( this._getDaysInMonth( date.getFullYear(), date.getMonth() ) );
9195
		}
9196
		return this._isInRange( inst, date );
9197
	},
9198
 
9199
	/* Is the given date in the accepted range? */
9200
	_isInRange: function( inst, date ) {
9201
		var yearSplit, currentYear,
9202
			minDate = this._getMinMaxDate( inst, "min" ),
9203
			maxDate = this._getMinMaxDate( inst, "max" ),
9204
			minYear = null,
9205
			maxYear = null,
9206
			years = this._get( inst, "yearRange" );
9207
			if ( years ) {
9208
				yearSplit = years.split( ":" );
9209
				currentYear = new Date().getFullYear();
9210
				minYear = parseInt( yearSplit[ 0 ], 10 );
9211
				maxYear = parseInt( yearSplit[ 1 ], 10 );
9212
				if ( yearSplit[ 0 ].match( /[+\-].*/ ) ) {
9213
					minYear += currentYear;
9214
				}
9215
				if ( yearSplit[ 1 ].match( /[+\-].*/ ) ) {
9216
					maxYear += currentYear;
9217
				}
9218
			}
9219
 
9220
		return ( ( !minDate || date.getTime() >= minDate.getTime() ) &&
9221
			( !maxDate || date.getTime() <= maxDate.getTime() ) &&
9222
			( !minYear || date.getFullYear() >= minYear ) &&
9223
			( !maxYear || date.getFullYear() <= maxYear ) );
9224
	},
9225
 
9226
	/* Provide the configuration settings for formatting/parsing. */
9227
	_getFormatConfig: function( inst ) {
9228
		var shortYearCutoff = this._get( inst, "shortYearCutoff" );
9229
		shortYearCutoff = ( typeof shortYearCutoff !== "string" ? shortYearCutoff :
9230
			new Date().getFullYear() % 100 + parseInt( shortYearCutoff, 10 ) );
9231
		return { shortYearCutoff: shortYearCutoff,
9232
			dayNamesShort: this._get( inst, "dayNamesShort" ), dayNames: this._get( inst, "dayNames" ),
9233
			monthNamesShort: this._get( inst, "monthNamesShort" ), monthNames: this._get( inst, "monthNames" ) };
9234
	},
9235
 
9236
	/* Format the given date for display. */
9237
	_formatDate: function( inst, day, month, year ) {
9238
		if ( !day ) {
9239
			inst.currentDay = inst.selectedDay;
9240
			inst.currentMonth = inst.selectedMonth;
9241
			inst.currentYear = inst.selectedYear;
9242
		}
9243
		var date = ( day ? ( typeof day === "object" ? day :
9244
			this._daylightSavingAdjust( new Date( year, month, day ) ) ) :
9245
			this._daylightSavingAdjust( new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) );
9246
		return this.formatDate( this._get( inst, "dateFormat" ), date, this._getFormatConfig( inst ) );
9247
	}
9248
} );
9249
 
9250
/*
9251
 * Bind hover events for datepicker elements.
9252
 * Done via delegate so the binding only occurs once in the lifetime of the parent div.
9253
 * Global datepicker_instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
9254
 */
9255
function datepicker_bindHover( dpDiv ) {
9256
	var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";
9257
	return dpDiv.on( "mouseout", selector, function() {
9258
			$( this ).removeClass( "ui-state-hover" );
9259
			if ( this.className.indexOf( "ui-datepicker-prev" ) !== -1 ) {
9260
				$( this ).removeClass( "ui-datepicker-prev-hover" );
9261
			}
9262
			if ( this.className.indexOf( "ui-datepicker-next" ) !== -1 ) {
9263
				$( this ).removeClass( "ui-datepicker-next-hover" );
9264
			}
9265
		} )
9266
		.on( "mouseover", selector, datepicker_handleMouseover );
9267
}
9268
 
9269
function datepicker_handleMouseover() {
9270
	if ( !$.datepicker._isDisabledDatepicker( datepicker_instActive.inline ? datepicker_instActive.dpDiv.parent()[ 0 ] : datepicker_instActive.input[ 0 ] ) ) {
9271
		$( this ).parents( ".ui-datepicker-calendar" ).find( "a" ).removeClass( "ui-state-hover" );
9272
		$( this ).addClass( "ui-state-hover" );
9273
		if ( this.className.indexOf( "ui-datepicker-prev" ) !== -1 ) {
9274
			$( this ).addClass( "ui-datepicker-prev-hover" );
9275
		}
9276
		if ( this.className.indexOf( "ui-datepicker-next" ) !== -1 ) {
9277
			$( this ).addClass( "ui-datepicker-next-hover" );
9278
		}
9279
	}
9280
}
9281
 
9282
/* jQuery extend now ignores nulls! */
9283
function datepicker_extendRemove( target, props ) {
9284
	$.extend( target, props );
9285
	for ( var name in props ) {
9286
		if ( props[ name ] == null ) {
9287
			target[ name ] = props[ name ];
9288
		}
9289
	}
9290
	return target;
9291
}
9292
 
9293
/* Invoke the datepicker functionality.
9294
   @param  options  string - a command, optionally followed by additional parameters or
9295
					Object - settings for attaching new datepicker functionality
9296
   @return  jQuery object */
9297
$.fn.datepicker = function( options ) {
9298
 
9299
	/* Verify an empty collection wasn't passed - Fixes #6976 */
9300
	if ( !this.length ) {
9301
		return this;
9302
	}
9303
 
9304
	/* Initialise the date picker. */
9305
	if ( !$.datepicker.initialized ) {
9306
		$( document ).on( "mousedown", $.datepicker._checkExternalClick );
9307
		$.datepicker.initialized = true;
9308
	}
9309
 
9310
	/* Append datepicker main container to body if not exist. */
9311
	if ( $( "#" + $.datepicker._mainDivId ).length === 0 ) {
9312
		$( "body" ).append( $.datepicker.dpDiv );
9313
	}
9314
 
9315
	var otherArgs = Array.prototype.slice.call( arguments, 1 );
9316
	if ( typeof options === "string" && ( options === "isDisabled" || options === "getDate" || options === "widget" ) ) {
9317
		return $.datepicker[ "_" + options + "Datepicker" ].
9318
			apply( $.datepicker, [ this[ 0 ] ].concat( otherArgs ) );
9319
	}
9320
	if ( options === "option" && arguments.length === 2 && typeof arguments[ 1 ] === "string" ) {
9321
		return $.datepicker[ "_" + options + "Datepicker" ].
9322
			apply( $.datepicker, [ this[ 0 ] ].concat( otherArgs ) );
9323
	}
9324
	return this.each( function() {
9325
		if ( typeof options === "string" ) {
9326
			$.datepicker[ "_" + options + "Datepicker" ]
9327
				.apply( $.datepicker, [ this ].concat( otherArgs ) );
9328
		} else {
9329
			$.datepicker._attachDatepicker( this, options );
9330
		}
9331
	} );
9332
};
9333
 
9334
$.datepicker = new Datepicker(); // singleton instance
9335
$.datepicker.initialized = false;
9336
$.datepicker.uuid = new Date().getTime();
9337
$.datepicker.version = "1.14.1";
9338
 
9339
var widgetsDatepicker = $.datepicker;
9340
 
9341
 
9342
/*!
9343
 * jQuery UI Mouse 1.14.1
9344
 * https://jqueryui.com
9345
 *
9346
 * Copyright OpenJS Foundation and other contributors
9347
 * Released under the MIT license.
9348
 * https://jquery.org/license
9349
 */
9350
 
9351
//>>label: Mouse
9352
//>>group: Widgets
9353
//>>description: Abstracts mouse-based interactions to assist in creating certain widgets.
9354
//>>docs: https://api.jqueryui.com/mouse/
9355
 
9356
 
9357
var mouseHandled = false;
9358
$( document ).on( "mouseup", function() {
9359
	mouseHandled = false;
9360
} );
9361
 
9362
var widgetsMouse = $.widget( "ui.mouse", {
9363
	version: "1.14.1",
9364
	options: {
9365
		cancel: "input, textarea, button, select, option",
9366
		distance: 1,
9367
		delay: 0
9368
	},
9369
	_mouseInit: function() {
9370
		var that = this;
9371
 
9372
		this.element
9373
			.on( "mousedown." + this.widgetName, function( event ) {
9374
				return that._mouseDown( event );
9375
			} )
9376
			.on( "click." + this.widgetName, function( event ) {
9377
				if ( true === $.data( event.target, that.widgetName + ".preventClickEvent" ) ) {
9378
					$.removeData( event.target, that.widgetName + ".preventClickEvent" );
9379
					event.stopImmediatePropagation();
9380
					return false;
9381
				}
9382
			} );
9383
 
9384
		this.started = false;
9385
	},
9386
 
9387
	// TODO: make sure destroying one instance of mouse doesn't mess with
9388
	// other instances of mouse
9389
	_mouseDestroy: function() {
9390
		this.element.off( "." + this.widgetName );
9391
		if ( this._mouseMoveDelegate ) {
9392
			this.document
9393
				.off( "mousemove." + this.widgetName, this._mouseMoveDelegate )
9394
				.off( "mouseup." + this.widgetName, this._mouseUpDelegate );
9395
		}
9396
	},
9397
 
9398
	_mouseDown: function( event ) {
9399
 
9400
		// don't let more than one widget handle mouseStart
9401
		if ( mouseHandled ) {
9402
			return;
9403
		}
9404
 
9405
		this._mouseMoved = false;
9406
 
9407
		// We may have missed mouseup (out of window)
9408
		if ( this._mouseStarted ) {
9409
			this._mouseUp( event );
9410
		}
9411
 
9412
		this._mouseDownEvent = event;
9413
 
9414
		var that = this,
9415
			btnIsLeft = event.which === 1,
9416
			elIsCancel = typeof this.options.cancel === "string" ?
9417
				$( event.target ).closest( this.options.cancel ).length :
9418
				false;
9419
		if ( !btnIsLeft || elIsCancel || !this._mouseCapture( event ) ) {
9420
			return true;
9421
		}
9422
 
9423
		this.mouseDelayMet = !this.options.delay;
9424
		if ( !this.mouseDelayMet ) {
9425
			this._mouseDelayTimer = setTimeout( function() {
9426
				that.mouseDelayMet = true;
9427
			}, this.options.delay );
9428
		}
9429
 
9430
		if ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) {
9431
			this._mouseStarted = ( this._mouseStart( event ) !== false );
9432
			if ( !this._mouseStarted ) {
9433
				event.preventDefault();
9434
				return true;
9435
			}
9436
		}
9437
 
9438
		// Click event may never have fired (Gecko & Opera)
9439
		if ( true === $.data( event.target, this.widgetName + ".preventClickEvent" ) ) {
9440
			$.removeData( event.target, this.widgetName + ".preventClickEvent" );
9441
		}
9442
 
9443
		// These delegates are required to keep context
9444
		this._mouseMoveDelegate = function( event ) {
9445
			return that._mouseMove( event );
9446
		};
9447
		this._mouseUpDelegate = function( event ) {
9448
			return that._mouseUp( event );
9449
		};
9450
 
9451
		this.document
9452
			.on( "mousemove." + this.widgetName, this._mouseMoveDelegate )
9453
			.on( "mouseup." + this.widgetName, this._mouseUpDelegate );
9454
 
9455
		event.preventDefault();
9456
 
9457
		mouseHandled = true;
9458
		return true;
9459
	},
9460
 
9461
	_mouseMove: function( event ) {
9462
 
9463
		// Only check for mouseups outside the document if you've moved inside the document
9464
		// at least once.
9465
		if ( this._mouseMoved && !event.which ) {
9466
 
9467
			// Support: Safari <=8 - 9
9468
			// Safari sets which to 0 if you press any of the following keys
9469
			// during a drag (#14461)
9470
			if ( event.originalEvent.altKey || event.originalEvent.ctrlKey ||
9471
					event.originalEvent.metaKey || event.originalEvent.shiftKey ) {
9472
				this.ignoreMissingWhich = true;
9473
			} else if ( !this.ignoreMissingWhich ) {
9474
				return this._mouseUp( event );
9475
			}
9476
		}
9477
 
9478
		if ( event.which || event.button ) {
9479
			this._mouseMoved = true;
9480
		}
9481
 
9482
		if ( this._mouseStarted ) {
9483
			this._mouseDrag( event );
9484
			return event.preventDefault();
9485
		}
9486
 
9487
		if ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) {
9488
			this._mouseStarted =
9489
				( this._mouseStart( this._mouseDownEvent, event ) !== false );
9490
			if ( this._mouseStarted ) {
9491
				this._mouseDrag( event );
9492
			} else {
9493
				this._mouseUp( event );
9494
			}
9495
		}
9496
 
9497
		return !this._mouseStarted;
9498
	},
9499
 
9500
	_mouseUp: function( event ) {
9501
		this.document
9502
			.off( "mousemove." + this.widgetName, this._mouseMoveDelegate )
9503
			.off( "mouseup." + this.widgetName, this._mouseUpDelegate );
9504
 
9505
		if ( this._mouseStarted ) {
9506
			this._mouseStarted = false;
9507
 
9508
			if ( event.target === this._mouseDownEvent.target ) {
9509
				$.data( event.target, this.widgetName + ".preventClickEvent", true );
9510
			}
9511
 
9512
			this._mouseStop( event );
9513
		}
9514
 
9515
		if ( this._mouseDelayTimer ) {
9516
			clearTimeout( this._mouseDelayTimer );
9517
			delete this._mouseDelayTimer;
9518
		}
9519
 
9520
		this.ignoreMissingWhich = false;
9521
		mouseHandled = false;
9522
		event.preventDefault();
9523
	},
9524
 
9525
	_mouseDistanceMet: function( event ) {
9526
		return ( Math.max(
9527
				Math.abs( this._mouseDownEvent.pageX - event.pageX ),
9528
				Math.abs( this._mouseDownEvent.pageY - event.pageY )
9529
			) >= this.options.distance
9530
		);
9531
	},
9532
 
9533
	_mouseDelayMet: function( /* event */ ) {
9534
		return this.mouseDelayMet;
9535
	},
9536
 
9537
	// These are placeholder methods, to be overriden by extending plugin
9538
	_mouseStart: function( /* event */ ) {},
9539
	_mouseDrag: function( /* event */ ) {},
9540
	_mouseStop: function( /* event */ ) {},
9541
	_mouseCapture: function( /* event */ ) {
9542
		return true;
9543
	}
9544
} );
9545
 
9546
 
9547
 
9548
// $.ui.plugin is deprecated. Use $.widget() extensions instead.
9549
var plugin = $.ui.plugin = {
9550
	add: function( module, option, set ) {
9551
		var i,
9552
			proto = $.ui[ module ].prototype;
9553
		for ( i in set ) {
9554
			proto.plugins[ i ] = proto.plugins[ i ] || [];
9555
			proto.plugins[ i ].push( [ option, set[ i ] ] );
9556
		}
9557
	},
9558
	call: function( instance, name, args, allowDisconnected ) {
9559
		var i,
9560
			set = instance.plugins[ name ];
9561
 
9562
		if ( !set ) {
9563
			return;
9564
		}
9565
 
9566
		if ( !allowDisconnected && ( !instance.element[ 0 ].parentNode ||
9567
				instance.element[ 0 ].parentNode.nodeType === 11 ) ) {
9568
			return;
9569
		}
9570
 
9571
		for ( i = 0; i < set.length; i++ ) {
9572
			if ( instance.options[ set[ i ][ 0 ] ] ) {
9573
				set[ i ][ 1 ].apply( instance.element, args );
9574
			}
9575
		}
9576
	}
9577
};
9578
 
9579
 
9580
/*!
9581
 * jQuery UI Draggable 1.14.1
9582
 * https://jqueryui.com
9583
 *
9584
 * Copyright OpenJS Foundation and other contributors
9585
 * Released under the MIT license.
9586
 * https://jquery.org/license
9587
 */
9588
 
9589
//>>label: Draggable
9590
//>>group: Interactions
9591
//>>description: Enables dragging functionality for any element.
9592
//>>docs: https://api.jqueryui.com/draggable/
9593
//>>demos: https://jqueryui.com/draggable/
9594
//>>css.structure: ../../themes/base/draggable.css
9595
 
9596
 
9597
$.widget( "ui.draggable", $.ui.mouse, {
9598
	version: "1.14.1",
9599
	widgetEventPrefix: "drag",
9600
	options: {
9601
		addClasses: true,
9602
		appendTo: "parent",
9603
		axis: false,
9604
		connectToSortable: false,
9605
		containment: false,
9606
		cursor: "auto",
9607
		cursorAt: false,
9608
		grid: false,
9609
		handle: false,
9610
		helper: "original",
9611
		iframeFix: false,
9612
		opacity: false,
9613
		refreshPositions: false,
9614
		revert: false,
9615
		revertDuration: 500,
9616
		scope: "default",
9617
		scroll: true,
9618
		scrollSensitivity: 20,
9619
		scrollSpeed: 20,
9620
		snap: false,
9621
		snapMode: "both",
9622
		snapTolerance: 20,
9623
		stack: false,
9624
		zIndex: false,
9625
 
9626
		// Callbacks
9627
		drag: null,
9628
		start: null,
9629
		stop: null
9630
	},
9631
	_create: function() {
9632
 
9633
		if ( this.options.helper === "original" ) {
9634
			this._setPositionRelative();
9635
		}
9636
		if ( this.options.addClasses ) {
9637
			this._addClass( "ui-draggable" );
9638
		}
9639
		this._setHandleClassName();
9640
 
9641
		this._mouseInit();
9642
	},
9643
 
9644
	_setOption: function( key, value ) {
9645
		this._super( key, value );
9646
		if ( key === "handle" ) {
9647
			this._removeHandleClassName();
9648
			this._setHandleClassName();
9649
		}
9650
	},
9651
 
9652
	_destroy: function() {
9653
		if ( ( this.helper || this.element ).is( ".ui-draggable-dragging" ) ) {
9654
			this.destroyOnClear = true;
9655
			return;
9656
		}
9657
		this._removeHandleClassName();
9658
		this._mouseDestroy();
9659
	},
9660
 
9661
	_mouseCapture: function( event ) {
9662
		var o = this.options;
9663
 
9664
		// Among others, prevent a drag on a resizable-handle
9665
		if ( this.helper || o.disabled ||
9666
				$( event.target ).closest( ".ui-resizable-handle" ).length > 0 ) {
9667
			return false;
9668
		}
9669
 
9670
		//Quit if we're not on a valid handle
9671
		this.handle = this._getHandle( event );
9672
		if ( !this.handle ) {
9673
			return false;
9674
		}
9675
 
9676
		this._blurActiveElement( event );
9677
 
9678
		this._blockFrames( o.iframeFix === true ? "iframe" : o.iframeFix );
9679
 
9680
		return true;
9681
 
9682
	},
9683
 
9684
	_blockFrames: function( selector ) {
9685
		this.iframeBlocks = this.document.find( selector ).map( function() {
9686
			var iframe = $( this );
9687
 
9688
			return $( "<div>" )
9689
				.css( "position", "absolute" )
9690
				.appendTo( iframe.parent() )
9691
				.outerWidth( iframe.outerWidth() )
9692
				.outerHeight( iframe.outerHeight() )
9693
				.offset( iframe.offset() )[ 0 ];
9694
		} );
9695
	},
9696
 
9697
	_unblockFrames: function() {
9698
		if ( this.iframeBlocks ) {
9699
			this.iframeBlocks.remove();
9700
			delete this.iframeBlocks;
9701
		}
9702
	},
9703
 
9704
	_blurActiveElement: function( event ) {
9705
		var activeElement = this.document[ 0 ].activeElement,
9706
			target = $( event.target );
9707
 
9708
		// Don't blur if the event occurred on an element that is within
9709
		// the currently focused element
9710
		// See #10527, #12472
9711
		if ( target.closest( activeElement ).length ) {
9712
			return;
9713
		}
9714
 
9715
		// Blur any element that currently has focus, see #4261
9716
		$( activeElement ).trigger( "blur" );
9717
	},
9718
 
9719
	_mouseStart: function( event ) {
9720
 
9721
		var o = this.options;
9722
 
9723
		//Create and append the visible helper
9724
		this.helper = this._createHelper( event );
9725
 
9726
		this._addClass( this.helper, "ui-draggable-dragging" );
9727
 
9728
		//Cache the helper size
9729
		this._cacheHelperProportions();
9730
 
9731
		//If ddmanager is used for droppables, set the global draggable
9732
		if ( $.ui.ddmanager ) {
9733
			$.ui.ddmanager.current = this;
9734
		}
9735
 
9736
		/*
9737
		 * - Position generation -
9738
		 * This block generates everything position related - it's the core of draggables.
9739
		 */
9740
 
9741
		//Cache the margins of the original element
9742
		this._cacheMargins();
9743
 
9744
		//Store the helper's css position
9745
		this.cssPosition = this.helper.css( "position" );
9746
		this.scrollParent = this.helper.scrollParent( true );
9747
		this.offsetParent = this.helper.offsetParent();
9748
		this.hasFixedAncestor = this.helper.parents().filter( function() {
9749
				return $( this ).css( "position" ) === "fixed";
9750
			} ).length > 0;
9751
 
9752
		//The element's absolute position on the page minus margins
9753
		this.positionAbs = this.element.offset();
9754
		this._refreshOffsets( event );
9755
 
9756
		//Generate the original position
9757
		this.originalPosition = this.position = this._generatePosition( event, false );
9758
		this.originalPageX = event.pageX;
9759
		this.originalPageY = event.pageY;
9760
 
9761
		//Adjust the mouse offset relative to the helper if "cursorAt" is supplied
9762
		if ( o.cursorAt ) {
9763
			this._adjustOffsetFromHelper( o.cursorAt );
9764
		}
9765
 
9766
		//Set a containment if given in the options
9767
		this._setContainment();
9768
 
9769
		//Trigger event + callbacks
9770
		if ( this._trigger( "start", event ) === false ) {
9771
			this._clear();
9772
			return false;
9773
		}
9774
 
9775
		//Recache the helper size
9776
		this._cacheHelperProportions();
9777
 
9778
		//Prepare the droppable offsets
9779
		if ( $.ui.ddmanager && !o.dropBehaviour ) {
9780
			$.ui.ddmanager.prepareOffsets( this, event );
9781
		}
9782
 
9783
		// Execute the drag once - this causes the helper not to be visible before getting its
9784
		// correct position
9785
		this._mouseDrag( event, true );
9786
 
9787
		// If the ddmanager is used for droppables, inform the manager that dragging has started
9788
		// (see #5003)
9789
		if ( $.ui.ddmanager ) {
9790
			$.ui.ddmanager.dragStart( this, event );
9791
		}
9792
 
9793
		return true;
9794
	},
9795
 
9796
	_refreshOffsets: function( event ) {
9797
		this.offset = {
9798
			top: this.positionAbs.top - this.margins.top,
9799
			left: this.positionAbs.left - this.margins.left,
9800
			scroll: false,
9801
			parent: this._getParentOffset(),
9802
			relative: this._getRelativeOffset()
9803
		};
9804
 
9805
		this.offset.click = {
9806
			left: event.pageX - this.offset.left,
9807
			top: event.pageY - this.offset.top
9808
		};
9809
	},
9810
 
9811
	_mouseDrag: function( event, noPropagation ) {
9812
 
9813
		// reset any necessary cached properties (see #5009)
9814
		if ( this.hasFixedAncestor ) {
9815
			this.offset.parent = this._getParentOffset();
9816
		}
9817
 
9818
		//Compute the helpers position
9819
		this.position = this._generatePosition( event, true );
9820
		this.positionAbs = this._convertPositionTo( "absolute" );
9821
 
9822
		//Call plugins and callbacks and use the resulting position if something is returned
9823
		if ( !noPropagation ) {
9824
			var ui = this._uiHash();
9825
			if ( this._trigger( "drag", event, ui ) === false ) {
9826
				this._mouseUp( new $.Event( "mouseup", event ) );
9827
				return false;
9828
			}
9829
			this.position = ui.position;
9830
		}
9831
 
9832
		this.helper[ 0 ].style.left = this.position.left + "px";
9833
		this.helper[ 0 ].style.top = this.position.top + "px";
9834
 
9835
		if ( $.ui.ddmanager ) {
9836
			$.ui.ddmanager.drag( this, event );
9837
		}
9838
 
9839
		return false;
9840
	},
9841
 
9842
	_mouseStop: function( event ) {
9843
 
9844
		//If we are using droppables, inform the manager about the drop
9845
		var that = this,
9846
			dropped = false;
9847
		if ( $.ui.ddmanager && !this.options.dropBehaviour ) {
9848
			dropped = $.ui.ddmanager.drop( this, event );
9849
		}
9850
 
9851
		//if a drop comes from outside (a sortable)
9852
		if ( this.dropped ) {
9853
			dropped = this.dropped;
9854
			this.dropped = false;
9855
		}
9856
 
9857
		if ( ( this.options.revert === "invalid" && !dropped ) ||
9858
				( this.options.revert === "valid" && dropped ) ||
9859
				this.options.revert === true || ( typeof this.options.revert === "function" &&
9860
				this.options.revert.call( this.element, dropped ) )
9861
		) {
9862
			$( this.helper ).animate(
9863
				this.originalPosition,
9864
				parseInt( this.options.revertDuration, 10 ),
9865
				function() {
9866
					if ( that._trigger( "stop", event ) !== false ) {
9867
						that._clear();
9868
					}
9869
				}
9870
			);
9871
		} else {
9872
			if ( this._trigger( "stop", event ) !== false ) {
9873
				this._clear();
9874
			}
9875
		}
9876
 
9877
		return false;
9878
	},
9879
 
9880
	_mouseUp: function( event ) {
9881
		this._unblockFrames();
9882
 
9883
		// If the ddmanager is used for droppables, inform the manager that dragging has stopped
9884
		// (see #5003)
9885
		if ( $.ui.ddmanager ) {
9886
			$.ui.ddmanager.dragStop( this, event );
9887
		}
9888
 
9889
		// Only need to focus if the event occurred on the draggable itself, see #10527
9890
		if ( this.handleElement.is( event.target ) ) {
9891
 
9892
			// The interaction is over; whether or not the click resulted in a drag,
9893
			// focus the element
9894
			this.element.trigger( "focus" );
9895
		}
9896
 
9897
		return $.ui.mouse.prototype._mouseUp.call( this, event );
9898
	},
9899
 
9900
	cancel: function() {
9901
 
9902
		if ( this.helper.is( ".ui-draggable-dragging" ) ) {
9903
			this._mouseUp( new $.Event( "mouseup", { target: this.element[ 0 ] } ) );
9904
		} else {
9905
			this._clear();
9906
		}
9907
 
9908
		return this;
9909
 
9910
	},
9911
 
9912
	_getHandle: function( event ) {
9913
		return this.options.handle ?
9914
			!!$( event.target ).closest( this.element.find( this.options.handle ) ).length :
9915
			true;
9916
	},
9917
 
9918
	_setHandleClassName: function() {
9919
		this.handleElement = this.options.handle ?
9920
			this.element.find( this.options.handle ) : this.element;
9921
		this._addClass( this.handleElement, "ui-draggable-handle" );
9922
	},
9923
 
9924
	_removeHandleClassName: function() {
9925
		this._removeClass( this.handleElement, "ui-draggable-handle" );
9926
	},
9927
 
9928
	_createHelper: function( event ) {
9929
 
9930
		var o = this.options,
9931
			helperIsFunction = typeof o.helper === "function",
9932
			helper = helperIsFunction ?
9933
				$( o.helper.apply( this.element[ 0 ], [ event ] ) ) :
9934
				( o.helper === "clone" ?
9935
					this.element.clone().removeAttr( "id" ) :
9936
					this.element );
9937
 
9938
		if ( !helper.parents( "body" ).length ) {
9939
			helper.appendTo( ( o.appendTo === "parent" ?
9940
				this.element[ 0 ].parentNode :
9941
				o.appendTo ) );
9942
		}
9943
 
9944
		// https://bugs.jqueryui.com/ticket/9446
9945
		// a helper function can return the original element
9946
		// which wouldn't have been set to relative in _create
9947
		if ( helperIsFunction && helper[ 0 ] === this.element[ 0 ] ) {
9948
			this._setPositionRelative();
9949
		}
9950
 
9951
		if ( helper[ 0 ] !== this.element[ 0 ] &&
9952
				!( /(fixed|absolute)/ ).test( helper.css( "position" ) ) ) {
9953
			helper.css( "position", "absolute" );
9954
		}
9955
 
9956
		return helper;
9957
 
9958
	},
9959
 
9960
	_setPositionRelative: function() {
9961
		if ( !( /^(?:r|a|f)/ ).test( this.element.css( "position" ) ) ) {
9962
			this.element[ 0 ].style.position = "relative";
9963
		}
9964
	},
9965
 
9966
	_adjustOffsetFromHelper: function( obj ) {
9967
		if ( typeof obj === "string" ) {
9968
			obj = obj.split( " " );
9969
		}
9970
		if ( Array.isArray( obj ) ) {
9971
			obj = { left: +obj[ 0 ], top: +obj[ 1 ] || 0 };
9972
		}
9973
		if ( "left" in obj ) {
9974
			this.offset.click.left = obj.left + this.margins.left;
9975
		}
9976
		if ( "right" in obj ) {
9977
			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
9978
		}
9979
		if ( "top" in obj ) {
9980
			this.offset.click.top = obj.top + this.margins.top;
9981
		}
9982
		if ( "bottom" in obj ) {
9983
			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
9984
		}
9985
	},
9986
 
9987
	_isRootNode: function( element ) {
9988
		return ( /(html|body)/i ).test( element.tagName ) || element === this.document[ 0 ];
9989
	},
9990
 
9991
	_getParentOffset: function() {
9992
 
9993
		//Get the offsetParent and cache its position
9994
		var po = this.offsetParent.offset(),
9995
			document = this.document[ 0 ];
9996
 
9997
		// This is a special case where we need to modify a offset calculated on start, since the
9998
		// following happened:
9999
		// 1. The position of the helper is absolute, so it's position is calculated based on the
10000
		// next positioned parent
10001
		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't
10002
		// the document, which means that the scroll is included in the initial calculation of the
10003
		// offset of the parent, and never recalculated upon drag
10004
		if ( this.cssPosition === "absolute" && this.scrollParent[ 0 ] !== document &&
10005
				$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) {
10006
			po.left += this.scrollParent.scrollLeft();
10007
			po.top += this.scrollParent.scrollTop();
10008
		}
10009
 
10010
		if ( this._isRootNode( this.offsetParent[ 0 ] ) ) {
10011
			po = { top: 0, left: 0 };
10012
		}
10013
 
10014
		return {
10015
			top: po.top + ( parseInt( this.offsetParent.css( "borderTopWidth" ), 10 ) || 0 ),
10016
			left: po.left + ( parseInt( this.offsetParent.css( "borderLeftWidth" ), 10 ) || 0 )
10017
		};
10018
 
10019
	},
10020
 
10021
	_getRelativeOffset: function() {
10022
		if ( this.cssPosition !== "relative" ) {
10023
			return { top: 0, left: 0 };
10024
		}
10025
 
10026
		var p = this.element.position(),
10027
			scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );
10028
 
10029
		return {
10030
			top: p.top - ( parseInt( this.helper.css( "top" ), 10 ) || 0 ) +
10031
				( !scrollIsRootNode ? this.scrollParent.scrollTop() : 0 ),
10032
			left: p.left - ( parseInt( this.helper.css( "left" ), 10 ) || 0 ) +
10033
				( !scrollIsRootNode ? this.scrollParent.scrollLeft() : 0 )
10034
		};
10035
 
10036
	},
10037
 
10038
	_cacheMargins: function() {
10039
		this.margins = {
10040
			left: ( parseInt( this.element.css( "marginLeft" ), 10 ) || 0 ),
10041
			top: ( parseInt( this.element.css( "marginTop" ), 10 ) || 0 ),
10042
			right: ( parseInt( this.element.css( "marginRight" ), 10 ) || 0 ),
10043
			bottom: ( parseInt( this.element.css( "marginBottom" ), 10 ) || 0 )
10044
		};
10045
	},
10046
 
10047
	_cacheHelperProportions: function() {
10048
		this.helperProportions = {
10049
			width: this.helper.outerWidth(),
10050
			height: this.helper.outerHeight()
10051
		};
10052
	},
10053
 
10054
	_setContainment: function() {
10055
 
10056
		var isUserScrollable, c, ce,
10057
			o = this.options,
10058
			document = this.document[ 0 ];
10059
 
10060
		this.relativeContainer = null;
10061
 
10062
		if ( !o.containment ) {
10063
			this.containment = null;
10064
			return;
10065
		}
10066
 
10067
		if ( o.containment === "window" ) {
10068
			this.containment = [
10069
				$( window ).scrollLeft() - this.offset.relative.left - this.offset.parent.left,
10070
				$( window ).scrollTop() - this.offset.relative.top - this.offset.parent.top,
10071
				$( window ).scrollLeft() + $( window ).width() -
10072
					this.helperProportions.width - this.margins.left,
10073
				$( window ).scrollTop() +
10074
					( $( window ).height() || document.body.parentNode.scrollHeight ) -
10075
					this.helperProportions.height - this.margins.top
10076
			];
10077
			return;
10078
		}
10079
 
10080
		if ( o.containment === "document" ) {
10081
			this.containment = [
10082
				0,
10083
				0,
10084
				$( document ).width() - this.helperProportions.width - this.margins.left,
10085
				( $( document ).height() || document.body.parentNode.scrollHeight ) -
10086
					this.helperProportions.height - this.margins.top
10087
			];
10088
			return;
10089
		}
10090
 
10091
		if ( o.containment.constructor === Array ) {
10092
			this.containment = o.containment;
10093
			return;
10094
		}
10095
 
10096
		if ( o.containment === "parent" ) {
10097
			o.containment = this.helper[ 0 ].parentNode;
10098
		}
10099
 
10100
		c = $( o.containment );
10101
		ce = c[ 0 ];
10102
 
10103
		if ( !ce ) {
10104
			return;
10105
		}
10106
 
10107
		isUserScrollable = /(scroll|auto)/.test( c.css( "overflow" ) );
10108
 
10109
		this.containment = [
10110
			( parseInt( c.css( "borderLeftWidth" ), 10 ) || 0 ) +
10111
				( parseInt( c.css( "paddingLeft" ), 10 ) || 0 ),
10112
			( parseInt( c.css( "borderTopWidth" ), 10 ) || 0 ) +
10113
				( parseInt( c.css( "paddingTop" ), 10 ) || 0 ),
10114
			( isUserScrollable ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) -
10115
				( parseInt( c.css( "borderRightWidth" ), 10 ) || 0 ) -
10116
				( parseInt( c.css( "paddingRight" ), 10 ) || 0 ) -
10117
				this.helperProportions.width -
10118
				this.margins.left -
10119
				this.margins.right,
10120
			( isUserScrollable ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) -
10121
				( parseInt( c.css( "borderBottomWidth" ), 10 ) || 0 ) -
10122
				( parseInt( c.css( "paddingBottom" ), 10 ) || 0 ) -
10123
				this.helperProportions.height -
10124
				this.margins.top -
10125
				this.margins.bottom
10126
		];
10127
		this.relativeContainer = c;
10128
	},
10129
 
10130
	_convertPositionTo: function( d, pos ) {
10131
 
10132
		if ( !pos ) {
10133
			pos = this.position;
10134
		}
10135
 
10136
		var mod = d === "absolute" ? 1 : -1,
10137
			scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );
10138
 
10139
		return {
10140
			top: (
10141
 
10142
				// The absolute mouse position
10143
				pos.top	+
10144
 
10145
				// Only for relative positioned nodes: Relative offset from element to offset parent
10146
				this.offset.relative.top * mod +
10147
 
10148
				// The offsetParent's offset without borders (offset + border)
10149
				this.offset.parent.top * mod -
10150
				( ( this.cssPosition === "fixed" ?
10151
					-this.offset.scroll.top :
10152
					( scrollIsRootNode ? 0 : this.offset.scroll.top ) ) * mod )
10153
			),
10154
			left: (
10155
 
10156
				// The absolute mouse position
10157
				pos.left +
10158
 
10159
				// Only for relative positioned nodes: Relative offset from element to offset parent
10160
				this.offset.relative.left * mod +
10161
 
10162
				// The offsetParent's offset without borders (offset + border)
10163
				this.offset.parent.left * mod	-
10164
				( ( this.cssPosition === "fixed" ?
10165
					-this.offset.scroll.left :
10166
					( scrollIsRootNode ? 0 : this.offset.scroll.left ) ) * mod )
10167
			)
10168
		};
10169
 
10170
	},
10171
 
10172
	_generatePosition: function( event, constrainPosition ) {
10173
 
10174
		var containment, co, top, left,
10175
			o = this.options,
10176
			scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ),
10177
			pageX = event.pageX,
10178
			pageY = event.pageY;
10179
 
10180
		// Cache the scroll
10181
		if ( !scrollIsRootNode || !this.offset.scroll ) {
10182
			this.offset.scroll = {
10183
				top: this.scrollParent.scrollTop(),
10184
				left: this.scrollParent.scrollLeft()
10185
			};
10186
		}
10187
 
10188
		/*
10189
		 * - Position constraining -
10190
		 * Constrain the position to a mix of grid, containment.
10191
		 */
10192
 
10193
		// If we are not dragging yet, we won't check for options
10194
		if ( constrainPosition ) {
10195
			if ( this.containment ) {
10196
				if ( this.relativeContainer ) {
10197
					co = this.relativeContainer.offset();
10198
					containment = [
10199
						this.containment[ 0 ] + co.left,
10200
						this.containment[ 1 ] + co.top,
10201
						this.containment[ 2 ] + co.left,
10202
						this.containment[ 3 ] + co.top
10203
					];
10204
				} else {
10205
					containment = this.containment;
10206
				}
10207
 
10208
				if ( event.pageX - this.offset.click.left < containment[ 0 ] ) {
10209
					pageX = containment[ 0 ] + this.offset.click.left;
10210
				}
10211
				if ( event.pageY - this.offset.click.top < containment[ 1 ] ) {
10212
					pageY = containment[ 1 ] + this.offset.click.top;
10213
				}
10214
				if ( event.pageX - this.offset.click.left > containment[ 2 ] ) {
10215
					pageX = containment[ 2 ] + this.offset.click.left;
10216
				}
10217
				if ( event.pageY - this.offset.click.top > containment[ 3 ] ) {
10218
					pageY = containment[ 3 ] + this.offset.click.top;
10219
				}
10220
			}
10221
 
10222
			if ( o.grid ) {
10223
 
10224
				//Check for grid elements set to 0 to prevent divide by 0 error causing invalid
10225
				// argument errors in IE (see ticket #6950)
10226
				top = o.grid[ 1 ] ? this.originalPageY + Math.round( ( pageY -
10227
					this.originalPageY ) / o.grid[ 1 ] ) * o.grid[ 1 ] : this.originalPageY;
10228
				pageY = containment ? ( ( top - this.offset.click.top >= containment[ 1 ] ||
10229
					top - this.offset.click.top > containment[ 3 ] ) ?
10230
						top :
10231
						( ( top - this.offset.click.top >= containment[ 1 ] ) ?
10232
							top - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) : top;
10233
 
10234
				left = o.grid[ 0 ] ? this.originalPageX +
10235
					Math.round( ( pageX - this.originalPageX ) / o.grid[ 0 ] ) * o.grid[ 0 ] :
10236
					this.originalPageX;
10237
				pageX = containment ? ( ( left - this.offset.click.left >= containment[ 0 ] ||
10238
					left - this.offset.click.left > containment[ 2 ] ) ?
10239
						left :
10240
						( ( left - this.offset.click.left >= containment[ 0 ] ) ?
10241
							left - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) : left;
10242
			}
10243
 
10244
			if ( o.axis === "y" ) {
10245
				pageX = this.originalPageX;
10246
			}
10247
 
10248
			if ( o.axis === "x" ) {
10249
				pageY = this.originalPageY;
10250
			}
10251
		}
10252
 
10253
		return {
10254
			top: (
10255
 
10256
				// The absolute mouse position
10257
				pageY -
10258
 
10259
				// Click offset (relative to the element)
10260
				this.offset.click.top -
10261
 
10262
				// Only for relative positioned nodes: Relative offset from element to offset parent
10263
				this.offset.relative.top -
10264
 
10265
				// The offsetParent's offset without borders (offset + border)
10266
				this.offset.parent.top +
10267
				( this.cssPosition === "fixed" ?
10268
					-this.offset.scroll.top :
10269
					( scrollIsRootNode ? 0 : this.offset.scroll.top ) )
10270
			),
10271
			left: (
10272
 
10273
				// The absolute mouse position
10274
				pageX -
10275
 
10276
				// Click offset (relative to the element)
10277
				this.offset.click.left -
10278
 
10279
				// Only for relative positioned nodes: Relative offset from element to offset parent
10280
				this.offset.relative.left -
10281
 
10282
				// The offsetParent's offset without borders (offset + border)
10283
				this.offset.parent.left +
10284
				( this.cssPosition === "fixed" ?
10285
					-this.offset.scroll.left :
10286
					( scrollIsRootNode ? 0 : this.offset.scroll.left ) )
10287
			)
10288
		};
10289
 
10290
	},
10291
 
10292
	_clear: function() {
10293
		this._removeClass( this.helper, "ui-draggable-dragging" );
10294
		if ( this.helper[ 0 ] !== this.element[ 0 ] && !this.cancelHelperRemoval ) {
10295
			this.helper.remove();
10296
		}
10297
		this.helper = null;
10298
		this.cancelHelperRemoval = false;
10299
		if ( this.destroyOnClear ) {
10300
			this.destroy();
10301
		}
10302
	},
10303
 
10304
	// From now on bulk stuff - mainly helpers
10305
 
10306
	_trigger: function( type, event, ui ) {
10307
		ui = ui || this._uiHash();
10308
		$.ui.plugin.call( this, type, [ event, ui, this ], true );
10309
 
10310
		// Absolute position and offset (see #6884 ) have to be recalculated after plugins
10311
		if ( /^(drag|start|stop)/.test( type ) ) {
10312
			this.positionAbs = this._convertPositionTo( "absolute" );
10313
			ui.offset = this.positionAbs;
10314
		}
10315
		return $.Widget.prototype._trigger.call( this, type, event, ui );
10316
	},
10317
 
10318
	plugins: {},
10319
 
10320
	_uiHash: function() {
10321
		return {
10322
			helper: this.helper,
10323
			position: this.position,
10324
			originalPosition: this.originalPosition,
10325
			offset: this.positionAbs
10326
		};
10327
	}
10328
 
10329
} );
10330
 
10331
$.ui.plugin.add( "draggable", "connectToSortable", {
10332
	start: function( event, ui, draggable ) {
10333
		var uiSortable = $.extend( {}, ui, {
10334
			item: draggable.element
10335
		} );
10336
 
10337
		draggable.sortables = [];
10338
		$( draggable.options.connectToSortable ).each( function() {
10339
			var sortable = $( this ).sortable( "instance" );
10340
 
10341
			if ( sortable && !sortable.options.disabled ) {
10342
				draggable.sortables.push( sortable );
10343
 
10344
				// RefreshPositions is called at drag start to refresh the containerCache
10345
				// which is used in drag. This ensures it's initialized and synchronized
10346
				// with any changes that might have happened on the page since initialization.
10347
				sortable.refreshPositions();
10348
				sortable._trigger( "activate", event, uiSortable );
10349
			}
10350
		} );
10351
	},
10352
	stop: function( event, ui, draggable ) {
10353
		var uiSortable = $.extend( {}, ui, {
10354
			item: draggable.element
10355
		} );
10356
 
10357
		draggable.cancelHelperRemoval = false;
10358
 
10359
		$.each( draggable.sortables, function() {
10360
			var sortable = this;
10361
 
10362
			if ( sortable.isOver ) {
10363
				sortable.isOver = 0;
10364
 
10365
				// Allow this sortable to handle removing the helper
10366
				draggable.cancelHelperRemoval = true;
10367
				sortable.cancelHelperRemoval = false;
10368
 
10369
				// Use _storedCSS To restore properties in the sortable,
10370
				// as this also handles revert (#9675) since the draggable
10371
				// may have modified them in unexpected ways (#8809)
10372
				sortable._storedCSS = {
10373
					position: sortable.placeholder.css( "position" ),
10374
					top: sortable.placeholder.css( "top" ),
10375
					left: sortable.placeholder.css( "left" )
10376
				};
10377
 
10378
				sortable._mouseStop( event );
10379
 
10380
				// Once drag has ended, the sortable should return to using
10381
				// its original helper, not the shared helper from draggable
10382
				sortable.options.helper = sortable.options._helper;
10383
			} else {
10384
 
10385
				// Prevent this Sortable from removing the helper.
10386
				// However, don't set the draggable to remove the helper
10387
				// either as another connected Sortable may yet handle the removal.
10388
				sortable.cancelHelperRemoval = true;
10389
 
10390
				sortable._trigger( "deactivate", event, uiSortable );
10391
			}
10392
		} );
10393
	},
10394
	drag: function( event, ui, draggable ) {
10395
		$.each( draggable.sortables, function() {
10396
			var innermostIntersecting = false,
10397
				sortable = this;
10398
 
10399
			// Copy over variables that sortable's _intersectsWith uses
10400
			sortable.positionAbs = draggable.positionAbs;
10401
			sortable.helperProportions = draggable.helperProportions;
10402
			sortable.offset.click = draggable.offset.click;
10403
 
10404
			if ( sortable._intersectsWith( sortable.containerCache ) ) {
10405
				innermostIntersecting = true;
10406
 
10407
				$.each( draggable.sortables, function() {
10408
 
10409
					// Copy over variables that sortable's _intersectsWith uses
10410
					this.positionAbs = draggable.positionAbs;
10411
					this.helperProportions = draggable.helperProportions;
10412
					this.offset.click = draggable.offset.click;
10413
 
10414
					if ( this !== sortable &&
10415
							this._intersectsWith( this.containerCache ) &&
10416
							$.contains( sortable.element[ 0 ], this.element[ 0 ] ) ) {
10417
						innermostIntersecting = false;
10418
					}
10419
 
10420
					return innermostIntersecting;
10421
				} );
10422
			}
10423
 
10424
			if ( innermostIntersecting ) {
10425
 
10426
				// If it intersects, we use a little isOver variable and set it once,
10427
				// so that the move-in stuff gets fired only once.
10428
				if ( !sortable.isOver ) {
10429
					sortable.isOver = 1;
10430
 
10431
					// Store draggable's parent in case we need to reappend to it later.
10432
					draggable._parent = ui.helper.parent();
10433
 
10434
					sortable.currentItem = ui.helper
10435
						.appendTo( sortable.element )
10436
						.data( "ui-sortable-item", true );
10437
 
10438
					// Store helper option to later restore it
10439
					sortable.options._helper = sortable.options.helper;
10440
 
10441
					sortable.options.helper = function() {
10442
						return ui.helper[ 0 ];
10443
					};
10444
 
10445
					// Fire the start events of the sortable with our passed browser event,
10446
					// and our own helper (so it doesn't create a new one)
10447
					event.target = sortable.currentItem[ 0 ];
10448
					sortable._mouseCapture( event, true );
10449
					sortable._mouseStart( event, true, true );
10450
 
10451
					// Because the browser event is way off the new appended portlet,
10452
					// modify necessary variables to reflect the changes
10453
					sortable.offset.click.top = draggable.offset.click.top;
10454
					sortable.offset.click.left = draggable.offset.click.left;
10455
					sortable.offset.parent.left -= draggable.offset.parent.left -
10456
						sortable.offset.parent.left;
10457
					sortable.offset.parent.top -= draggable.offset.parent.top -
10458
						sortable.offset.parent.top;
10459
 
10460
					draggable._trigger( "toSortable", event );
10461
 
10462
					// Inform draggable that the helper is in a valid drop zone,
10463
					// used solely in the revert option to handle "valid/invalid".
10464
					draggable.dropped = sortable.element;
10465
 
10466
					// Need to refreshPositions of all sortables in the case that
10467
					// adding to one sortable changes the location of the other sortables (#9675)
10468
					$.each( draggable.sortables, function() {
10469
						this.refreshPositions();
10470
					} );
10471
 
10472
					// Hack so receive/update callbacks work (mostly)
10473
					draggable.currentItem = draggable.element;
10474
					sortable.fromOutside = draggable;
10475
				}
10476
 
10477
				if ( sortable.currentItem ) {
10478
					sortable._mouseDrag( event );
10479
 
10480
					// Copy the sortable's position because the draggable's can potentially reflect
10481
					// a relative position, while sortable is always absolute, which the dragged
10482
					// element has now become. (#8809)
10483
					ui.position = sortable.position;
10484
				}
10485
			} else {
10486
 
10487
				// If it doesn't intersect with the sortable, and it intersected before,
10488
				// we fake the drag stop of the sortable, but make sure it doesn't remove
10489
				// the helper by using cancelHelperRemoval.
10490
				if ( sortable.isOver ) {
10491
 
10492
					sortable.isOver = 0;
10493
					sortable.cancelHelperRemoval = true;
10494
 
10495
					// Calling sortable's mouseStop would trigger a revert,
10496
					// so revert must be temporarily false until after mouseStop is called.
10497
					sortable.options._revert = sortable.options.revert;
10498
					sortable.options.revert = false;
10499
 
10500
					sortable._trigger( "out", event, sortable._uiHash( sortable ) );
10501
					sortable._mouseStop( event, true );
10502
 
10503
					// Restore sortable behaviors that were modfied
10504
					// when the draggable entered the sortable area (#9481)
10505
					sortable.options.revert = sortable.options._revert;
10506
					sortable.options.helper = sortable.options._helper;
10507
 
10508
					if ( sortable.placeholder ) {
10509
						sortable.placeholder.remove();
10510
					}
10511
 
10512
					// Restore and recalculate the draggable's offset considering the sortable
10513
					// may have modified them in unexpected ways. (#8809, #10669)
10514
					ui.helper.appendTo( draggable._parent );
10515
					draggable._refreshOffsets( event );
10516
					ui.position = draggable._generatePosition( event, true );
10517
 
10518
					draggable._trigger( "fromSortable", event );
10519
 
10520
					// Inform draggable that the helper is no longer in a valid drop zone
10521
					draggable.dropped = false;
10522
 
10523
					// Need to refreshPositions of all sortables just in case removing
10524
					// from one sortable changes the location of other sortables (#9675)
10525
					$.each( draggable.sortables, function() {
10526
						this.refreshPositions();
10527
					} );
10528
				}
10529
			}
10530
		} );
10531
	}
10532
} );
10533
 
10534
$.ui.plugin.add( "draggable", "cursor", {
10535
	start: function( event, ui, instance ) {
10536
		var t = $( "body" ),
10537
			o = instance.options;
10538
 
10539
		if ( t.css( "cursor" ) ) {
10540
			o._cursor = t.css( "cursor" );
10541
		}
10542
		t.css( "cursor", o.cursor );
10543
	},
10544
	stop: function( event, ui, instance ) {
10545
		var o = instance.options;
10546
		if ( o._cursor ) {
10547
			$( "body" ).css( "cursor", o._cursor );
10548
		}
10549
	}
10550
} );
10551
 
10552
$.ui.plugin.add( "draggable", "opacity", {
10553
	start: function( event, ui, instance ) {
10554
		var t = $( ui.helper ),
10555
			o = instance.options;
10556
		if ( t.css( "opacity" ) ) {
10557
			o._opacity = t.css( "opacity" );
10558
		}
10559
		t.css( "opacity", o.opacity );
10560
	},
10561
	stop: function( event, ui, instance ) {
10562
		var o = instance.options;
10563
		if ( o._opacity ) {
10564
			$( ui.helper ).css( "opacity", o._opacity );
10565
		}
10566
	}
10567
} );
10568
 
10569
$.ui.plugin.add( "draggable", "scroll", {
10570
	start: function( event, ui, i ) {
10571
		if ( !i.scrollParentNotHidden ) {
10572
			i.scrollParentNotHidden = i.helper.scrollParent( false );
10573
		}
10574
 
10575
		if ( i.scrollParentNotHidden[ 0 ] !== i.document[ 0 ] &&
10576
				i.scrollParentNotHidden[ 0 ].tagName !== "HTML" ) {
10577
			i.overflowOffset = i.scrollParentNotHidden.offset();
10578
		}
10579
	},
10580
	drag: function( event, ui, i  ) {
10581
 
10582
		var o = i.options,
10583
			scrolled = false,
10584
			scrollParent = i.scrollParentNotHidden[ 0 ],
10585
			document = i.document[ 0 ];
10586
 
10587
		if ( scrollParent !== document && scrollParent.tagName !== "HTML" ) {
10588
			if ( !o.axis || o.axis !== "x" ) {
10589
				if ( ( i.overflowOffset.top + scrollParent.offsetHeight ) - event.pageY <
10590
						o.scrollSensitivity ) {
10591
					scrollParent.scrollTop = scrolled = scrollParent.scrollTop + o.scrollSpeed;
10592
				} else if ( event.pageY - i.overflowOffset.top < o.scrollSensitivity ) {
10593
					scrollParent.scrollTop = scrolled = scrollParent.scrollTop - o.scrollSpeed;
10594
				}
10595
			}
10596
 
10597
			if ( !o.axis || o.axis !== "y" ) {
10598
				if ( ( i.overflowOffset.left + scrollParent.offsetWidth ) - event.pageX <
10599
						o.scrollSensitivity ) {
10600
					scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft + o.scrollSpeed;
10601
				} else if ( event.pageX - i.overflowOffset.left < o.scrollSensitivity ) {
10602
					scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft - o.scrollSpeed;
10603
				}
10604
			}
10605
 
10606
		} else {
10607
 
10608
			if ( !o.axis || o.axis !== "x" ) {
10609
				if ( event.pageY - $( document ).scrollTop() < o.scrollSensitivity ) {
10610
					scrolled = $( document ).scrollTop( $( document ).scrollTop() - o.scrollSpeed );
10611
				} else if ( $( window ).height() - ( event.pageY - $( document ).scrollTop() ) <
10612
						o.scrollSensitivity ) {
10613
					scrolled = $( document ).scrollTop( $( document ).scrollTop() + o.scrollSpeed );
10614
				}
10615
			}
10616
 
10617
			if ( !o.axis || o.axis !== "y" ) {
10618
				if ( event.pageX - $( document ).scrollLeft() < o.scrollSensitivity ) {
10619
					scrolled = $( document ).scrollLeft(
10620
						$( document ).scrollLeft() - o.scrollSpeed
10621
					);
10622
				} else if ( $( window ).width() - ( event.pageX - $( document ).scrollLeft() ) <
10623
						o.scrollSensitivity ) {
10624
					scrolled = $( document ).scrollLeft(
10625
						$( document ).scrollLeft() + o.scrollSpeed
10626
					);
10627
				}
10628
			}
10629
 
10630
		}
10631
 
10632
		if ( scrolled !== false && $.ui.ddmanager && !o.dropBehaviour ) {
10633
			$.ui.ddmanager.prepareOffsets( i, event );
10634
		}
10635
 
10636
	}
10637
} );
10638
 
10639
$.ui.plugin.add( "draggable", "snap", {
10640
	start: function( event, ui, i ) {
10641
 
10642
		var o = i.options;
10643
 
10644
		i.snapElements = [];
10645
 
10646
		$( o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap )
10647
			.each( function() {
10648
				var $t = $( this ),
10649
					$o = $t.offset();
10650
				if ( this !== i.element[ 0 ] ) {
10651
					i.snapElements.push( {
10652
						item: this,
10653
						width: $t.outerWidth(), height: $t.outerHeight(),
10654
						top: $o.top, left: $o.left
10655
					} );
10656
				}
10657
			} );
10658
 
10659
	},
10660
	drag: function( event, ui, inst ) {
10661
 
10662
		var ts, bs, ls, rs, l, r, t, b, i, first,
10663
			o = inst.options,
10664
			d = o.snapTolerance,
10665
			x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
10666
			y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
10667
 
10668
		for ( i = inst.snapElements.length - 1; i >= 0; i-- ) {
10669
 
10670
			l = inst.snapElements[ i ].left - inst.margins.left;
10671
			r = l + inst.snapElements[ i ].width;
10672
			t = inst.snapElements[ i ].top - inst.margins.top;
10673
			b = t + inst.snapElements[ i ].height;
10674
 
10675
			if ( x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d ||
10676
					!$.contains( inst.snapElements[ i ].item.ownerDocument,
10677
					inst.snapElements[ i ].item ) ) {
10678
				if ( inst.snapElements[ i ].snapping ) {
10679
					if ( inst.options.snap.release ) {
10680
						inst.options.snap.release.call(
10681
							inst.element,
10682
							event,
10683
							$.extend( inst._uiHash(), { snapItem: inst.snapElements[ i ].item } )
10684
						);
10685
					}
10686
				}
10687
				inst.snapElements[ i ].snapping = false;
10688
				continue;
10689
			}
10690
 
10691
			if ( o.snapMode !== "inner" ) {
10692
				ts = Math.abs( t - y2 ) <= d;
10693
				bs = Math.abs( b - y1 ) <= d;
10694
				ls = Math.abs( l - x2 ) <= d;
10695
				rs = Math.abs( r - x1 ) <= d;
10696
				if ( ts ) {
10697
					ui.position.top = inst._convertPositionTo( "relative", {
10698
						top: t - inst.helperProportions.height,
10699
						left: 0
10700
					} ).top;
10701
				}
10702
				if ( bs ) {
10703
					ui.position.top = inst._convertPositionTo( "relative", {
10704
						top: b,
10705
						left: 0
10706
					} ).top;
10707
				}
10708
				if ( ls ) {
10709
					ui.position.left = inst._convertPositionTo( "relative", {
10710
						top: 0,
10711
						left: l - inst.helperProportions.width
10712
					} ).left;
10713
				}
10714
				if ( rs ) {
10715
					ui.position.left = inst._convertPositionTo( "relative", {
10716
						top: 0,
10717
						left: r
10718
					} ).left;
10719
				}
10720
			}
10721
 
10722
			first = ( ts || bs || ls || rs );
10723
 
10724
			if ( o.snapMode !== "outer" ) {
10725
				ts = Math.abs( t - y1 ) <= d;
10726
				bs = Math.abs( b - y2 ) <= d;
10727
				ls = Math.abs( l - x1 ) <= d;
10728
				rs = Math.abs( r - x2 ) <= d;
10729
				if ( ts ) {
10730
					ui.position.top = inst._convertPositionTo( "relative", {
10731
						top: t,
10732
						left: 0
10733
					} ).top;
10734
				}
10735
				if ( bs ) {
10736
					ui.position.top = inst._convertPositionTo( "relative", {
10737
						top: b - inst.helperProportions.height,
10738
						left: 0
10739
					} ).top;
10740
				}
10741
				if ( ls ) {
10742
					ui.position.left = inst._convertPositionTo( "relative", {
10743
						top: 0,
10744
						left: l
10745
					} ).left;
10746
				}
10747
				if ( rs ) {
10748
					ui.position.left = inst._convertPositionTo( "relative", {
10749
						top: 0,
10750
						left: r - inst.helperProportions.width
10751
					} ).left;
10752
				}
10753
			}
10754
 
10755
			if ( !inst.snapElements[ i ].snapping && ( ts || bs || ls || rs || first ) ) {
10756
				if ( inst.options.snap.snap ) {
10757
					inst.options.snap.snap.call(
10758
						inst.element,
10759
						event,
10760
						$.extend( inst._uiHash(), {
10761
							snapItem: inst.snapElements[ i ].item
10762
						} ) );
10763
				}
10764
			}
10765
			inst.snapElements[ i ].snapping = ( ts || bs || ls || rs || first );
10766
 
10767
		}
10768
 
10769
	}
10770
} );
10771
 
10772
$.ui.plugin.add( "draggable", "stack", {
10773
	start: function( event, ui, instance ) {
10774
		var min,
10775
			o = instance.options,
10776
			group = $.makeArray( $( o.stack ) ).sort( function( a, b ) {
10777
				return ( parseInt( $( a ).css( "zIndex" ), 10 ) || 0 ) -
10778
					( parseInt( $( b ).css( "zIndex" ), 10 ) || 0 );
10779
			} );
10780
 
10781
		if ( !group.length ) {
10782
			return;
10783
		}
10784
 
10785
		min = parseInt( $( group[ 0 ] ).css( "zIndex" ), 10 ) || 0;
10786
		$( group ).each( function( i ) {
10787
			$( this ).css( "zIndex", min + i );
10788
		} );
10789
		this.css( "zIndex", ( min + group.length ) );
10790
	}
10791
} );
10792
 
10793
$.ui.plugin.add( "draggable", "zIndex", {
10794
	start: function( event, ui, instance ) {
10795
		var t = $( ui.helper ),
10796
			o = instance.options;
10797
 
10798
		if ( t.css( "zIndex" ) ) {
10799
			o._zIndex = t.css( "zIndex" );
10800
		}
10801
		t.css( "zIndex", o.zIndex );
10802
	},
10803
	stop: function( event, ui, instance ) {
10804
		var o = instance.options;
10805
 
10806
		if ( o._zIndex ) {
10807
			$( ui.helper ).css( "zIndex", o._zIndex );
10808
		}
10809
	}
10810
} );
10811
 
10812
var widgetsDraggable = $.ui.draggable;
10813
 
10814
 
10815
/*!
10816
 * jQuery UI Resizable 1.14.1
10817
 * https://jqueryui.com
10818
 *
10819
 * Copyright OpenJS Foundation and other contributors
10820
 * Released under the MIT license.
10821
 * https://jquery.org/license
10822
 */
10823
 
10824
//>>label: Resizable
10825
//>>group: Interactions
10826
//>>description: Enables resize functionality for any element.
10827
//>>docs: https://api.jqueryui.com/resizable/
10828
//>>demos: https://jqueryui.com/resizable/
10829
//>>css.structure: ../../themes/base/core.css
10830
//>>css.structure: ../../themes/base/resizable.css
10831
//>>css.theme: ../../themes/base/theme.css
10832
 
10833
 
10834
$.widget( "ui.resizable", $.ui.mouse, {
10835
	version: "1.14.1",
10836
	widgetEventPrefix: "resize",
10837
	options: {
10838
		alsoResize: false,
10839
		animate: false,
10840
		animateDuration: "slow",
10841
		animateEasing: "swing",
10842
		aspectRatio: false,
10843
		autoHide: false,
10844
		classes: {
10845
			"ui-resizable-se": "ui-icon ui-icon-gripsmall-diagonal-se"
10846
		},
10847
		containment: false,
10848
		ghost: false,
10849
		grid: false,
10850
		handles: "e,s,se",
10851
		helper: false,
10852
		maxHeight: null,
10853
		maxWidth: null,
10854
		minHeight: 10,
10855
		minWidth: 10,
10856
 
10857
		// See #7960
10858
		zIndex: 90,
10859
 
10860
		// Callbacks
10861
		resize: null,
10862
		start: null,
10863
		stop: null
10864
	},
10865
 
10866
	_num: function( value ) {
10867
		return parseFloat( value ) || 0;
10868
	},
10869
 
10870
	_isNumber: function( value ) {
10871
		return !isNaN( parseFloat( value ) );
10872
	},
10873
 
10874
	_hasScroll: function( el, a ) {
10875
 
10876
		var scroll,
10877
			has = false,
10878
			overflow = $( el ).css( "overflow" );
10879
 
10880
		if ( overflow === "hidden" ) {
10881
			return false;
10882
		}
10883
		if ( overflow === "scroll" ) {
10884
			return true;
10885
		}
10886
 
10887
		scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop";
10888
 
10889
		if ( el[ scroll ] > 0 ) {
10890
			return true;
10891
		}
10892
 
10893
		// TODO: determine which cases actually cause this to happen
10894
		// if the element doesn't have the scroll set, see if it's possible to
10895
		// set the scroll
10896
		try {
10897
			el[ scroll ] = 1;
10898
			has = ( el[ scroll ] > 0 );
10899
			el[ scroll ] = 0;
10900
		} catch ( e ) {
10901
 
10902
			// `el` might be a string, then setting `scroll` will throw
10903
			// an error in strict mode; ignore it.
10904
		}
10905
		return has;
10906
	},
10907
 
10908
	_create: function() {
10909
 
10910
		var margins,
10911
			o = this.options,
10912
			that = this;
10913
		this._addClass( "ui-resizable" );
10914
 
10915
		$.extend( this, {
10916
			_aspectRatio: !!( o.aspectRatio ),
10917
			aspectRatio: o.aspectRatio,
10918
			originalElement: this.element,
10919
			_proportionallyResizeElements: [],
10920
			_helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null
10921
		} );
10922
 
10923
		// Wrap the element if it cannot hold child nodes
10924
		if ( this.element[ 0 ].nodeName.match( /^(canvas|textarea|input|select|button|img)$/i ) ) {
10925
 
10926
			this.element.wrap(
10927
				$( "<div class='ui-wrapper'></div>" ).css( {
10928
					overflow: "hidden",
10929
					position: this.element.css( "position" ),
10930
					width: this.element.outerWidth(),
10931
					height: this.element.outerHeight(),
10932
					top: this.element.css( "top" ),
10933
					left: this.element.css( "left" )
10934
				} )
10935
			);
10936
 
10937
			this.element = this.element.parent().data(
10938
				"ui-resizable", this.element.resizable( "instance" )
10939
			);
10940
 
10941
			this.elementIsWrapper = true;
10942
 
10943
			margins = {
10944
				marginTop: this.originalElement.css( "marginTop" ),
10945
				marginRight: this.originalElement.css( "marginRight" ),
10946
				marginBottom: this.originalElement.css( "marginBottom" ),
10947
				marginLeft: this.originalElement.css( "marginLeft" )
10948
			};
10949
 
10950
			this.element.css( margins );
10951
 
10952
			// Support: Safari
10953
			// Prevent Safari textarea resize
10954
			this.originalResizeStyle = this.originalElement.css( "resize" );
10955
			this.originalElement.css( "resize", "none" );
10956
 
10957
			this._proportionallyResizeElements.push( this.originalElement.css( {
10958
				position: "static",
10959
				zoom: 1,
10960
				display: "block"
10961
			} ) );
10962
 
10963
			this._proportionallyResize();
10964
		}
10965
 
10966
		this._setupHandles();
10967
 
10968
		if ( o.autoHide ) {
10969
			$( this.element )
10970
				.on( "mouseenter", function() {
10971
					if ( o.disabled ) {
10972
						return;
10973
					}
10974
					that._removeClass( "ui-resizable-autohide" );
10975
					that._handles.show();
10976
				} )
10977
				.on( "mouseleave", function() {
10978
					if ( o.disabled ) {
10979
						return;
10980
					}
10981
					if ( !that.resizing ) {
10982
						that._addClass( "ui-resizable-autohide" );
10983
						that._handles.hide();
10984
					}
10985
				} );
10986
		}
10987
 
10988
		this._mouseInit();
10989
	},
10990
 
10991
	_destroy: function() {
10992
 
10993
		this._mouseDestroy();
10994
		this._addedHandles.remove();
10995
 
10996
		var wrapper,
10997
			_destroy = function( exp ) {
10998
				$( exp )
10999
					.removeData( "resizable" )
11000
					.removeData( "ui-resizable" )
11001
					.off( ".resizable" );
11002
			};
11003
 
11004
		// TODO: Unwrap at same DOM position
11005
		if ( this.elementIsWrapper ) {
11006
			_destroy( this.element );
11007
			wrapper = this.element;
11008
			this.originalElement.css( {
11009
				position: wrapper.css( "position" ),
11010
				width: wrapper.outerWidth(),
11011
				height: wrapper.outerHeight(),
11012
				top: wrapper.css( "top" ),
11013
				left: wrapper.css( "left" )
11014
			} ).insertAfter( wrapper );
11015
			wrapper.remove();
11016
		}
11017
 
11018
		this.originalElement.css( "resize", this.originalResizeStyle );
11019
		_destroy( this.originalElement );
11020
 
11021
		return this;
11022
	},
11023
 
11024
	_setOption: function( key, value ) {
11025
		this._super( key, value );
11026
 
11027
		switch ( key ) {
11028
		case "handles":
11029
			this._removeHandles();
11030
			this._setupHandles();
11031
			break;
11032
		case "aspectRatio":
11033
			this._aspectRatio = !!value;
11034
			break;
11035
		default:
11036
			break;
11037
		}
11038
	},
11039
 
11040
	_setupHandles: function() {
11041
		var o = this.options, handle, i, n, hname, axis, that = this;
11042
		this.handles = o.handles ||
11043
			( !$( ".ui-resizable-handle", this.element ).length ?
11044
				"e,s,se" : {
11045
					n: ".ui-resizable-n",
11046
					e: ".ui-resizable-e",
11047
					s: ".ui-resizable-s",
11048
					w: ".ui-resizable-w",
11049
					se: ".ui-resizable-se",
11050
					sw: ".ui-resizable-sw",
11051
					ne: ".ui-resizable-ne",
11052
					nw: ".ui-resizable-nw"
11053
				} );
11054
 
11055
		this._handles = $();
11056
		this._addedHandles = $();
11057
		if ( this.handles.constructor === String ) {
11058
 
11059
			if ( this.handles === "all" ) {
11060
				this.handles = "n,e,s,w,se,sw,ne,nw";
11061
			}
11062
 
11063
			n = this.handles.split( "," );
11064
			this.handles = {};
11065
 
11066
			for ( i = 0; i < n.length; i++ ) {
11067
 
11068
				handle = String.prototype.trim.call( n[ i ] );
11069
				hname = "ui-resizable-" + handle;
11070
				axis = $( "<div>" );
11071
				this._addClass( axis, "ui-resizable-handle " + hname );
11072
 
11073
				axis.css( { zIndex: o.zIndex } );
11074
 
11075
				this.handles[ handle ] = ".ui-resizable-" + handle;
11076
				if ( !this.element.children( this.handles[ handle ] ).length ) {
11077
					this.element.append( axis );
11078
					this._addedHandles = this._addedHandles.add( axis );
11079
				}
11080
			}
11081
 
11082
		}
11083
 
11084
		this._renderAxis = function( target ) {
11085
 
11086
			var i, axis, padPos, padWrapper;
11087
 
11088
			target = target || this.element;
11089
 
11090
			for ( i in this.handles ) {
11091
 
11092
				if ( this.handles[ i ].constructor === String ) {
11093
					this.handles[ i ] = this.element.children( this.handles[ i ] ).first().show();
11094
				} else if ( this.handles[ i ].jquery || this.handles[ i ].nodeType ) {
11095
					this.handles[ i ] = $( this.handles[ i ] );
11096
					this._on( this.handles[ i ], { "mousedown": that._mouseDown } );
11097
				}
11098
 
11099
				if ( this.elementIsWrapper &&
11100
						this.originalElement[ 0 ]
11101
							.nodeName
11102
							.match( /^(textarea|input|select|button)$/i ) ) {
11103
					axis = $( this.handles[ i ], this.element );
11104
 
11105
					padWrapper = /sw|ne|nw|se|n|s/.test( i ) ?
11106
						axis.outerHeight() :
11107
						axis.outerWidth();
11108
 
11109
					padPos = [ "padding",
11110
						/ne|nw|n/.test( i ) ? "Top" :
11111
						/se|sw|s/.test( i ) ? "Bottom" :
11112
						/^e$/.test( i ) ? "Right" : "Left" ].join( "" );
11113
 
11114
					target.css( padPos, padWrapper );
11115
 
11116
					this._proportionallyResize();
11117
				}
11118
 
11119
				this._handles = this._handles.add( this.handles[ i ] );
11120
			}
11121
		};
11122
 
11123
		// TODO: make renderAxis a prototype function
11124
		this._renderAxis( this.element );
11125
 
11126
		this._handles = this._handles.add( this.element.find( ".ui-resizable-handle" ) );
11127
		this._handles.disableSelection();
11128
 
11129
		this._handles.on( "mouseover", function() {
11130
			if ( !that.resizing ) {
11131
				if ( this.className ) {
11132
					axis = this.className.match( /ui-resizable-(se|sw|ne|nw|n|e|s|w)/i );
11133
				}
11134
				that.axis = axis && axis[ 1 ] ? axis[ 1 ] : "se";
11135
			}
11136
		} );
11137
 
11138
		if ( o.autoHide ) {
11139
			this._handles.hide();
11140
			this._addClass( "ui-resizable-autohide" );
11141
		}
11142
	},
11143
 
11144
	_removeHandles: function() {
11145
		this._addedHandles.remove();
11146
	},
11147
 
11148
	_mouseCapture: function( event ) {
11149
		var i, handle,
11150
			capture = false;
11151
 
11152
		for ( i in this.handles ) {
11153
			handle = $( this.handles[ i ] )[ 0 ];
11154
			if ( handle === event.target || $.contains( handle, event.target ) ) {
11155
				capture = true;
11156
			}
11157
		}
11158
 
11159
		return !this.options.disabled && capture;
11160
	},
11161
 
11162
	_mouseStart: function( event ) {
11163
 
11164
		var curleft, curtop, cursor, calculatedSize,
11165
			o = this.options,
11166
			el = this.element;
11167
 
11168
		this.resizing = true;
11169
 
11170
		this._renderProxy();
11171
 
11172
		curleft = this._num( this.helper.css( "left" ) );
11173
		curtop = this._num( this.helper.css( "top" ) );
11174
 
11175
		if ( o.containment ) {
11176
			curleft += $( o.containment ).scrollLeft() || 0;
11177
			curtop += $( o.containment ).scrollTop() || 0;
11178
		}
11179
 
11180
		this.offset = this.helper.offset();
11181
		this.position = { left: curleft, top: curtop };
11182
 
11183
		if ( !this._helper ) {
11184
			calculatedSize = this._calculateAdjustedElementDimensions( el );
11185
		}
11186
 
11187
		this.size = this._helper ? {
11188
				width: this.helper.width(),
11189
				height: this.helper.height()
11190
			} : {
11191
				width: calculatedSize.width,
11192
				height: calculatedSize.height
11193
			};
11194
 
11195
		this.originalSize = this._helper ? {
11196
				width: el.outerWidth(),
11197
				height: el.outerHeight()
11198
			} : {
11199
				width: calculatedSize.width,
11200
				height: calculatedSize.height
11201
			};
11202
 
11203
		this.sizeDiff = {
11204
			width: el.outerWidth() - el.width(),
11205
			height: el.outerHeight() - el.height()
11206
		};
11207
 
11208
		this.originalPosition = { left: curleft, top: curtop };
11209
		this.originalMousePosition = { left: event.pageX, top: event.pageY };
11210
 
11211
		this.aspectRatio = ( typeof o.aspectRatio === "number" ) ?
11212
			o.aspectRatio :
11213
			( ( this.originalSize.width / this.originalSize.height ) || 1 );
11214
 
11215
		cursor = $( ".ui-resizable-" + this.axis ).css( "cursor" );
11216
		$( "body" ).css( "cursor", cursor === "auto" ? this.axis + "-resize" : cursor );
11217
 
11218
		this._addClass( "ui-resizable-resizing" );
11219
		this._propagate( "start", event );
11220
		return true;
11221
	},
11222
 
11223
	_mouseDrag: function( event ) {
11224
 
11225
		var data, props,
11226
			smp = this.originalMousePosition,
11227
			a = this.axis,
11228
			dx = ( event.pageX - smp.left ) || 0,
11229
			dy = ( event.pageY - smp.top ) || 0,
11230
			trigger = this._change[ a ];
11231
 
11232
		this._updatePrevProperties();
11233
 
11234
		if ( !trigger ) {
11235
			return false;
11236
		}
11237
 
11238
		data = trigger.apply( this, [ event, dx, dy ] );
11239
 
11240
		this._updateVirtualBoundaries( event.shiftKey );
11241
		if ( this._aspectRatio || event.shiftKey ) {
11242
			data = this._updateRatio( data, event );
11243
		}
11244
 
11245
		data = this._respectSize( data, event );
11246
 
11247
		this._updateCache( data );
11248
 
11249
		this._propagate( "resize", event );
11250
 
11251
		props = this._applyChanges();
11252
 
11253
		if ( !this._helper && this._proportionallyResizeElements.length ) {
11254
			this._proportionallyResize();
11255
		}
11256
 
11257
		if ( !$.isEmptyObject( props ) ) {
11258
			this._updatePrevProperties();
11259
			this._trigger( "resize", event, this.ui() );
11260
			this._applyChanges();
11261
		}
11262
 
11263
		return false;
11264
	},
11265
 
11266
	_mouseStop: function( event ) {
11267
 
11268
		this.resizing = false;
11269
		var pr, ista, soffseth, soffsetw, s, left, top,
11270
			o = this.options, that = this;
11271
 
11272
		if ( this._helper ) {
11273
 
11274
			pr = this._proportionallyResizeElements;
11275
			ista = pr.length && ( /textarea/i ).test( pr[ 0 ].nodeName );
11276
			soffseth = ista && this._hasScroll( pr[ 0 ], "left" ) ? 0 : that.sizeDiff.height;
11277
			soffsetw = ista ? 0 : that.sizeDiff.width;
11278
 
11279
			s = {
11280
				width: ( that.helper.width()  - soffsetw ),
11281
				height: ( that.helper.height() - soffseth )
11282
			};
11283
			left = ( parseFloat( that.element.css( "left" ) ) +
11284
				( that.position.left - that.originalPosition.left ) ) || null;
11285
			top = ( parseFloat( that.element.css( "top" ) ) +
11286
				( that.position.top - that.originalPosition.top ) ) || null;
11287
 
11288
			if ( !o.animate ) {
11289
				this.element.css( $.extend( s, { top: top, left: left } ) );
11290
			}
11291
 
11292
			that.helper.height( that.size.height );
11293
			that.helper.width( that.size.width );
11294
 
11295
			if ( this._helper && !o.animate ) {
11296
				this._proportionallyResize();
11297
			}
11298
		}
11299
 
11300
		$( "body" ).css( "cursor", "auto" );
11301
 
11302
		this._removeClass( "ui-resizable-resizing" );
11303
 
11304
		this._propagate( "stop", event );
11305
 
11306
		if ( this._helper ) {
11307
			this.helper.remove();
11308
		}
11309
 
11310
		return false;
11311
 
11312
	},
11313
 
11314
	_updatePrevProperties: function() {
11315
		this.prevPosition = {
11316
			top: this.position.top,
11317
			left: this.position.left
11318
		};
11319
		this.prevSize = {
11320
			width: this.size.width,
11321
			height: this.size.height
11322
		};
11323
	},
11324
 
11325
	_applyChanges: function() {
11326
		var props = {};
11327
 
11328
		if ( this.position.top !== this.prevPosition.top ) {
11329
			props.top = this.position.top + "px";
11330
		}
11331
		if ( this.position.left !== this.prevPosition.left ) {
11332
			props.left = this.position.left + "px";
11333
		}
11334
 
11335
		this.helper.css( props );
11336
 
11337
		if ( this.size.width !== this.prevSize.width ) {
11338
			props.width = this.size.width + "px";
11339
			this.helper.width( props.width );
11340
		}
11341
		if ( this.size.height !== this.prevSize.height ) {
11342
			props.height = this.size.height + "px";
11343
			this.helper.height( props.height );
11344
		}
11345
 
11346
		return props;
11347
	},
11348
 
11349
	_updateVirtualBoundaries: function( forceAspectRatio ) {
11350
		var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b,
11351
			o = this.options;
11352
 
11353
		b = {
11354
			minWidth: this._isNumber( o.minWidth ) ? o.minWidth : 0,
11355
			maxWidth: this._isNumber( o.maxWidth ) ? o.maxWidth : Infinity,
11356
			minHeight: this._isNumber( o.minHeight ) ? o.minHeight : 0,
11357
			maxHeight: this._isNumber( o.maxHeight ) ? o.maxHeight : Infinity
11358
		};
11359
 
11360
		if ( this._aspectRatio || forceAspectRatio ) {
11361
			pMinWidth = b.minHeight * this.aspectRatio;
11362
			pMinHeight = b.minWidth / this.aspectRatio;
11363
			pMaxWidth = b.maxHeight * this.aspectRatio;
11364
			pMaxHeight = b.maxWidth / this.aspectRatio;
11365
 
11366
			if ( pMinWidth > b.minWidth ) {
11367
				b.minWidth = pMinWidth;
11368
			}
11369
			if ( pMinHeight > b.minHeight ) {
11370
				b.minHeight = pMinHeight;
11371
			}
11372
			if ( pMaxWidth < b.maxWidth ) {
11373
				b.maxWidth = pMaxWidth;
11374
			}
11375
			if ( pMaxHeight < b.maxHeight ) {
11376
				b.maxHeight = pMaxHeight;
11377
			}
11378
		}
11379
		this._vBoundaries = b;
11380
	},
11381
 
11382
	_updateCache: function( data ) {
11383
		this.offset = this.helper.offset();
11384
		if ( this._isNumber( data.left ) ) {
11385
			this.position.left = data.left;
11386
		}
11387
		if ( this._isNumber( data.top ) ) {
11388
			this.position.top = data.top;
11389
		}
11390
		if ( this._isNumber( data.height ) ) {
11391
			this.size.height = data.height;
11392
		}
11393
		if ( this._isNumber( data.width ) ) {
11394
			this.size.width = data.width;
11395
		}
11396
	},
11397
 
11398
	_updateRatio: function( data ) {
11399
 
11400
		var cpos = this.position,
11401
			csize = this.size,
11402
			a = this.axis;
11403
 
11404
		if ( this._isNumber( data.height ) ) {
11405
			data.width = ( data.height * this.aspectRatio );
11406
		} else if ( this._isNumber( data.width ) ) {
11407
			data.height = ( data.width / this.aspectRatio );
11408
		}
11409
 
11410
		if ( a === "sw" ) {
11411
			data.left = cpos.left + ( csize.width - data.width );
11412
			data.top = null;
11413
		}
11414
		if ( a === "nw" ) {
11415
			data.top = cpos.top + ( csize.height - data.height );
11416
			data.left = cpos.left + ( csize.width - data.width );
11417
		}
11418
 
11419
		return data;
11420
	},
11421
 
11422
	_respectSize: function( data ) {
11423
 
11424
		var o = this._vBoundaries,
11425
			a = this.axis,
11426
			ismaxw = this._isNumber( data.width ) && o.maxWidth && ( o.maxWidth < data.width ),
11427
			ismaxh = this._isNumber( data.height ) && o.maxHeight && ( o.maxHeight < data.height ),
11428
			isminw = this._isNumber( data.width ) && o.minWidth && ( o.minWidth > data.width ),
11429
			isminh = this._isNumber( data.height ) && o.minHeight && ( o.minHeight > data.height ),
11430
			dw = this.originalPosition.left + this.originalSize.width,
11431
			dh = this.originalPosition.top + this.originalSize.height,
11432
			cw = /sw|nw|w/.test( a ), ch = /nw|ne|n/.test( a );
11433
		if ( isminw ) {
11434
			data.width = o.minWidth;
11435
		}
11436
		if ( isminh ) {
11437
			data.height = o.minHeight;
11438
		}
11439
		if ( ismaxw ) {
11440
			data.width = o.maxWidth;
11441
		}
11442
		if ( ismaxh ) {
11443
			data.height = o.maxHeight;
11444
		}
11445
 
11446
		if ( isminw && cw ) {
11447
			data.left = dw - o.minWidth;
11448
		}
11449
		if ( ismaxw && cw ) {
11450
			data.left = dw - o.maxWidth;
11451
		}
11452
		if ( isminh && ch ) {
11453
			data.top = dh - o.minHeight;
11454
		}
11455
		if ( ismaxh && ch ) {
11456
			data.top = dh - o.maxHeight;
11457
		}
11458
 
11459
		// Fixing jump error on top/left - bug #2330
11460
		if ( !data.width && !data.height && !data.left && data.top ) {
11461
			data.top = null;
11462
		} else if ( !data.width && !data.height && !data.top && data.left ) {
11463
			data.left = null;
11464
		}
11465
 
11466
		return data;
11467
	},
11468
 
11469
	_getPaddingPlusBorderDimensions: function( element ) {
11470
		var i = 0,
11471
			widths = [],
11472
			borders = [
11473
				element.css( "borderTopWidth" ),
11474
				element.css( "borderRightWidth" ),
11475
				element.css( "borderBottomWidth" ),
11476
				element.css( "borderLeftWidth" )
11477
			],
11478
			paddings = [
11479
				element.css( "paddingTop" ),
11480
				element.css( "paddingRight" ),
11481
				element.css( "paddingBottom" ),
11482
				element.css( "paddingLeft" )
11483
			];
11484
 
11485
		for ( ; i < 4; i++ ) {
11486
			widths[ i ] = ( parseFloat( borders[ i ] ) || 0 );
11487
			widths[ i ] += ( parseFloat( paddings[ i ] ) || 0 );
11488
		}
11489
 
11490
		return {
11491
			height: widths[ 0 ] + widths[ 2 ],
11492
			width: widths[ 1 ] + widths[ 3 ]
11493
		};
11494
	},
11495
 
11496
	_calculateAdjustedElementDimensions: function( element ) {
11497
		var elWidth, elHeight, paddingBorder,
11498
			ce = element.get( 0 );
11499
 
11500
		if ( element.css( "box-sizing" ) !== "content-box" ||
11501
			( !this._hasScroll( ce ) && !this._hasScroll( ce, "left" ) ) ) {
11502
				return {
11503
					height: parseFloat( element.css( "height" ) ),
11504
					width: parseFloat( element.css( "width" ) )
11505
				};
11506
		}
11507
 
11508
		// Check if CSS inline styles are set and use those (usually from previous resizes)
11509
		elWidth = parseFloat( ce.style.width );
11510
		elHeight = parseFloat( ce.style.height );
11511
 
11512
		paddingBorder = this._getPaddingPlusBorderDimensions( element );
11513
		elWidth = isNaN( elWidth ) ?
11514
			this._getElementTheoreticalSize( element, paddingBorder, "width" ) :
11515
			elWidth;
11516
		elHeight = isNaN( elHeight ) ?
11517
			this._getElementTheoreticalSize( element, paddingBorder, "height" ) :
11518
			elHeight;
11519
 
11520
		return {
11521
			height: elHeight,
11522
			width: elWidth
11523
		};
11524
	},
11525
 
11526
	_getElementTheoreticalSize: function( element, extraSize, dimension ) {
11527
 
11528
		// offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border
11529
		var size = Math.max( 0, Math.ceil(
11530
			element.get( 0 )[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] -
11531
			extraSize[ dimension ] -
11532
			0.5
11533
 
11534
		// If offsetWidth/offsetHeight is unknown, then we can't determine theoretical size.
11535
		// Use an explicit zero to avoid NaN.
11536
		// See https://github.com/jquery/jquery/issues/3964
11537
		) ) || 0;
11538
 
11539
		return size;
11540
	},
11541
 
11542
	_proportionallyResize: function() {
11543
 
11544
		if ( !this._proportionallyResizeElements.length ) {
11545
			return;
11546
		}
11547
 
11548
		var prel,
11549
			i = 0,
11550
			element = this.helper || this.element;
11551
 
11552
		for ( ; i < this._proportionallyResizeElements.length; i++ ) {
11553
 
11554
			prel = this._proportionallyResizeElements[ i ];
11555
 
11556
			// TODO: Seems like a bug to cache this.outerDimensions
11557
			// considering that we are in a loop.
11558
			if ( !this.outerDimensions ) {
11559
				this.outerDimensions = this._getPaddingPlusBorderDimensions( prel );
11560
			}
11561
 
11562
			prel.css( {
11563
				height: ( element.height() - this.outerDimensions.height ) || 0,
11564
				width: ( element.width() - this.outerDimensions.width ) || 0
11565
			} );
11566
 
11567
		}
11568
 
11569
	},
11570
 
11571
	_renderProxy: function() {
11572
 
11573
		var el = this.element, o = this.options;
11574
		this.elementOffset = el.offset();
11575
 
11576
		if ( this._helper ) {
11577
 
11578
			this.helper = this.helper || $( "<div></div>" ).css( { overflow: "hidden" } );
11579
 
11580
			this._addClass( this.helper, this._helper );
11581
			this.helper.css( {
11582
				width: this.element.outerWidth(),
11583
				height: this.element.outerHeight(),
11584
				position: "absolute",
11585
				left: this.elementOffset.left + "px",
11586
				top: this.elementOffset.top + "px",
11587
				zIndex: ++o.zIndex //TODO: Don't modify option
11588
			} );
11589
 
11590
			this.helper
11591
				.appendTo( "body" )
11592
				.disableSelection();
11593
 
11594
		} else {
11595
			this.helper = this.element;
11596
		}
11597
 
11598
	},
11599
 
11600
	_change: {
11601
		e: function( event, dx ) {
11602
			return { width: this.originalSize.width + dx };
11603
		},
11604
		w: function( event, dx ) {
11605
			var cs = this.originalSize, sp = this.originalPosition;
11606
			return { left: sp.left + dx, width: cs.width - dx };
11607
		},
11608
		n: function( event, dx, dy ) {
11609
			var cs = this.originalSize, sp = this.originalPosition;
11610
			return { top: sp.top + dy, height: cs.height - dy };
11611
		},
11612
		s: function( event, dx, dy ) {
11613
			return { height: this.originalSize.height + dy };
11614
		},
11615
		se: function( event, dx, dy ) {
11616
			return $.extend( this._change.s.apply( this, arguments ),
11617
				this._change.e.apply( this, [ event, dx, dy ] ) );
11618
		},
11619
		sw: function( event, dx, dy ) {
11620
			return $.extend( this._change.s.apply( this, arguments ),
11621
				this._change.w.apply( this, [ event, dx, dy ] ) );
11622
		},
11623
		ne: function( event, dx, dy ) {
11624
			return $.extend( this._change.n.apply( this, arguments ),
11625
				this._change.e.apply( this, [ event, dx, dy ] ) );
11626
		},
11627
		nw: function( event, dx, dy ) {
11628
			return $.extend( this._change.n.apply( this, arguments ),
11629
				this._change.w.apply( this, [ event, dx, dy ] ) );
11630
		}
11631
	},
11632
 
11633
	_propagate: function( n, event ) {
11634
		$.ui.plugin.call( this, n, [ event, this.ui() ] );
11635
		if ( n !== "resize" ) {
11636
			this._trigger( n, event, this.ui() );
11637
		}
11638
	},
11639
 
11640
	plugins: {},
11641
 
11642
	ui: function() {
11643
		return {
11644
			originalElement: this.originalElement,
11645
			element: this.element,
11646
			helper: this.helper,
11647
			position: this.position,
11648
			size: this.size,
11649
			originalSize: this.originalSize,
11650
			originalPosition: this.originalPosition
11651
		};
11652
	}
11653
 
11654
} );
11655
 
11656
/*
11657
 * Resizable Extensions
11658
 */
11659
 
11660
$.ui.plugin.add( "resizable", "animate", {
11661
 
11662
	stop: function( event ) {
11663
		var that = $( this ).resizable( "instance" ),
11664
			o = that.options,
11665
			pr = that._proportionallyResizeElements,
11666
			ista = pr.length && ( /textarea/i ).test( pr[ 0 ].nodeName ),
11667
			soffseth = ista && that._hasScroll( pr[ 0 ], "left" ) ? 0 : that.sizeDiff.height,
11668
			soffsetw = ista ? 0 : that.sizeDiff.width,
11669
			style = {
11670
				width: ( that.size.width - soffsetw ),
11671
				height: ( that.size.height - soffseth )
11672
			},
11673
			left = ( parseFloat( that.element.css( "left" ) ) +
11674
				( that.position.left - that.originalPosition.left ) ) || null,
11675
			top = ( parseFloat( that.element.css( "top" ) ) +
11676
				( that.position.top - that.originalPosition.top ) ) || null;
11677
 
11678
		that.element.animate(
11679
			$.extend( style, top && left ? { top: top, left: left } : {} ), {
11680
				duration: o.animateDuration,
11681
				easing: o.animateEasing,
11682
				step: function() {
11683
 
11684
					var data = {
11685
						width: parseFloat( that.element.css( "width" ) ),
11686
						height: parseFloat( that.element.css( "height" ) ),
11687
						top: parseFloat( that.element.css( "top" ) ),
11688
						left: parseFloat( that.element.css( "left" ) )
11689
					};
11690
 
11691
					if ( pr && pr.length ) {
11692
						$( pr[ 0 ] ).css( { width: data.width, height: data.height } );
11693
					}
11694
 
11695
					// Propagating resize, and updating values for each animation step
11696
					that._updateCache( data );
11697
					that._propagate( "resize", event );
11698
 
11699
				}
11700
			}
11701
		);
11702
	}
11703
 
11704
} );
11705
 
11706
$.ui.plugin.add( "resizable", "containment", {
11707
 
11708
	start: function() {
11709
		var element, p, co, ch, cw, width, height,
11710
			that = $( this ).resizable( "instance" ),
11711
			o = that.options,
11712
			el = that.element,
11713
			oc = o.containment,
11714
			ce = ( oc instanceof $ ) ?
11715
				oc.get( 0 ) :
11716
				( /parent/.test( oc ) ) ? el.parent().get( 0 ) : oc;
11717
 
11718
		if ( !ce ) {
11719
			return;
11720
		}
11721
 
11722
		that.containerElement = $( ce );
11723
 
11724
		if ( /document/.test( oc ) || oc === document ) {
11725
			that.containerOffset = {
11726
				left: 0,
11727
				top: 0
11728
			};
11729
			that.containerPosition = {
11730
				left: 0,
11731
				top: 0
11732
			};
11733
 
11734
			that.parentData = {
11735
				element: $( document ),
11736
				left: 0,
11737
				top: 0,
11738
				width: $( document ).width(),
11739
				height: $( document ).height() || document.body.parentNode.scrollHeight
11740
			};
11741
		} else {
11742
			element = $( ce );
11743
			p = [];
11744
			$( [ "Top", "Right", "Left", "Bottom" ] ).each( function( i, name ) {
11745
				p[ i ] = that._num( element.css( "padding" + name ) );
11746
			} );
11747
 
11748
			that.containerOffset = element.offset();
11749
			that.containerPosition = element.position();
11750
			that.containerSize = {
11751
				height: ( element.innerHeight() - p[ 3 ] ),
11752
				width: ( element.innerWidth() - p[ 1 ] )
11753
			};
11754
 
11755
			co = that.containerOffset;
11756
			ch = that.containerSize.height;
11757
			cw = that.containerSize.width;
11758
			width = ( that._hasScroll( ce, "left" ) ? ce.scrollWidth : cw );
11759
			height = ( that._hasScroll( ce ) ? ce.scrollHeight : ch );
11760
 
11761
			that.parentData = {
11762
				element: ce,
11763
				left: co.left,
11764
				top: co.top,
11765
				width: width,
11766
				height: height
11767
			};
11768
		}
11769
	},
11770
 
11771
	resize: function( event ) {
11772
		var woset, hoset, isParent, isOffsetRelative,
11773
			that = $( this ).resizable( "instance" ),
11774
			o = that.options,
11775
			co = that.containerOffset,
11776
			cp = that.position,
11777
			pRatio = that._aspectRatio || event.shiftKey,
11778
			cop = {
11779
				top: 0,
11780
				left: 0
11781
			},
11782
			ce = that.containerElement,
11783
			continueResize = true;
11784
 
11785
		if ( ce[ 0 ] !== document && ( /static/ ).test( ce.css( "position" ) ) ) {
11786
			cop = co;
11787
		}
11788
 
11789
		if ( cp.left < ( that._helper ? co.left : 0 ) ) {
11790
			that.size.width = that.size.width +
11791
				( that._helper ?
11792
					( that.position.left - co.left ) :
11793
					( that.position.left - cop.left ) );
11794
 
11795
			if ( pRatio ) {
11796
				that.size.height = that.size.width / that.aspectRatio;
11797
				continueResize = false;
11798
			}
11799
			that.position.left = o.helper ? co.left : 0;
11800
		}
11801
 
11802
		if ( cp.top < ( that._helper ? co.top : 0 ) ) {
11803
			that.size.height = that.size.height +
11804
				( that._helper ?
11805
					( that.position.top - co.top ) :
11806
					that.position.top );
11807
 
11808
			if ( pRatio ) {
11809
				that.size.width = that.size.height * that.aspectRatio;
11810
				continueResize = false;
11811
			}
11812
			that.position.top = that._helper ? co.top : 0;
11813
		}
11814
 
11815
		isParent = that.containerElement.get( 0 ) === that.element.parent().get( 0 );
11816
		isOffsetRelative = /relative|absolute/.test( that.containerElement.css( "position" ) );
11817
 
11818
		if ( isParent && isOffsetRelative ) {
11819
			that.offset.left = that.parentData.left + that.position.left;
11820
			that.offset.top = that.parentData.top + that.position.top;
11821
		} else {
11822
			that.offset.left = that.element.offset().left;
11823
			that.offset.top = that.element.offset().top;
11824
		}
11825
 
11826
		woset = Math.abs( that.sizeDiff.width +
11827
			( that._helper ?
11828
				that.offset.left - cop.left :
11829
				( that.offset.left - co.left ) ) );
11830
 
11831
		hoset = Math.abs( that.sizeDiff.height +
11832
			( that._helper ?
11833
				that.offset.top - cop.top :
11834
				( that.offset.top - co.top ) ) );
11835
 
11836
		if ( woset + that.size.width >= that.parentData.width ) {
11837
			that.size.width = that.parentData.width - woset;
11838
			if ( pRatio ) {
11839
				that.size.height = that.size.width / that.aspectRatio;
11840
				continueResize = false;
11841
			}
11842
		}
11843
 
11844
		if ( hoset + that.size.height >= that.parentData.height ) {
11845
			that.size.height = that.parentData.height - hoset;
11846
			if ( pRatio ) {
11847
				that.size.width = that.size.height * that.aspectRatio;
11848
				continueResize = false;
11849
			}
11850
		}
11851
 
11852
		if ( !continueResize ) {
11853
			that.position.left = that.prevPosition.left;
11854
			that.position.top = that.prevPosition.top;
11855
			that.size.width = that.prevSize.width;
11856
			that.size.height = that.prevSize.height;
11857
		}
11858
	},
11859
 
11860
	stop: function() {
11861
		var that = $( this ).resizable( "instance" ),
11862
			o = that.options,
11863
			co = that.containerOffset,
11864
			cop = that.containerPosition,
11865
			ce = that.containerElement,
11866
			helper = $( that.helper ),
11867
			ho = helper.offset(),
11868
			w = helper.outerWidth() - that.sizeDiff.width,
11869
			h = helper.outerHeight() - that.sizeDiff.height;
11870
 
11871
		if ( that._helper && !o.animate && ( /relative/ ).test( ce.css( "position" ) ) ) {
11872
			$( this ).css( {
11873
				left: ho.left - cop.left - co.left,
11874
				width: w,
11875
				height: h
11876
			} );
11877
		}
11878
 
11879
		if ( that._helper && !o.animate && ( /static/ ).test( ce.css( "position" ) ) ) {
11880
			$( this ).css( {
11881
				left: ho.left - cop.left - co.left,
11882
				width: w,
11883
				height: h
11884
			} );
11885
		}
11886
	}
11887
} );
11888
 
11889
$.ui.plugin.add( "resizable", "alsoResize", {
11890
 
11891
	start: function() {
11892
		var that = $( this ).resizable( "instance" ),
11893
			o = that.options;
11894
 
11895
		$( o.alsoResize ).each( function() {
11896
			var el = $( this ),
11897
				elSize = that._calculateAdjustedElementDimensions( el );
11898
 
11899
			el.data( "ui-resizable-alsoresize", {
11900
				width: elSize.width, height: elSize.height,
11901
				left: parseFloat( el.css( "left" ) ), top: parseFloat( el.css( "top" ) )
11902
			} );
11903
		} );
11904
	},
11905
 
11906
	resize: function( event, ui ) {
11907
		var that = $( this ).resizable( "instance" ),
11908
			o = that.options,
11909
			os = that.originalSize,
11910
			op = that.originalPosition,
11911
			delta = {
11912
				height: ( that.size.height - os.height ) || 0,
11913
				width: ( that.size.width - os.width ) || 0,
11914
				top: ( that.position.top - op.top ) || 0,
11915
				left: ( that.position.left - op.left ) || 0
11916
			};
11917
 
11918
			$( o.alsoResize ).each( function() {
11919
				var el = $( this ), start = $( this ).data( "ui-resizable-alsoresize" ), style = {},
11920
					css = el.parents( ui.originalElement[ 0 ] ).length ?
11921
							[ "width", "height" ] :
11922
							[ "width", "height", "top", "left" ];
11923
 
11924
				$.each( css, function( i, prop ) {
11925
					var sum = ( start[ prop ] || 0 ) + ( delta[ prop ] || 0 );
11926
					if ( sum && sum >= 0 ) {
11927
						style[ prop ] = sum || null;
11928
					}
11929
				} );
11930
 
11931
				el.css( style );
11932
			} );
11933
	},
11934
 
11935
	stop: function() {
11936
		$( this ).removeData( "ui-resizable-alsoresize" );
11937
	}
11938
} );
11939
 
11940
$.ui.plugin.add( "resizable", "ghost", {
11941
 
11942
	start: function() {
11943
 
11944
		var that = $( this ).resizable( "instance" ), cs = that.size;
11945
 
11946
		that.ghost = that.originalElement.clone();
11947
		that.ghost.css( {
11948
			opacity: 0.25,
11949
			display: "block",
11950
			position: "relative",
11951
			height: cs.height,
11952
			width: cs.width,
11953
			margin: 0,
11954
			left: 0,
11955
			top: 0
11956
		} );
11957
 
11958
		that._addClass( that.ghost, "ui-resizable-ghost" );
11959
 
11960
		// DEPRECATED
11961
		// TODO: remove after 1.12
11962
		if ( $.uiBackCompat === true && typeof that.options.ghost === "string" ) {
11963
 
11964
			// Ghost option
11965
			that.ghost.addClass( this.options.ghost );
11966
		}
11967
 
11968
		that.ghost.appendTo( that.helper );
11969
 
11970
	},
11971
 
11972
	resize: function() {
11973
		var that = $( this ).resizable( "instance" );
11974
		if ( that.ghost ) {
11975
			that.ghost.css( {
11976
				position: "relative",
11977
				height: that.size.height,
11978
				width: that.size.width
11979
			} );
11980
		}
11981
	},
11982
 
11983
	stop: function() {
11984
		var that = $( this ).resizable( "instance" );
11985
		if ( that.ghost && that.helper ) {
11986
			that.helper.get( 0 ).removeChild( that.ghost.get( 0 ) );
11987
		}
11988
	}
11989
 
11990
} );
11991
 
11992
$.ui.plugin.add( "resizable", "grid", {
11993
 
11994
	resize: function() {
11995
		var outerDimensions,
11996
			that = $( this ).resizable( "instance" ),
11997
			o = that.options,
11998
			cs = that.size,
11999
			os = that.originalSize,
12000
			op = that.originalPosition,
12001
			a = that.axis,
12002
			grid = typeof o.grid === "number" ? [ o.grid, o.grid ] : o.grid,
12003
			gridX = ( grid[ 0 ] || 1 ),
12004
			gridY = ( grid[ 1 ] || 1 ),
12005
			ox = Math.round( ( cs.width - os.width ) / gridX ) * gridX,
12006
			oy = Math.round( ( cs.height - os.height ) / gridY ) * gridY,
12007
			newWidth = os.width + ox,
12008
			newHeight = os.height + oy,
12009
			isMaxWidth = o.maxWidth && ( o.maxWidth < newWidth ),
12010
			isMaxHeight = o.maxHeight && ( o.maxHeight < newHeight ),
12011
			isMinWidth = o.minWidth && ( o.minWidth > newWidth ),
12012
			isMinHeight = o.minHeight && ( o.minHeight > newHeight );
12013
 
12014
		o.grid = grid;
12015
 
12016
		if ( isMinWidth ) {
12017
			newWidth += gridX;
12018
		}
12019
		if ( isMinHeight ) {
12020
			newHeight += gridY;
12021
		}
12022
		if ( isMaxWidth ) {
12023
			newWidth -= gridX;
12024
		}
12025
		if ( isMaxHeight ) {
12026
			newHeight -= gridY;
12027
		}
12028
 
12029
		if ( /^(se|s|e)$/.test( a ) ) {
12030
			that.size.width = newWidth;
12031
			that.size.height = newHeight;
12032
		} else if ( /^(ne)$/.test( a ) ) {
12033
			that.size.width = newWidth;
12034
			that.size.height = newHeight;
12035
			that.position.top = op.top - oy;
12036
		} else if ( /^(sw)$/.test( a ) ) {
12037
			that.size.width = newWidth;
12038
			that.size.height = newHeight;
12039
			that.position.left = op.left - ox;
12040
		} else {
12041
			if ( newHeight - gridY <= 0 || newWidth - gridX <= 0 ) {
12042
				outerDimensions = that._getPaddingPlusBorderDimensions( this );
12043
			}
12044
 
12045
			if ( newHeight - gridY > 0 ) {
12046
				that.size.height = newHeight;
12047
				that.position.top = op.top - oy;
12048
			} else {
12049
				newHeight = gridY - outerDimensions.height;
12050
				that.size.height = newHeight;
12051
				that.position.top = op.top + os.height - newHeight;
12052
			}
12053
			if ( newWidth - gridX > 0 ) {
12054
				that.size.width = newWidth;
12055
				that.position.left = op.left - ox;
12056
			} else {
12057
				newWidth = gridX - outerDimensions.width;
12058
				that.size.width = newWidth;
12059
				that.position.left = op.left + os.width - newWidth;
12060
			}
12061
		}
12062
	}
12063
 
12064
} );
12065
 
12066
var widgetsResizable = $.ui.resizable;
12067
 
12068
 
12069
/*!
12070
 * jQuery UI Dialog 1.14.1
12071
 * https://jqueryui.com
12072
 *
12073
 * Copyright OpenJS Foundation and other contributors
12074
 * Released under the MIT license.
12075
 * https://jquery.org/license
12076
 */
12077
 
12078
//>>label: Dialog
12079
//>>group: Widgets
12080
//>>description: Displays customizable dialog windows.
12081
//>>docs: https://api.jqueryui.com/dialog/
12082
//>>demos: https://jqueryui.com/dialog/
12083
//>>css.structure: ../../themes/base/core.css
12084
//>>css.structure: ../../themes/base/dialog.css
12085
//>>css.theme: ../../themes/base/theme.css
12086
 
12087
 
12088
$.widget( "ui.dialog", {
12089
	version: "1.14.1",
12090
	options: {
12091
		appendTo: "body",
12092
		autoOpen: true,
12093
		buttons: [],
12094
		classes: {
12095
			"ui-dialog": "ui-corner-all",
12096
			"ui-dialog-titlebar": "ui-corner-all"
12097
		},
12098
		closeOnEscape: true,
12099
		closeText: "Close",
12100
		draggable: true,
12101
		hide: null,
12102
		height: "auto",
12103
		maxHeight: null,
12104
		maxWidth: null,
12105
		minHeight: 150,
12106
		minWidth: 150,
12107
		modal: false,
12108
		position: {
12109
			my: "center",
12110
			at: "center",
12111
			of: window,
12112
			collision: "fit",
12113
 
12114
			// Ensure the titlebar is always visible
12115
			using: function( pos ) {
12116
				var topOffset = $( this ).css( pos ).offset().top;
12117
				if ( topOffset < 0 ) {
12118
					$( this ).css( "top", pos.top - topOffset );
12119
				}
12120
			}
12121
		},
12122
		resizable: true,
12123
		show: null,
12124
		title: null,
12125
		uiDialogTitleHeadingLevel: 0,
12126
		width: 300,
12127
 
12128
		// Callbacks
12129
		beforeClose: null,
12130
		close: null,
12131
		drag: null,
12132
		dragStart: null,
12133
		dragStop: null,
12134
		focus: null,
12135
		open: null,
12136
		resize: null,
12137
		resizeStart: null,
12138
		resizeStop: null
12139
	},
12140
 
12141
	sizeRelatedOptions: {
12142
		buttons: true,
12143
		height: true,
12144
		maxHeight: true,
12145
		maxWidth: true,
12146
		minHeight: true,
12147
		minWidth: true,
12148
		width: true
12149
	},
12150
 
12151
	resizableRelatedOptions: {
12152
		maxHeight: true,
12153
		maxWidth: true,
12154
		minHeight: true,
12155
		minWidth: true
12156
	},
12157
 
12158
	_create: function() {
12159
		this.originalCss = {
12160
			display: this.element[ 0 ].style.display,
12161
			width: this.element[ 0 ].style.width,
12162
			minHeight: this.element[ 0 ].style.minHeight,
12163
			maxHeight: this.element[ 0 ].style.maxHeight,
12164
			height: this.element[ 0 ].style.height
12165
		};
12166
		this.originalPosition = {
12167
			parent: this.element.parent(),
12168
			index: this.element.parent().children().index( this.element )
12169
		};
12170
		this.originalTitle = this.element.attr( "title" );
12171
		if ( this.options.title == null && this.originalTitle != null ) {
12172
			this.options.title = this.originalTitle;
12173
		}
12174
 
12175
		// Dialogs can't be disabled
12176
		if ( this.options.disabled ) {
12177
			this.options.disabled = false;
12178
		}
12179
 
12180
		this._createWrapper();
12181
 
12182
		this.element
12183
			.show()
12184
			.removeAttr( "title" )
12185
			.appendTo( this.uiDialog );
12186
 
12187
		this._addClass( "ui-dialog-content", "ui-widget-content" );
12188
 
12189
		this._createTitlebar();
12190
		this._createButtonPane();
12191
 
12192
		if ( this.options.draggable && $.fn.draggable ) {
12193
			this._makeDraggable();
12194
		}
12195
		if ( this.options.resizable && $.fn.resizable ) {
12196
			this._makeResizable();
12197
		}
12198
 
12199
		this._isOpen = false;
12200
 
12201
		this._trackFocus();
12202
	},
12203
 
12204
	_init: function() {
12205
		if ( this.options.autoOpen ) {
12206
			this.open();
12207
		}
12208
	},
12209
 
12210
	_appendTo: function() {
12211
		var element = this.options.appendTo;
12212
		if ( element && ( element.jquery || element.nodeType ) ) {
12213
			return $( element );
12214
		}
12215
		return this.document.find( element || "body" ).eq( 0 );
12216
	},
12217
 
12218
	_destroy: function() {
12219
		var next,
12220
			originalPosition = this.originalPosition;
12221
 
12222
		this._untrackInstance();
12223
		this._destroyOverlay();
12224
 
12225
		this.element
12226
			.removeUniqueId()
12227
			.css( this.originalCss )
12228
 
12229
			// Without detaching first, the following becomes really slow
12230
			.detach();
12231
 
12232
		this.uiDialog.remove();
12233
 
12234
		if ( this.originalTitle ) {
12235
			this.element.attr( "title", this.originalTitle );
12236
		}
12237
 
12238
		next = originalPosition.parent.children().eq( originalPosition.index );
12239
 
12240
		// Don't try to place the dialog next to itself (#8613)
12241
		if ( next.length && next[ 0 ] !== this.element[ 0 ] ) {
12242
			next.before( this.element );
12243
		} else {
12244
			originalPosition.parent.append( this.element );
12245
		}
12246
	},
12247
 
12248
	widget: function() {
12249
		return this.uiDialog;
12250
	},
12251
 
12252
	disable: $.noop,
12253
	enable: $.noop,
12254
 
12255
	close: function( event ) {
12256
		var that = this;
12257
 
12258
		if ( !this._isOpen || this._trigger( "beforeClose", event ) === false ) {
12259
			return;
12260
		}
12261
 
12262
		this._isOpen = false;
12263
		this._focusedElement = null;
12264
		this._destroyOverlay();
12265
		this._untrackInstance();
12266
 
12267
		if ( !this.opener.filter( ":focusable" ).trigger( "focus" ).length ) {
12268
 
12269
			// Hiding a focused element doesn't trigger blur in WebKit
12270
			// so in case we have nothing to focus on, explicitly blur the active element
12271
			// https://bugs.webkit.org/show_bug.cgi?id=47182
12272
			$( this.document[ 0 ].activeElement ).trigger( "blur" );
12273
		}
12274
 
12275
		this._hide( this.uiDialog, this.options.hide, function() {
12276
			that._trigger( "close", event );
12277
		} );
12278
	},
12279
 
12280
	isOpen: function() {
12281
		return this._isOpen;
12282
	},
12283
 
12284
	moveToTop: function() {
12285
		this._moveToTop();
12286
	},
12287
 
12288
	_moveToTop: function( event, silent ) {
12289
		var moved = false,
12290
			zIndices = this.uiDialog.siblings( ".ui-front:visible" ).map( function() {
12291
				return +$( this ).css( "z-index" );
12292
			} ).get(),
12293
			zIndexMax = Math.max.apply( null, zIndices );
12294
 
12295
		if ( zIndexMax >= +this.uiDialog.css( "z-index" ) ) {
12296
			this.uiDialog.css( "z-index", zIndexMax + 1 );
12297
			moved = true;
12298
		}
12299
 
12300
		if ( moved && !silent ) {
12301
			this._trigger( "focus", event );
12302
		}
12303
		return moved;
12304
	},
12305
 
12306
	open: function() {
12307
		var that = this;
12308
		if ( this._isOpen ) {
12309
			if ( this._moveToTop() ) {
12310
				this._focusTabbable();
12311
			}
12312
			return;
12313
		}
12314
 
12315
		this._isOpen = true;
12316
		this.opener = $( this.document[ 0 ].activeElement );
12317
 
12318
		this._size();
12319
		this._position();
12320
		this._createOverlay();
12321
		this._moveToTop( null, true );
12322
 
12323
		// Ensure the overlay is moved to the top with the dialog, but only when
12324
		// opening. The overlay shouldn't move after the dialog is open so that
12325
		// modeless dialogs opened after the modal dialog stack properly.
12326
		if ( this.overlay ) {
12327
			this.overlay.css( "z-index", this.uiDialog.css( "z-index" ) - 1 );
12328
		}
12329
 
12330
		this._show( this.uiDialog, this.options.show, function() {
12331
			that._focusTabbable();
12332
			that._trigger( "focus" );
12333
		} );
12334
 
12335
		// Track the dialog immediately upon opening in case a focus event
12336
		// somehow occurs outside of the dialog before an element inside the
12337
		// dialog is focused (#10152)
12338
		this._makeFocusTarget();
12339
 
12340
		this._trigger( "open" );
12341
	},
12342
 
12343
	_focusTabbable: function() {
12344
 
12345
		// Set focus to the first match:
12346
		// 1. An element that was focused previously
12347
		// 2. First element inside the dialog matching [autofocus]
12348
		// 3. Tabbable element inside the content element
12349
		// 4. Tabbable element inside the buttonpane
12350
		// 5. The close button
12351
		// 6. The dialog itself
12352
		var hasFocus = this._focusedElement;
12353
		if ( !hasFocus ) {
12354
			hasFocus = this.element.find( "[autofocus]" );
12355
		}
12356
		if ( !hasFocus.length ) {
12357
			hasFocus = this.element.find( ":tabbable" );
12358
		}
12359
		if ( !hasFocus.length ) {
12360
			hasFocus = this.uiDialogButtonPane.find( ":tabbable" );
12361
		}
12362
		if ( !hasFocus.length ) {
12363
			hasFocus = this.uiDialogTitlebarClose.filter( ":tabbable" );
12364
		}
12365
		if ( !hasFocus.length ) {
12366
			hasFocus = this.uiDialog;
12367
		}
12368
		hasFocus.eq( 0 ).trigger( "focus" );
12369
	},
12370
 
12371
	_restoreTabbableFocus: function() {
12372
		var activeElement = this.document[ 0 ].activeElement,
12373
			isActive = this.uiDialog[ 0 ] === activeElement ||
12374
				$.contains( this.uiDialog[ 0 ], activeElement );
12375
		if ( !isActive ) {
12376
			this._focusTabbable();
12377
		}
12378
	},
12379
 
12380
	_keepFocus: function( event ) {
12381
		event.preventDefault();
12382
		this._restoreTabbableFocus();
12383
	},
12384
 
12385
	_createWrapper: function() {
12386
		this.uiDialog = $( "<div>" )
12387
			.hide()
12388
			.attr( {
12389
 
12390
				// Setting tabIndex makes the div focusable
12391
				tabIndex: -1,
12392
				role: "dialog",
12393
				"aria-modal": this.options.modal ? "true" : null
12394
			} )
12395
			.appendTo( this._appendTo() );
12396
 
12397
		this._addClass( this.uiDialog, "ui-dialog", "ui-widget ui-widget-content ui-front" );
12398
		this._on( this.uiDialog, {
12399
			keydown: function( event ) {
12400
				if ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
12401
						event.keyCode === $.ui.keyCode.ESCAPE ) {
12402
					event.preventDefault();
12403
					this.close( event );
12404
					return;
12405
				}
12406
 
12407
				// Prevent tabbing out of dialogs
12408
				if ( event.keyCode !== $.ui.keyCode.TAB || event.isDefaultPrevented() ) {
12409
					return;
12410
				}
12411
				var tabbables = this.uiDialog.find( ":tabbable" ),
12412
					first = tabbables.first(),
12413
					last = tabbables.last();
12414
 
12415
				if ( ( event.target === last[ 0 ] || event.target === this.uiDialog[ 0 ] ) &&
12416
						!event.shiftKey ) {
12417
					this._delay( function() {
12418
						first.trigger( "focus" );
12419
					} );
12420
					event.preventDefault();
12421
				} else if ( ( event.target === first[ 0 ] ||
12422
						event.target === this.uiDialog[ 0 ] ) && event.shiftKey ) {
12423
					this._delay( function() {
12424
						last.trigger( "focus" );
12425
					} );
12426
					event.preventDefault();
12427
				}
12428
			},
12429
			mousedown: function( event ) {
12430
				if ( this._moveToTop( event ) ) {
12431
					this._focusTabbable();
12432
				}
12433
			}
12434
		} );
12435
 
12436
		// We assume that any existing aria-describedby attribute means
12437
		// that the dialog content is marked up properly
12438
		// otherwise we brute force the content as the description
12439
		if ( !this.element.find( "[aria-describedby]" ).length ) {
12440
			this.uiDialog.attr( {
12441
				"aria-describedby": this.element.uniqueId().attr( "id" )
12442
			} );
12443
		}
12444
	},
12445
 
12446
	_createTitlebar: function() {
12447
		var uiDialogTitle;
12448
 
12449
		this.uiDialogTitlebar = $( "<div>" );
12450
		this._addClass( this.uiDialogTitlebar,
12451
			"ui-dialog-titlebar", "ui-widget-header ui-helper-clearfix" );
12452
		this._on( this.uiDialogTitlebar, {
12453
			mousedown: function( event ) {
12454
 
12455
				// Don't prevent click on close button (#8838)
12456
				// Focusing a dialog that is partially scrolled out of view
12457
				// causes the browser to scroll it into view, preventing the click event
12458
				if ( !$( event.target ).closest( ".ui-dialog-titlebar-close" ) ) {
12459
 
12460
					// Dialog isn't getting focus when dragging (#8063)
12461
					this.uiDialog.trigger( "focus" );
12462
				}
12463
			}
12464
		} );
12465
 
12466
		this.uiDialogTitlebarClose = $( "<button type='button'></button>" )
12467
			.button( {
12468
				label: $( "<a>" ).text( this.options.closeText ).html(),
12469
				icon: "ui-icon-closethick",
12470
				showLabel: false
12471
			} )
12472
			.appendTo( this.uiDialogTitlebar );
12473
 
12474
		this._addClass( this.uiDialogTitlebarClose, "ui-dialog-titlebar-close" );
12475
		this._on( this.uiDialogTitlebarClose, {
12476
			click: function( event ) {
12477
				event.preventDefault();
12478
				this.close( event );
12479
			}
12480
		} );
12481
 
12482
		var uiDialogHeadingLevel = Number.isInteger( this.options.uiDialogTitleHeadingLevel ) &&
12483
			this.options.uiDialogTitleHeadingLevel > 0 &&
12484
			this.options.uiDialogTitleHeadingLevel <= 6 ?
12485
			"h" + this.options.uiDialogTitleHeadingLevel : "span";
12486
 
12487
		uiDialogTitle = $( "<" + uiDialogHeadingLevel + ">" )
12488
			.uniqueId().prependTo( this.uiDialogTitlebar );
12489
		this._addClass( uiDialogTitle, "ui-dialog-title" );
12490
		this._title( uiDialogTitle );
12491
 
12492
		this.uiDialogTitlebar.prependTo( this.uiDialog );
12493
 
12494
		this.uiDialog.attr( {
12495
			"aria-labelledby": uiDialogTitle.attr( "id" )
12496
		} );
12497
	},
12498
 
12499
	_title: function( title ) {
12500
		if ( this.options.title ) {
12501
			title.text( this.options.title );
12502
		} else {
12503
			title.html( "&#160;" );
12504
		}
12505
	},
12506
 
12507
	_createButtonPane: function() {
12508
		this.uiDialogButtonPane = $( "<div>" );
12509
		this._addClass( this.uiDialogButtonPane, "ui-dialog-buttonpane",
12510
			"ui-widget-content ui-helper-clearfix" );
12511
 
12512
		this.uiButtonSet = $( "<div>" )
12513
			.appendTo( this.uiDialogButtonPane );
12514
		this._addClass( this.uiButtonSet, "ui-dialog-buttonset" );
12515
 
12516
		this._createButtons();
12517
	},
12518
 
12519
	_createButtons: function() {
12520
		var that = this,
12521
			buttons = this.options.buttons;
12522
 
12523
		// If we already have a button pane, remove it
12524
		this.uiDialogButtonPane.remove();
12525
		this.uiButtonSet.empty();
12526
 
12527
		if ( $.isEmptyObject( buttons ) || ( Array.isArray( buttons ) && !buttons.length ) ) {
12528
			this._removeClass( this.uiDialog, "ui-dialog-buttons" );
12529
			return;
12530
		}
12531
 
12532
		$.each( buttons, function( name, props ) {
12533
			var click, buttonOptions;
12534
			props = typeof props === "function" ?
12535
				{ click: props, text: name } :
12536
				props;
12537
 
12538
			// Default to a non-submitting button
12539
			props = $.extend( { type: "button" }, props );
12540
 
12541
			// Change the context for the click callback to be the main element
12542
			click = props.click;
12543
			buttonOptions = {
12544
				icon: props.icon,
12545
				iconPosition: props.iconPosition,
12546
				showLabel: props.showLabel,
12547
 
12548
				// Deprecated options
12549
				icons: props.icons,
12550
				text: props.text
12551
			};
12552
 
12553
			delete props.click;
12554
			delete props.icon;
12555
			delete props.iconPosition;
12556
			delete props.showLabel;
12557
 
12558
			// Deprecated options
12559
			delete props.icons;
12560
			if ( typeof props.text === "boolean" ) {
12561
				delete props.text;
12562
			}
12563
 
12564
			$( "<button></button>", props )
12565
				.button( buttonOptions )
12566
				.appendTo( that.uiButtonSet )
12567
				.on( "click", function() {
12568
					click.apply( that.element[ 0 ], arguments );
12569
				} );
12570
		} );
12571
		this._addClass( this.uiDialog, "ui-dialog-buttons" );
12572
		this.uiDialogButtonPane.appendTo( this.uiDialog );
12573
	},
12574
 
12575
	_makeDraggable: function() {
12576
		var that = this,
12577
			options = this.options;
12578
 
12579
		function filteredUi( ui ) {
12580
			return {
12581
				position: ui.position,
12582
				offset: ui.offset
12583
			};
12584
		}
12585
 
12586
		this.uiDialog.draggable( {
12587
			cancel: ".ui-dialog-content, .ui-dialog-titlebar-close",
12588
			handle: ".ui-dialog-titlebar",
12589
			containment: "document",
12590
			start: function( event, ui ) {
12591
				that._addClass( $( this ), "ui-dialog-dragging" );
12592
				that._blockFrames();
12593
				that._trigger( "dragStart", event, filteredUi( ui ) );
12594
			},
12595
			drag: function( event, ui ) {
12596
				that._trigger( "drag", event, filteredUi( ui ) );
12597
			},
12598
			stop: function( event, ui ) {
12599
				var left = ui.offset.left - that.document.scrollLeft(),
12600
					top = ui.offset.top - that.document.scrollTop();
12601
 
12602
				options.position = {
12603
					my: "left top",
12604
					at: "left" + ( left >= 0 ? "+" : "" ) + left + " " +
12605
						"top" + ( top >= 0 ? "+" : "" ) + top,
12606
					of: that.window
12607
				};
12608
				that._removeClass( $( this ), "ui-dialog-dragging" );
12609
				that._unblockFrames();
12610
				that._trigger( "dragStop", event, filteredUi( ui ) );
12611
			}
12612
		} );
12613
	},
12614
 
12615
	_makeResizable: function() {
12616
		var that = this,
12617
			options = this.options,
12618
			handles = options.resizable,
12619
 
12620
			// .ui-resizable has position: relative defined in the stylesheet
12621
			// but dialogs have to use absolute or fixed positioning
12622
			position = this.uiDialog.css( "position" ),
12623
			resizeHandles = typeof handles === "string" ?
12624
				handles :
12625
				"n,e,s,w,se,sw,ne,nw";
12626
 
12627
		function filteredUi( ui ) {
12628
			return {
12629
				originalPosition: ui.originalPosition,
12630
				originalSize: ui.originalSize,
12631
				position: ui.position,
12632
				size: ui.size
12633
			};
12634
		}
12635
 
12636
		this.uiDialog.resizable( {
12637
			cancel: ".ui-dialog-content",
12638
			containment: "document",
12639
			alsoResize: this.element,
12640
			maxWidth: options.maxWidth,
12641
			maxHeight: options.maxHeight,
12642
			minWidth: options.minWidth,
12643
			minHeight: this._minHeight(),
12644
			handles: resizeHandles,
12645
			start: function( event, ui ) {
12646
				that._addClass( $( this ), "ui-dialog-resizing" );
12647
				that._blockFrames();
12648
				that._trigger( "resizeStart", event, filteredUi( ui ) );
12649
			},
12650
			resize: function( event, ui ) {
12651
				that._trigger( "resize", event, filteredUi( ui ) );
12652
			},
12653
			stop: function( event, ui ) {
12654
				var offset = that.uiDialog.offset(),
12655
					left = offset.left - that.document.scrollLeft(),
12656
					top = offset.top - that.document.scrollTop();
12657
 
12658
				options.height = that.uiDialog.height();
12659
				options.width = that.uiDialog.width();
12660
				options.position = {
12661
					my: "left top",
12662
					at: "left" + ( left >= 0 ? "+" : "" ) + left + " " +
12663
						"top" + ( top >= 0 ? "+" : "" ) + top,
12664
					of: that.window
12665
				};
12666
				that._removeClass( $( this ), "ui-dialog-resizing" );
12667
				that._unblockFrames();
12668
				that._trigger( "resizeStop", event, filteredUi( ui ) );
12669
			}
12670
		} )
12671
			.css( "position", position );
12672
	},
12673
 
12674
	_trackFocus: function() {
12675
		this._on( this.widget(), {
12676
			focusin: function( event ) {
12677
				this._makeFocusTarget();
12678
				this._focusedElement = $( event.target );
12679
			}
12680
		} );
12681
	},
12682
 
12683
	_makeFocusTarget: function() {
12684
		this._untrackInstance();
12685
		this._trackingInstances().unshift( this );
12686
	},
12687
 
12688
	_untrackInstance: function() {
12689
		var instances = this._trackingInstances(),
12690
			exists = $.inArray( this, instances );
12691
		if ( exists !== -1 ) {
12692
			instances.splice( exists, 1 );
12693
		}
12694
	},
12695
 
12696
	_trackingInstances: function() {
12697
		var instances = this.document.data( "ui-dialog-instances" );
12698
		if ( !instances ) {
12699
			instances = [];
12700
			this.document.data( "ui-dialog-instances", instances );
12701
		}
12702
		return instances;
12703
	},
12704
 
12705
	_minHeight: function() {
12706
		var options = this.options;
12707
 
12708
		return options.height === "auto" ?
12709
			options.minHeight :
12710
			Math.min( options.minHeight, options.height );
12711
	},
12712
 
12713
	_position: function() {
12714
 
12715
		// Need to show the dialog to get the actual offset in the position plugin
12716
		var isVisible = this.uiDialog.is( ":visible" );
12717
		if ( !isVisible ) {
12718
			this.uiDialog.show();
12719
		}
12720
		this.uiDialog.position( this.options.position );
12721
		if ( !isVisible ) {
12722
			this.uiDialog.hide();
12723
		}
12724
	},
12725
 
12726
	_setOptions: function( options ) {
12727
		var that = this,
12728
			resize = false,
12729
			resizableOptions = {};
12730
 
12731
		$.each( options, function( key, value ) {
12732
			that._setOption( key, value );
12733
 
12734
			if ( key in that.sizeRelatedOptions ) {
12735
				resize = true;
12736
			}
12737
			if ( key in that.resizableRelatedOptions ) {
12738
				resizableOptions[ key ] = value;
12739
			}
12740
		} );
12741
 
12742
		if ( resize ) {
12743
			this._size();
12744
			this._position();
12745
		}
12746
		if ( this.uiDialog.is( ":data(ui-resizable)" ) ) {
12747
			this.uiDialog.resizable( "option", resizableOptions );
12748
		}
12749
	},
12750
 
12751
	_setOption: function( key, value ) {
12752
		var isDraggable, isResizable,
12753
			uiDialog = this.uiDialog;
12754
 
12755
		if ( key === "disabled" ) {
12756
			return;
12757
		}
12758
 
12759
		this._super( key, value );
12760
 
12761
		if ( key === "appendTo" ) {
12762
			this.uiDialog.appendTo( this._appendTo() );
12763
		}
12764
 
12765
		if ( key === "buttons" ) {
12766
			this._createButtons();
12767
		}
12768
 
12769
		if ( key === "closeText" ) {
12770
			this.uiDialogTitlebarClose.button( {
12771
 
12772
				// Ensure that we always pass a string
12773
				label: $( "<a>" ).text( "" + this.options.closeText ).html()
12774
			} );
12775
		}
12776
 
12777
		if ( key === "draggable" ) {
12778
			isDraggable = uiDialog.is( ":data(ui-draggable)" );
12779
			if ( isDraggable && !value ) {
12780
				uiDialog.draggable( "destroy" );
12781
			}
12782
 
12783
			if ( !isDraggable && value ) {
12784
				this._makeDraggable();
12785
			}
12786
		}
12787
 
12788
		if ( key === "position" ) {
12789
			this._position();
12790
		}
12791
 
12792
		if ( key === "resizable" ) {
12793
 
12794
			// currently resizable, becoming non-resizable
12795
			isResizable = uiDialog.is( ":data(ui-resizable)" );
12796
			if ( isResizable && !value ) {
12797
				uiDialog.resizable( "destroy" );
12798
			}
12799
 
12800
			// Currently resizable, changing handles
12801
			if ( isResizable && typeof value === "string" ) {
12802
				uiDialog.resizable( "option", "handles", value );
12803
			}
12804
 
12805
			// Currently non-resizable, becoming resizable
12806
			if ( !isResizable && value !== false ) {
12807
				this._makeResizable();
12808
			}
12809
		}
12810
 
12811
		if ( key === "title" ) {
12812
			this._title( this.uiDialogTitlebar.find( ".ui-dialog-title" ) );
12813
		}
12814
 
12815
		if ( key === "modal" ) {
12816
			uiDialog.attr( "aria-modal", value ? "true" : null );
12817
		}
12818
	},
12819
 
12820
	_size: function() {
12821
 
12822
		// If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
12823
		// divs will both have width and height set, so we need to reset them
12824
		var nonContentHeight, minContentHeight, maxContentHeight,
12825
			options = this.options;
12826
 
12827
		// Reset content sizing
12828
		this.element.show().css( {
12829
			width: "auto",
12830
			minHeight: 0,
12831
			maxHeight: "none",
12832
			height: 0
12833
		} );
12834
 
12835
		if ( options.minWidth > options.width ) {
12836
			options.width = options.minWidth;
12837
		}
12838
 
12839
		// Reset wrapper sizing
12840
		// determine the height of all the non-content elements
12841
		nonContentHeight = this.uiDialog.css( {
12842
			height: "auto",
12843
			width: options.width
12844
		} )
12845
			.outerHeight();
12846
		minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
12847
		maxContentHeight = typeof options.maxHeight === "number" ?
12848
			Math.max( 0, options.maxHeight - nonContentHeight ) :
12849
			"none";
12850
 
12851
		if ( options.height === "auto" ) {
12852
			this.element.css( {
12853
				minHeight: minContentHeight,
12854
				maxHeight: maxContentHeight,
12855
				height: "auto"
12856
			} );
12857
		} else {
12858
			this.element.height( Math.max( 0, options.height - nonContentHeight ) );
12859
		}
12860
 
12861
		if ( this.uiDialog.is( ":data(ui-resizable)" ) ) {
12862
			this.uiDialog.resizable( "option", "minHeight", this._minHeight() );
12863
		}
12864
	},
12865
 
12866
	_blockFrames: function() {
12867
		this.iframeBlocks = this.document.find( "iframe" ).map( function() {
12868
			var iframe = $( this );
12869
 
12870
			return $( "<div>" )
12871
				.css( {
12872
					position: "absolute",
12873
					width: iframe.outerWidth(),
12874
					height: iframe.outerHeight()
12875
				} )
12876
				.appendTo( iframe.parent() )
12877
				.offset( iframe.offset() )[ 0 ];
12878
		} );
12879
	},
12880
 
12881
	_unblockFrames: function() {
12882
		if ( this.iframeBlocks ) {
12883
			this.iframeBlocks.remove();
12884
			delete this.iframeBlocks;
12885
		}
12886
	},
12887
 
12888
	_allowInteraction: function( event ) {
12889
		if ( $( event.target ).closest( ".ui-dialog" ).length ) {
12890
			return true;
12891
		}
12892
 
12893
		// TODO: Remove hack when datepicker implements
12894
		// the .ui-front logic (#8989)
12895
		return !!$( event.target ).closest( ".ui-datepicker" ).length;
12896
	},
12897
 
12898
	_createOverlay: function() {
12899
		if ( !this.options.modal ) {
12900
			return;
12901
		}
12902
 
12903
		// We use a delay in case the overlay is created from an
12904
		// event that we're going to be cancelling (#2804)
12905
		var isOpening = true;
12906
		this._delay( function() {
12907
			isOpening = false;
12908
		} );
12909
 
12910
		if ( !this.document.data( "ui-dialog-overlays" ) ) {
12911
 
12912
			// Prevent use of anchors and inputs
12913
			// This doesn't use `_on()` because it is a shared event handler
12914
			// across all open modal dialogs.
12915
			this.document.on( "focusin.ui-dialog", function( event ) {
12916
				if ( isOpening ) {
12917
					return;
12918
				}
12919
 
12920
				var instance = this._trackingInstances()[ 0 ];
12921
				if ( !instance._allowInteraction( event ) ) {
12922
					event.preventDefault();
12923
					instance._focusTabbable();
12924
				}
12925
			}.bind( this ) );
12926
		}
12927
 
12928
		this.overlay = $( "<div>" )
12929
			.appendTo( this._appendTo() );
12930
 
12931
		this._addClass( this.overlay, null, "ui-widget-overlay ui-front" );
12932
		this._on( this.overlay, {
12933
			mousedown: "_keepFocus"
12934
		} );
12935
		this.document.data( "ui-dialog-overlays",
12936
			( this.document.data( "ui-dialog-overlays" ) || 0 ) + 1 );
12937
	},
12938
 
12939
	_destroyOverlay: function() {
12940
		if ( !this.options.modal ) {
12941
			return;
12942
		}
12943
 
12944
		if ( this.overlay ) {
12945
			var overlays = this.document.data( "ui-dialog-overlays" ) - 1;
12946
 
12947
			if ( !overlays ) {
12948
				this.document.off( "focusin.ui-dialog" );
12949
				this.document.removeData( "ui-dialog-overlays" );
12950
			} else {
12951
				this.document.data( "ui-dialog-overlays", overlays );
12952
			}
12953
 
12954
			this.overlay.remove();
12955
			this.overlay = null;
12956
		}
12957
	}
12958
} );
12959
 
12960
// DEPRECATED
12961
// TODO: switch return back to widget declaration at top of file when this is removed
12962
if ( $.uiBackCompat === true ) {
12963
 
12964
	// Backcompat for dialogClass option
12965
	$.widget( "ui.dialog", $.ui.dialog, {
12966
		options: {
12967
			dialogClass: ""
12968
		},
12969
		_createWrapper: function() {
12970
			this._super();
12971
			this.uiDialog.addClass( this.options.dialogClass );
12972
		},
12973
		_setOption: function( key, value ) {
12974
			if ( key === "dialogClass" ) {
12975
				this.uiDialog
12976
					.removeClass( this.options.dialogClass )
12977
					.addClass( value );
12978
			}
12979
			this._superApply( arguments );
12980
		}
12981
	} );
12982
}
12983
 
12984
var widgetsDialog = $.ui.dialog;
12985
 
12986
 
12987
/*!
12988
 * jQuery UI Droppable 1.14.1
12989
 * https://jqueryui.com
12990
 *
12991
 * Copyright OpenJS Foundation and other contributors
12992
 * Released under the MIT license.
12993
 * https://jquery.org/license
12994
 */
12995
 
12996
//>>label: Droppable
12997
//>>group: Interactions
12998
//>>description: Enables drop targets for draggable elements.
12999
//>>docs: https://api.jqueryui.com/droppable/
13000
//>>demos: https://jqueryui.com/droppable/
13001
 
13002
 
13003
$.widget( "ui.droppable", {
13004
	version: "1.14.1",
13005
	widgetEventPrefix: "drop",
13006
	options: {
13007
		accept: "*",
13008
		addClasses: true,
13009
		greedy: false,
13010
		scope: "default",
13011
		tolerance: "intersect",
13012
 
13013
		// Callbacks
13014
		activate: null,
13015
		deactivate: null,
13016
		drop: null,
13017
		out: null,
13018
		over: null
13019
	},
13020
	_create: function() {
13021
 
13022
		var proportions,
13023
			o = this.options,
13024
			accept = o.accept;
13025
 
13026
		this.isover = false;
13027
		this.isout = true;
13028
 
13029
		this.accept = typeof accept === "function" ? accept : function( d ) {
13030
			return d.is( accept );
13031
		};
13032
 
13033
		this.proportions = function( /* valueToWrite */ ) {
13034
			if ( arguments.length ) {
13035
 
13036
				// Store the droppable's proportions
13037
				proportions = arguments[ 0 ];
13038
			} else {
13039
 
13040
				// Retrieve or derive the droppable's proportions
13041
				return proportions ?
13042
					proportions :
13043
					proportions = {
13044
						width: this.element[ 0 ].offsetWidth,
13045
						height: this.element[ 0 ].offsetHeight
13046
					};
13047
			}
13048
		};
13049
 
13050
		this._addToManager( o.scope );
13051
 
13052
		if ( o.addClasses ) {
13053
			this._addClass( "ui-droppable" );
13054
		}
13055
 
13056
	},
13057
 
13058
	_addToManager: function( scope ) {
13059
 
13060
		// Add the reference and positions to the manager
13061
		$.ui.ddmanager.droppables[ scope ] = $.ui.ddmanager.droppables[ scope ] || [];
13062
		$.ui.ddmanager.droppables[ scope ].push( this );
13063
	},
13064
 
13065
	_splice: function( drop ) {
13066
		var i = 0;
13067
		for ( ; i < drop.length; i++ ) {
13068
			if ( drop[ i ] === this ) {
13069
				drop.splice( i, 1 );
13070
			}
13071
		}
13072
	},
13073
 
13074
	_destroy: function() {
13075
		var drop = $.ui.ddmanager.droppables[ this.options.scope ];
13076
 
13077
		this._splice( drop );
13078
	},
13079
 
13080
	_setOption: function( key, value ) {
13081
 
13082
		if ( key === "accept" ) {
13083
			this.accept = typeof value === "function" ? value : function( d ) {
13084
				return d.is( value );
13085
			};
13086
		} else if ( key === "scope" ) {
13087
			var drop = $.ui.ddmanager.droppables[ this.options.scope ];
13088
 
13089
			this._splice( drop );
13090
			this._addToManager( value );
13091
		}
13092
 
13093
		this._super( key, value );
13094
	},
13095
 
13096
	_activate: function( event ) {
13097
		var draggable = $.ui.ddmanager.current;
13098
 
13099
		this._addActiveClass();
13100
		if ( draggable ) {
13101
			this._trigger( "activate", event, this.ui( draggable ) );
13102
		}
13103
	},
13104
 
13105
	_deactivate: function( event ) {
13106
		var draggable = $.ui.ddmanager.current;
13107
 
13108
		this._removeActiveClass();
13109
		if ( draggable ) {
13110
			this._trigger( "deactivate", event, this.ui( draggable ) );
13111
		}
13112
	},
13113
 
13114
	_over: function( event ) {
13115
 
13116
		var draggable = $.ui.ddmanager.current;
13117
 
13118
		// Bail if draggable and droppable are same element
13119
		if ( !draggable || ( draggable.currentItem ||
13120
				draggable.element )[ 0 ] === this.element[ 0 ] ) {
13121
			return;
13122
		}
13123
 
13124
		if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem ||
13125
				draggable.element ) ) ) {
13126
			this._addHoverClass();
13127
			this._trigger( "over", event, this.ui( draggable ) );
13128
		}
13129
 
13130
	},
13131
 
13132
	_out: function( event ) {
13133
 
13134
		var draggable = $.ui.ddmanager.current;
13135
 
13136
		// Bail if draggable and droppable are same element
13137
		if ( !draggable || ( draggable.currentItem ||
13138
				draggable.element )[ 0 ] === this.element[ 0 ] ) {
13139
			return;
13140
		}
13141
 
13142
		if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem ||
13143
				draggable.element ) ) ) {
13144
			this._removeHoverClass();
13145
			this._trigger( "out", event, this.ui( draggable ) );
13146
		}
13147
 
13148
	},
13149
 
13150
	_drop: function( event, custom ) {
13151
 
13152
		var draggable = custom || $.ui.ddmanager.current,
13153
			childrenIntersection = false;
13154
 
13155
		// Bail if draggable and droppable are same element
13156
		if ( !draggable || ( draggable.currentItem ||
13157
				draggable.element )[ 0 ] === this.element[ 0 ] ) {
13158
			return false;
13159
		}
13160
 
13161
		this.element
13162
			.find( ":data(ui-droppable)" )
13163
			.not( ".ui-draggable-dragging" )
13164
			.each( function() {
13165
				var inst = $( this ).droppable( "instance" );
13166
				if (
13167
					inst.options.greedy &&
13168
					!inst.options.disabled &&
13169
					inst.options.scope === draggable.options.scope &&
13170
					inst.accept.call(
13171
						inst.element[ 0 ], ( draggable.currentItem || draggable.element )
13172
					) &&
13173
					$.ui.intersect(
13174
						draggable,
13175
						$.extend( inst, { offset: inst.element.offset() } ),
13176
						inst.options.tolerance, event
13177
					)
13178
				) {
13179
					childrenIntersection = true;
13180
					return false;
13181
				}
13182
			} );
13183
		if ( childrenIntersection ) {
13184
			return false;
13185
		}
13186
 
13187
		if ( this.accept.call( this.element[ 0 ],
13188
				( draggable.currentItem || draggable.element ) ) ) {
13189
			this._removeActiveClass();
13190
			this._removeHoverClass();
13191
 
13192
			this._trigger( "drop", event, this.ui( draggable ) );
13193
			return this.element;
13194
		}
13195
 
13196
		return false;
13197
 
13198
	},
13199
 
13200
	ui: function( c ) {
13201
		return {
13202
			draggable: ( c.currentItem || c.element ),
13203
			helper: c.helper,
13204
			position: c.position,
13205
			offset: c.positionAbs
13206
		};
13207
	},
13208
 
13209
	// Extension points just to make backcompat sane and avoid duplicating logic
13210
	// TODO: Remove in 1.14 along with call to it below
13211
	_addHoverClass: function() {
13212
		this._addClass( "ui-droppable-hover" );
13213
	},
13214
 
13215
	_removeHoverClass: function() {
13216
		this._removeClass( "ui-droppable-hover" );
13217
	},
13218
 
13219
	_addActiveClass: function() {
13220
		this._addClass( "ui-droppable-active" );
13221
	},
13222
 
13223
	_removeActiveClass: function() {
13224
		this._removeClass( "ui-droppable-active" );
13225
	}
13226
} );
13227
 
13228
$.ui.intersect = ( function() {
13229
	function isOverAxis( x, reference, size ) {
13230
		return ( x >= reference ) && ( x < ( reference + size ) );
13231
	}
13232
 
13233
	return function( draggable, droppable, toleranceMode, event ) {
13234
 
13235
		if ( !droppable.offset ) {
13236
			return false;
13237
		}
13238
 
13239
		var x1 = ( draggable.positionAbs ||
13240
				draggable.position.absolute ).left + draggable.margins.left,
13241
			y1 = ( draggable.positionAbs ||
13242
				draggable.position.absolute ).top + draggable.margins.top,
13243
			x2 = x1 + draggable.helperProportions.width,
13244
			y2 = y1 + draggable.helperProportions.height,
13245
			l = droppable.offset.left,
13246
			t = droppable.offset.top,
13247
			r = l + droppable.proportions().width,
13248
			b = t + droppable.proportions().height;
13249
 
13250
		switch ( toleranceMode ) {
13251
		case "fit":
13252
			return ( l <= x1 && x2 <= r && t <= y1 && y2 <= b );
13253
		case "intersect":
13254
			return ( l < x1 + ( draggable.helperProportions.width / 2 ) && // Right Half
13255
				x2 - ( draggable.helperProportions.width / 2 ) < r && // Left Half
13256
				t < y1 + ( draggable.helperProportions.height / 2 ) && // Bottom Half
13257
				y2 - ( draggable.helperProportions.height / 2 ) < b ); // Top Half
13258
		case "pointer":
13259
			return isOverAxis( event.pageY, t, droppable.proportions().height ) &&
13260
				isOverAxis( event.pageX, l, droppable.proportions().width );
13261
		case "touch":
13262
			return (
13263
				( y1 >= t && y1 <= b ) || // Top edge touching
13264
				( y2 >= t && y2 <= b ) || // Bottom edge touching
13265
				( y1 < t && y2 > b ) // Surrounded vertically
13266
			) && (
13267
				( x1 >= l && x1 <= r ) || // Left edge touching
13268
				( x2 >= l && x2 <= r ) || // Right edge touching
13269
				( x1 < l && x2 > r ) // Surrounded horizontally
13270
			);
13271
		default:
13272
			return false;
13273
		}
13274
	};
13275
} )();
13276
 
13277
/*
13278
	This manager tracks offsets of draggables and droppables
13279
*/
13280
$.ui.ddmanager = {
13281
	current: null,
13282
	droppables: { "default": [] },
13283
	prepareOffsets: function( t, event ) {
13284
 
13285
		var i, j,
13286
			m = $.ui.ddmanager.droppables[ t.options.scope ] || [],
13287
			type = event ? event.type : null, // workaround for #2317
13288
			list = ( t.currentItem || t.element ).find( ":data(ui-droppable)" ).addBack();
13289
 
13290
		droppablesLoop: for ( i = 0; i < m.length; i++ ) {
13291
 
13292
			// No disabled and non-accepted
13293
			if ( m[ i ].options.disabled || ( t && !m[ i ].accept.call( m[ i ].element[ 0 ],
13294
					( t.currentItem || t.element ) ) ) ) {
13295
				continue;
13296
			}
13297
 
13298
			// Filter out elements in the current dragged item
13299
			for ( j = 0; j < list.length; j++ ) {
13300
				if ( list[ j ] === m[ i ].element[ 0 ] ) {
13301
					m[ i ].proportions().height = 0;
13302
					continue droppablesLoop;
13303
				}
13304
			}
13305
 
13306
			m[ i ].visible = m[ i ].element.css( "display" ) !== "none";
13307
			if ( !m[ i ].visible ) {
13308
				continue;
13309
			}
13310
 
13311
			// Activate the droppable if used directly from draggables
13312
			if ( type === "mousedown" ) {
13313
				m[ i ]._activate.call( m[ i ], event );
13314
			}
13315
 
13316
			m[ i ].offset = m[ i ].element.offset();
13317
			m[ i ].proportions( {
13318
				width: m[ i ].element[ 0 ].offsetWidth,
13319
				height: m[ i ].element[ 0 ].offsetHeight
13320
			} );
13321
 
13322
		}
13323
 
13324
	},
13325
	drop: function( draggable, event ) {
13326
 
13327
		var dropped = false;
13328
 
13329
		// Create a copy of the droppables in case the list changes during the drop (#9116)
13330
		$.each( ( $.ui.ddmanager.droppables[ draggable.options.scope ] || [] ).slice(), function() {
13331
 
13332
			if ( !this.options ) {
13333
				return;
13334
			}
13335
			if ( !this.options.disabled && this.visible &&
13336
					$.ui.intersect( draggable, this, this.options.tolerance, event ) ) {
13337
				dropped = this._drop.call( this, event ) || dropped;
13338
			}
13339
 
13340
			if ( !this.options.disabled && this.visible && this.accept.call( this.element[ 0 ],
13341
					( draggable.currentItem || draggable.element ) ) ) {
13342
				this.isout = true;
13343
				this.isover = false;
13344
				this._deactivate.call( this, event );
13345
			}
13346
 
13347
		} );
13348
		return dropped;
13349
 
13350
	},
13351
	dragStart: function( draggable, event ) {
13352
 
13353
		// Listen for scrolling so that if the dragging causes scrolling the position of the
13354
		// droppables can be recalculated (see #5003)
13355
		draggable.element.parentsUntil( "body" ).on( "scroll.droppable", function() {
13356
			if ( !draggable.options.refreshPositions ) {
13357
				$.ui.ddmanager.prepareOffsets( draggable, event );
13358
			}
13359
		} );
13360
	},
13361
	drag: function( draggable, event ) {
13362
 
13363
		// If you have a highly dynamic page, you might try this option. It renders positions
13364
		// every time you move the mouse.
13365
		if ( draggable.options.refreshPositions ) {
13366
			$.ui.ddmanager.prepareOffsets( draggable, event );
13367
		}
13368
 
13369
		// Run through all droppables and check their positions based on specific tolerance options
13370
		$.each( $.ui.ddmanager.droppables[ draggable.options.scope ] || [], function() {
13371
 
13372
			if ( this.options.disabled || this.greedyChild || !this.visible ) {
13373
				return;
13374
			}
13375
 
13376
			var parentInstance, scope, parent,
13377
				intersects = $.ui.intersect( draggable, this, this.options.tolerance, event ),
13378
				c = !intersects && this.isover ?
13379
					"isout" :
13380
					( intersects && !this.isover ? "isover" : null );
13381
			if ( !c ) {
13382
				return;
13383
			}
13384
 
13385
			if ( this.options.greedy ) {
13386
 
13387
				// find droppable parents with same scope
13388
				scope = this.options.scope;
13389
				parent = this.element.parents( ":data(ui-droppable)" ).filter( function() {
13390
					return $( this ).droppable( "instance" ).options.scope === scope;
13391
				} );
13392
 
13393
				if ( parent.length ) {
13394
					parentInstance = $( parent[ 0 ] ).droppable( "instance" );
13395
					parentInstance.greedyChild = ( c === "isover" );
13396
				}
13397
			}
13398
 
13399
			// We just moved into a greedy child
13400
			if ( parentInstance && c === "isover" ) {
13401
				parentInstance.isover = false;
13402
				parentInstance.isout = true;
13403
				parentInstance._out.call( parentInstance, event );
13404
			}
13405
 
13406
			this[ c ] = true;
13407
			this[ c === "isout" ? "isover" : "isout" ] = false;
13408
			this[ c === "isover" ? "_over" : "_out" ].call( this, event );
13409
 
13410
			// We just moved out of a greedy child
13411
			if ( parentInstance && c === "isout" ) {
13412
				parentInstance.isout = false;
13413
				parentInstance.isover = true;
13414
				parentInstance._over.call( parentInstance, event );
13415
			}
13416
		} );
13417
 
13418
	},
13419
	dragStop: function( draggable, event ) {
13420
		draggable.element.parentsUntil( "body" ).off( "scroll.droppable" );
13421
 
13422
		// Call prepareOffsets one final time since IE does not fire return scroll events when
13423
		// overflow was caused by drag (see #5003)
13424
		if ( !draggable.options.refreshPositions ) {
13425
			$.ui.ddmanager.prepareOffsets( draggable, event );
13426
		}
13427
	}
13428
};
13429
 
13430
// DEPRECATED
13431
// TODO: switch return back to widget declaration at top of file when this is removed
13432
if ( $.uiBackCompat === true ) {
13433
 
13434
	// Backcompat for activeClass and hoverClass options
13435
	$.widget( "ui.droppable", $.ui.droppable, {
13436
		options: {
13437
			hoverClass: false,
13438
			activeClass: false
13439
		},
13440
		_addActiveClass: function() {
13441
			this._super();
13442
			if ( this.options.activeClass ) {
13443
				this.element.addClass( this.options.activeClass );
13444
			}
13445
		},
13446
		_removeActiveClass: function() {
13447
			this._super();
13448
			if ( this.options.activeClass ) {
13449
				this.element.removeClass( this.options.activeClass );
13450
			}
13451
		},
13452
		_addHoverClass: function() {
13453
			this._super();
13454
			if ( this.options.hoverClass ) {
13455
				this.element.addClass( this.options.hoverClass );
13456
			}
13457
		},
13458
		_removeHoverClass: function() {
13459
			this._super();
13460
			if ( this.options.hoverClass ) {
13461
				this.element.removeClass( this.options.hoverClass );
13462
			}
13463
		}
13464
	} );
13465
}
13466
 
13467
var widgetsDroppable = $.ui.droppable;
13468
 
13469
 
13470
/*!
13471
 * jQuery UI Progressbar 1.14.1
13472
 * https://jqueryui.com
13473
 *
13474
 * Copyright OpenJS Foundation and other contributors
13475
 * Released under the MIT license.
13476
 * https://jquery.org/license
13477
 */
13478
 
13479
//>>label: Progressbar
13480
//>>group: Widgets
13481
/* eslint-disable max-len */
13482
//>>description: Displays a status indicator for loading state, standard percentage, and other progress indicators.
13483
/* eslint-enable max-len */
13484
//>>docs: https://api.jqueryui.com/progressbar/
13485
//>>demos: https://jqueryui.com/progressbar/
13486
//>>css.structure: ../../themes/base/core.css
13487
//>>css.structure: ../../themes/base/progressbar.css
13488
//>>css.theme: ../../themes/base/theme.css
13489
 
13490
 
13491
var widgetsProgressbar = $.widget( "ui.progressbar", {
13492
	version: "1.14.1",
13493
	options: {
13494
		classes: {
13495
			"ui-progressbar": "ui-corner-all",
13496
			"ui-progressbar-value": "ui-corner-left",
13497
			"ui-progressbar-complete": "ui-corner-right"
13498
		},
13499
		max: 100,
13500
		value: 0,
13501
 
13502
		change: null,
13503
		complete: null
13504
	},
13505
 
13506
	min: 0,
13507
 
13508
	_create: function() {
13509
 
13510
		// Constrain initial value
13511
		this.oldValue = this.options.value = this._constrainedValue();
13512
 
13513
		this.element.attr( {
13514
 
13515
			// Only set static values; aria-valuenow and aria-valuemax are
13516
			// set inside _refreshValue()
13517
			role: "progressbar",
13518
			"aria-valuemin": this.min
13519
		} );
13520
		this._addClass( "ui-progressbar", "ui-widget ui-widget-content" );
13521
 
13522
		this.valueDiv = $( "<div>" ).appendTo( this.element );
13523
		this._addClass( this.valueDiv, "ui-progressbar-value", "ui-widget-header" );
13524
		this._refreshValue();
13525
	},
13526
 
13527
	_destroy: function() {
13528
		this.element.removeAttr( "role aria-valuemin aria-valuemax aria-valuenow" );
13529
 
13530
		this.valueDiv.remove();
13531
	},
13532
 
13533
	value: function( newValue ) {
13534
		if ( newValue === undefined ) {
13535
			return this.options.value;
13536
		}
13537
 
13538
		this.options.value = this._constrainedValue( newValue );
13539
		this._refreshValue();
13540
	},
13541
 
13542
	_constrainedValue: function( newValue ) {
13543
		if ( newValue === undefined ) {
13544
			newValue = this.options.value;
13545
		}
13546
 
13547
		this.indeterminate = newValue === false;
13548
 
13549
		// Sanitize value
13550
		if ( typeof newValue !== "number" ) {
13551
			newValue = 0;
13552
		}
13553
 
13554
		return this.indeterminate ? false :
13555
			Math.min( this.options.max, Math.max( this.min, newValue ) );
13556
	},
13557
 
13558
	_setOptions: function( options ) {
13559
 
13560
		// Ensure "value" option is set after other values (like max)
13561
		var value = options.value;
13562
		delete options.value;
13563
 
13564
		this._super( options );
13565
 
13566
		this.options.value = this._constrainedValue( value );
13567
		this._refreshValue();
13568
	},
13569
 
13570
	_setOption: function( key, value ) {
13571
		if ( key === "max" ) {
13572
 
13573
			// Don't allow a max less than min
13574
			value = Math.max( this.min, value );
13575
		}
13576
		this._super( key, value );
13577
	},
13578
 
13579
	_setOptionDisabled: function( value ) {
13580
		this._super( value );
13581
 
13582
		this.element.attr( "aria-disabled", value );
13583
		this._toggleClass( null, "ui-state-disabled", !!value );
13584
	},
13585
 
13586
	_percentage: function() {
13587
		return this.indeterminate ?
13588
			100 :
13589
			100 * ( this.options.value - this.min ) / ( this.options.max - this.min );
13590
	},
13591
 
13592
	_refreshValue: function() {
13593
		var value = this.options.value,
13594
			percentage = this._percentage();
13595
 
13596
		this.valueDiv
13597
			.toggle( this.indeterminate || value > this.min )
13598
			.width( percentage.toFixed( 0 ) + "%" );
13599
 
13600
		this
13601
			._toggleClass( this.valueDiv, "ui-progressbar-complete", null,
13602
				value === this.options.max )
13603
			._toggleClass( "ui-progressbar-indeterminate", null, this.indeterminate );
13604
 
13605
		if ( this.indeterminate ) {
13606
			this.element.removeAttr( "aria-valuenow" );
13607
			if ( !this.overlayDiv ) {
13608
				this.overlayDiv = $( "<div>" ).appendTo( this.valueDiv );
13609
				this._addClass( this.overlayDiv, "ui-progressbar-overlay" );
13610
			}
13611
		} else {
13612
			this.element.attr( {
13613
				"aria-valuemax": this.options.max,
13614
				"aria-valuenow": value
13615
			} );
13616
			if ( this.overlayDiv ) {
13617
				this.overlayDiv.remove();
13618
				this.overlayDiv = null;
13619
			}
13620
		}
13621
 
13622
		if ( this.oldValue !== value ) {
13623
			this.oldValue = value;
13624
			this._trigger( "change" );
13625
		}
13626
		if ( value === this.options.max ) {
13627
			this._trigger( "complete" );
13628
		}
13629
	}
13630
} );
13631
 
13632
 
13633
/*!
13634
 * jQuery UI Selectable 1.14.1
13635
 * https://jqueryui.com
13636
 *
13637
 * Copyright OpenJS Foundation and other contributors
13638
 * Released under the MIT license.
13639
 * https://jquery.org/license
13640
 */
13641
 
13642
//>>label: Selectable
13643
//>>group: Interactions
13644
//>>description: Allows groups of elements to be selected with the mouse.
13645
//>>docs: https://api.jqueryui.com/selectable/
13646
//>>demos: https://jqueryui.com/selectable/
13647
//>>css.structure: ../../themes/base/selectable.css
13648
 
13649
 
13650
var widgetsSelectable = $.widget( "ui.selectable", $.ui.mouse, {
13651
	version: "1.14.1",
13652
	options: {
13653
		appendTo: "body",
13654
		autoRefresh: true,
13655
		distance: 0,
13656
		filter: "*",
13657
		tolerance: "touch",
13658
 
13659
		// Callbacks
13660
		selected: null,
13661
		selecting: null,
13662
		start: null,
13663
		stop: null,
13664
		unselected: null,
13665
		unselecting: null
13666
	},
13667
	_create: function() {
13668
		var that = this;
13669
 
13670
		this._addClass( "ui-selectable" );
13671
 
13672
		this.dragged = false;
13673
 
13674
		// Cache selectee children based on filter
13675
		this.refresh = function() {
13676
			that.elementPos = $( that.element[ 0 ] ).offset();
13677
			that.selectees = $( that.options.filter, that.element[ 0 ] );
13678
			that._addClass( that.selectees, "ui-selectee" );
13679
			that.selectees.each( function() {
13680
				var $this = $( this ),
13681
					selecteeOffset = $this.offset(),
13682
					pos = {
13683
						left: selecteeOffset.left - that.elementPos.left,
13684
						top: selecteeOffset.top - that.elementPos.top
13685
					};
13686
				$.data( this, "selectable-item", {
13687
					element: this,
13688
					$element: $this,
13689
					left: pos.left,
13690
					top: pos.top,
13691
					right: pos.left + $this.outerWidth(),
13692
					bottom: pos.top + $this.outerHeight(),
13693
					startselected: false,
13694
					selected: $this.hasClass( "ui-selected" ),
13695
					selecting: $this.hasClass( "ui-selecting" ),
13696
					unselecting: $this.hasClass( "ui-unselecting" )
13697
				} );
13698
			} );
13699
		};
13700
		this.refresh();
13701
 
13702
		this._mouseInit();
13703
 
13704
		this.helper = $( "<div>" );
13705
		this._addClass( this.helper, "ui-selectable-helper" );
13706
	},
13707
 
13708
	_destroy: function() {
13709
		this.selectees.removeData( "selectable-item" );
13710
		this._mouseDestroy();
13711
	},
13712
 
13713
	_mouseStart: function( event ) {
13714
		var that = this,
13715
			options = this.options;
13716
 
13717
		this.opos = [ event.pageX, event.pageY ];
13718
		this.elementPos = $( this.element[ 0 ] ).offset();
13719
 
13720
		if ( this.options.disabled ) {
13721
			return;
13722
		}
13723
 
13724
		this.selectees = $( options.filter, this.element[ 0 ] );
13725
 
13726
		this._trigger( "start", event );
13727
 
13728
		$( options.appendTo ).append( this.helper );
13729
 
13730
		// position helper (lasso)
13731
		this.helper.css( {
13732
			"left": event.pageX,
13733
			"top": event.pageY,
13734
			"width": 0,
13735
			"height": 0
13736
		} );
13737
 
13738
		if ( options.autoRefresh ) {
13739
			this.refresh();
13740
		}
13741
 
13742
		this.selectees.filter( ".ui-selected" ).each( function() {
13743
			var selectee = $.data( this, "selectable-item" );
13744
			selectee.startselected = true;
13745
			if ( !event.metaKey && !event.ctrlKey ) {
13746
				that._removeClass( selectee.$element, "ui-selected" );
13747
				selectee.selected = false;
13748
				that._addClass( selectee.$element, "ui-unselecting" );
13749
				selectee.unselecting = true;
13750
 
13751
				// selectable UNSELECTING callback
13752
				that._trigger( "unselecting", event, {
13753
					unselecting: selectee.element
13754
				} );
13755
			}
13756
		} );
13757
 
13758
		$( event.target ).parents().addBack().each( function() {
13759
			var doSelect,
13760
				selectee = $.data( this, "selectable-item" );
13761
			if ( selectee ) {
13762
				doSelect = ( !event.metaKey && !event.ctrlKey ) ||
13763
					!selectee.$element.hasClass( "ui-selected" );
13764
				that._removeClass( selectee.$element, doSelect ? "ui-unselecting" : "ui-selected" )
13765
					._addClass( selectee.$element, doSelect ? "ui-selecting" : "ui-unselecting" );
13766
				selectee.unselecting = !doSelect;
13767
				selectee.selecting = doSelect;
13768
				selectee.selected = doSelect;
13769
 
13770
				// selectable (UN)SELECTING callback
13771
				if ( doSelect ) {
13772
					that._trigger( "selecting", event, {
13773
						selecting: selectee.element
13774
					} );
13775
				} else {
13776
					that._trigger( "unselecting", event, {
13777
						unselecting: selectee.element
13778
					} );
13779
				}
13780
				return false;
13781
			}
13782
		} );
13783
 
13784
	},
13785
 
13786
	_mouseDrag: function( event ) {
13787
 
13788
		this.dragged = true;
13789
 
13790
		if ( this.options.disabled ) {
13791
			return;
13792
		}
13793
 
13794
		var tmp,
13795
			that = this,
13796
			options = this.options,
13797
			x1 = this.opos[ 0 ],
13798
			y1 = this.opos[ 1 ],
13799
			x2 = event.pageX,
13800
			y2 = event.pageY;
13801
 
13802
		if ( x1 > x2 ) {
13803
			tmp = x2; x2 = x1; x1 = tmp;
13804
		}
13805
		if ( y1 > y2 ) {
13806
			tmp = y2; y2 = y1; y1 = tmp;
13807
		}
13808
		this.helper.css( { left: x1, top: y1, width: x2 - x1, height: y2 - y1 } );
13809
 
13810
		this.selectees.each( function() {
13811
			var selectee = $.data( this, "selectable-item" ),
13812
				hit = false,
13813
				offset = {};
13814
 
13815
			//prevent helper from being selected if appendTo: selectable
13816
			if ( !selectee || selectee.element === that.element[ 0 ] ) {
13817
				return;
13818
			}
13819
 
13820
			offset.left   = selectee.left   + that.elementPos.left;
13821
			offset.right  = selectee.right  + that.elementPos.left;
13822
			offset.top    = selectee.top    + that.elementPos.top;
13823
			offset.bottom = selectee.bottom + that.elementPos.top;
13824
 
13825
			if ( options.tolerance === "touch" ) {
13826
				hit = ( !( offset.left > x2 || offset.right < x1 || offset.top > y2 ||
13827
                    offset.bottom < y1 ) );
13828
			} else if ( options.tolerance === "fit" ) {
13829
				hit = ( offset.left > x1 && offset.right < x2 && offset.top > y1 &&
13830
                    offset.bottom < y2 );
13831
			}
13832
 
13833
			if ( hit ) {
13834
 
13835
				// SELECT
13836
				if ( selectee.selected ) {
13837
					that._removeClass( selectee.$element, "ui-selected" );
13838
					selectee.selected = false;
13839
				}
13840
				if ( selectee.unselecting ) {
13841
					that._removeClass( selectee.$element, "ui-unselecting" );
13842
					selectee.unselecting = false;
13843
				}
13844
				if ( !selectee.selecting ) {
13845
					that._addClass( selectee.$element, "ui-selecting" );
13846
					selectee.selecting = true;
13847
 
13848
					// selectable SELECTING callback
13849
					that._trigger( "selecting", event, {
13850
						selecting: selectee.element
13851
					} );
13852
				}
13853
			} else {
13854
 
13855
				// UNSELECT
13856
				if ( selectee.selecting ) {
13857
					if ( ( event.metaKey || event.ctrlKey ) && selectee.startselected ) {
13858
						that._removeClass( selectee.$element, "ui-selecting" );
13859
						selectee.selecting = false;
13860
						that._addClass( selectee.$element, "ui-selected" );
13861
						selectee.selected = true;
13862
					} else {
13863
						that._removeClass( selectee.$element, "ui-selecting" );
13864
						selectee.selecting = false;
13865
						if ( selectee.startselected ) {
13866
							that._addClass( selectee.$element, "ui-unselecting" );
13867
							selectee.unselecting = true;
13868
						}
13869
 
13870
						// selectable UNSELECTING callback
13871
						that._trigger( "unselecting", event, {
13872
							unselecting: selectee.element
13873
						} );
13874
					}
13875
				}
13876
				if ( selectee.selected ) {
13877
					if ( !event.metaKey && !event.ctrlKey && !selectee.startselected ) {
13878
						that._removeClass( selectee.$element, "ui-selected" );
13879
						selectee.selected = false;
13880
 
13881
						that._addClass( selectee.$element, "ui-unselecting" );
13882
						selectee.unselecting = true;
13883
 
13884
						// selectable UNSELECTING callback
13885
						that._trigger( "unselecting", event, {
13886
							unselecting: selectee.element
13887
						} );
13888
					}
13889
				}
13890
			}
13891
		} );
13892
 
13893
		return false;
13894
	},
13895
 
13896
	_mouseStop: function( event ) {
13897
		var that = this;
13898
 
13899
		this.dragged = false;
13900
 
13901
		$( ".ui-unselecting", this.element[ 0 ] ).each( function() {
13902
			var selectee = $.data( this, "selectable-item" );
13903
			that._removeClass( selectee.$element, "ui-unselecting" );
13904
			selectee.unselecting = false;
13905
			selectee.startselected = false;
13906
			that._trigger( "unselected", event, {
13907
				unselected: selectee.element
13908
			} );
13909
		} );
13910
		$( ".ui-selecting", this.element[ 0 ] ).each( function() {
13911
			var selectee = $.data( this, "selectable-item" );
13912
			that._removeClass( selectee.$element, "ui-selecting" )
13913
				._addClass( selectee.$element, "ui-selected" );
13914
			selectee.selecting = false;
13915
			selectee.selected = true;
13916
			selectee.startselected = true;
13917
			that._trigger( "selected", event, {
13918
				selected: selectee.element
13919
			} );
13920
		} );
13921
		this._trigger( "stop", event );
13922
 
13923
		this.helper.remove();
13924
 
13925
		return false;
13926
	}
13927
 
13928
} );
13929
 
13930
 
13931
/*!
13932
 * jQuery UI Selectmenu 1.14.1
13933
 * https://jqueryui.com
13934
 *
13935
 * Copyright OpenJS Foundation and other contributors
13936
 * Released under the MIT license.
13937
 * https://jquery.org/license
13938
 */
13939
 
13940
//>>label: Selectmenu
13941
//>>group: Widgets
13942
/* eslint-disable max-len */
13943
//>>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.
13944
/* eslint-enable max-len */
13945
//>>docs: https://api.jqueryui.com/selectmenu/
13946
//>>demos: https://jqueryui.com/selectmenu/
13947
//>>css.structure: ../../themes/base/core.css
13948
//>>css.structure: ../../themes/base/selectmenu.css, ../../themes/base/button.css
13949
//>>css.theme: ../../themes/base/theme.css
13950
 
13951
 
13952
var widgetsSelectmenu = $.widget( "ui.selectmenu", [ $.ui.formResetMixin, {
13953
	version: "1.14.1",
13954
	defaultElement: "<select>",
13955
	options: {
13956
		appendTo: null,
13957
		classes: {
13958
			"ui-selectmenu-button-open": "ui-corner-top",
13959
			"ui-selectmenu-button-closed": "ui-corner-all"
13960
		},
13961
		disabled: null,
13962
		icons: {
13963
			button: "ui-icon-triangle-1-s"
13964
		},
13965
		position: {
13966
			my: "left top",
13967
			at: "left bottom",
13968
			collision: "none"
13969
		},
13970
		width: false,
13971
 
13972
		// Callbacks
13973
		change: null,
13974
		close: null,
13975
		focus: null,
13976
		open: null,
13977
		select: null
13978
	},
13979
 
13980
	_create: function() {
13981
		var selectmenuId = this.element.uniqueId().attr( "id" );
13982
		this.ids = {
13983
			element: selectmenuId,
13984
			button: selectmenuId + "-button",
13985
			menu: selectmenuId + "-menu"
13986
		};
13987
 
13988
		this._drawButton();
13989
		this._drawMenu();
13990
		this._bindFormResetHandler();
13991
 
13992
		this._rendered = false;
13993
		this.menuItems = $();
13994
	},
13995
 
13996
	_drawButton: function() {
13997
		var icon,
13998
			that = this,
13999
			item = this._parseOption(
14000
				this.element.find( "option:selected" ),
14001
				this.element[ 0 ].selectedIndex
14002
			);
14003
 
14004
		// Associate existing label with the new button
14005
		this.labels = this.element.labels().attr( "for", this.ids.button );
14006
		this._on( this.labels, {
14007
			click: function( event ) {
14008
				this.button.trigger( "focus" );
14009
				event.preventDefault();
14010
			}
14011
		} );
14012
 
14013
		// Hide original select element
14014
		this.element.hide();
14015
 
14016
		// Create button
14017
		this.button = $( "<span>", {
14018
			tabindex: this.options.disabled ? -1 : 0,
14019
			id: this.ids.button,
14020
			role: "combobox",
14021
			"aria-expanded": "false",
14022
			"aria-autocomplete": "list",
14023
			"aria-owns": this.ids.menu,
14024
			"aria-haspopup": "true",
14025
			title: this.element.attr( "title" )
14026
		} )
14027
			.insertAfter( this.element );
14028
 
14029
		this._addClass( this.button, "ui-selectmenu-button ui-selectmenu-button-closed",
14030
			"ui-button ui-widget" );
14031
 
14032
		icon = $( "<span>" ).appendTo( this.button );
14033
		this._addClass( icon, "ui-selectmenu-icon", "ui-icon " + this.options.icons.button );
14034
		this.buttonItem = this._renderButtonItem( item )
14035
			.appendTo( this.button );
14036
 
14037
		if ( this.options.width !== false ) {
14038
			this._resizeButton();
14039
		}
14040
 
14041
		this._on( this.button, this._buttonEvents );
14042
		this.button.one( "focusin", function() {
14043
 
14044
			// Delay rendering the menu items until the button receives focus.
14045
			// The menu may have already been rendered via a programmatic open.
14046
			if ( !that._rendered ) {
14047
				that._refreshMenu();
14048
			}
14049
		} );
14050
	},
14051
 
14052
	_drawMenu: function() {
14053
		var that = this;
14054
 
14055
		// Create menu
14056
		this.menu = $( "<ul>", {
14057
			"aria-hidden": "true",
14058
			"aria-labelledby": this.ids.button,
14059
			id: this.ids.menu
14060
		} );
14061
 
14062
		// Wrap menu
14063
		this.menuWrap = $( "<div>" ).append( this.menu );
14064
		this._addClass( this.menuWrap, "ui-selectmenu-menu", "ui-front" );
14065
		this.menuWrap.appendTo( this._appendTo() );
14066
 
14067
		// Initialize menu widget
14068
		this.menuInstance = this.menu
14069
			.menu( {
14070
				classes: {
14071
					"ui-menu": "ui-corner-bottom"
14072
				},
14073
				role: "listbox",
14074
				select: function( event, ui ) {
14075
					event.preventDefault();
14076
					that._select( ui.item.data( "ui-selectmenu-item" ), event );
14077
				},
14078
				focus: function( event, ui ) {
14079
					var item = ui.item.data( "ui-selectmenu-item" );
14080
 
14081
					// Prevent inital focus from firing and check if its a newly focused item
14082
					if ( that.focusIndex != null && item.index !== that.focusIndex ) {
14083
						that._trigger( "focus", event, { item: item } );
14084
						if ( !that.isOpen ) {
14085
							that._select( item, event );
14086
						}
14087
					}
14088
					that.focusIndex = item.index;
14089
 
14090
					that.button.attr( "aria-activedescendant",
14091
						that.menuItems.eq( item.index ).attr( "id" ) );
14092
				}
14093
			} )
14094
			.menu( "instance" );
14095
 
14096
		// Don't close the menu on mouseleave
14097
		this.menuInstance._off( this.menu, "mouseleave" );
14098
 
14099
		// Cancel the menu's collapseAll on document click
14100
		this.menuInstance._closeOnDocumentClick = function() {
14101
			return false;
14102
		};
14103
 
14104
		// Selects often contain empty items, but never contain dividers
14105
		this.menuInstance._isDivider = function() {
14106
			return false;
14107
		};
14108
	},
14109
 
14110
	refresh: function() {
14111
		this._refreshMenu();
14112
		this.buttonItem.replaceWith(
14113
			this.buttonItem = this._renderButtonItem(
14114
 
14115
				// Fall back to an empty object in case there are no options
14116
				this._getSelectedItem().data( "ui-selectmenu-item" ) || {}
14117
			)
14118
		);
14119
		if ( this.options.width === null ) {
14120
			this._resizeButton();
14121
		}
14122
	},
14123
 
14124
	_refreshMenu: function() {
14125
		var item,
14126
			options = this.element.find( "option" );
14127
 
14128
		this.menu.empty();
14129
 
14130
		this._parseOptions( options );
14131
		this._renderMenu( this.menu, this.items );
14132
 
14133
		this.menuInstance.refresh();
14134
		this.menuItems = this.menu.find( "li" )
14135
			.not( ".ui-selectmenu-optgroup" )
14136
				.find( ".ui-menu-item-wrapper" );
14137
 
14138
		this._rendered = true;
14139
 
14140
		if ( !options.length ) {
14141
			return;
14142
		}
14143
 
14144
		item = this._getSelectedItem();
14145
 
14146
		// Update the menu to have the correct item focused
14147
		this.menuInstance.focus( null, item );
14148
		this._setAria( item.data( "ui-selectmenu-item" ) );
14149
 
14150
		// Set disabled state
14151
		this._setOption( "disabled", this.element.prop( "disabled" ) );
14152
	},
14153
 
14154
	open: function( event ) {
14155
		if ( this.options.disabled ) {
14156
			return;
14157
		}
14158
 
14159
		// If this is the first time the menu is being opened, render the items
14160
		if ( !this._rendered ) {
14161
			this._refreshMenu();
14162
		} else {
14163
 
14164
			// Menu clears focus on close, reset focus to selected item
14165
			this._removeClass( this.menu.find( ".ui-state-active" ), null, "ui-state-active" );
14166
			this.menuInstance.focus( null, this._getSelectedItem() );
14167
		}
14168
 
14169
		// If there are no options, don't open the menu
14170
		if ( !this.menuItems.length ) {
14171
			return;
14172
		}
14173
 
14174
		this.isOpen = true;
14175
		this._toggleAttr();
14176
		this._resizeMenu();
14177
		this._position();
14178
 
14179
		this._on( this.document, this._documentClick );
14180
 
14181
		this._trigger( "open", event );
14182
	},
14183
 
14184
	_position: function() {
14185
		this.menuWrap.position( $.extend( { of: this.button }, this.options.position ) );
14186
	},
14187
 
14188
	close: function( event ) {
14189
		if ( !this.isOpen ) {
14190
			return;
14191
		}
14192
 
14193
		this.isOpen = false;
14194
		this._toggleAttr();
14195
 
14196
		this.range = null;
14197
		this._off( this.document );
14198
 
14199
		this._trigger( "close", event );
14200
	},
14201
 
14202
	widget: function() {
14203
		return this.button;
14204
	},
14205
 
14206
	menuWidget: function() {
14207
		return this.menu;
14208
	},
14209
 
14210
	_renderButtonItem: function( item ) {
14211
		var buttonItem = $( "<span>" );
14212
 
14213
		this._setText( buttonItem, item.label );
14214
		this._addClass( buttonItem, "ui-selectmenu-text" );
14215
 
14216
		return buttonItem;
14217
	},
14218
 
14219
	_renderMenu: function( ul, items ) {
14220
		var that = this,
14221
			currentOptgroup = "";
14222
 
14223
		$.each( items, function( index, item ) {
14224
			var li;
14225
 
14226
			if ( item.optgroup !== currentOptgroup ) {
14227
				li = $( "<li>", {
14228
					text: item.optgroup
14229
				} );
14230
				that._addClass( li, "ui-selectmenu-optgroup", "ui-menu-divider" +
14231
					( item.element.parent( "optgroup" ).prop( "disabled" ) ?
14232
						" ui-state-disabled" :
14233
						"" ) );
14234
 
14235
				li.appendTo( ul );
14236
 
14237
				currentOptgroup = item.optgroup;
14238
			}
14239
 
14240
			that._renderItemData( ul, item );
14241
		} );
14242
	},
14243
 
14244
	_renderItemData: function( ul, item ) {
14245
		return this._renderItem( ul, item ).data( "ui-selectmenu-item", item );
14246
	},
14247
 
14248
	_renderItem: function( ul, item ) {
14249
		var li = $( "<li>" ),
14250
			wrapper = $( "<div>", {
14251
				title: item.element.attr( "title" )
14252
			} );
14253
 
14254
		if ( item.disabled ) {
14255
			this._addClass( li, null, "ui-state-disabled" );
14256
		}
14257
 
14258
		if ( item.hidden ) {
14259
			li.prop( "hidden", true );
14260
		} else {
14261
			this._setText( wrapper, item.label );
14262
		}
14263
 
14264
		return li.append( wrapper ).appendTo( ul );
14265
	},
14266
 
14267
	_setText: function( element, value ) {
14268
		if ( value ) {
14269
			element.text( value );
14270
		} else {
14271
			element.html( "&#160;" );
14272
		}
14273
	},
14274
 
14275
	_move: function( direction, event ) {
14276
		var item, next,
14277
			filter = ".ui-menu-item";
14278
 
14279
		if ( this.isOpen ) {
14280
			item = this.menuItems.eq( this.focusIndex ).parent( "li" );
14281
		} else {
14282
			item = this.menuItems.eq( this.element[ 0 ].selectedIndex ).parent( "li" );
14283
			filter += ":not(.ui-state-disabled)";
14284
		}
14285
 
14286
		if ( direction === "first" || direction === "last" ) {
14287
			next = item[ direction === "first" ? "prevAll" : "nextAll" ]( filter ).eq( -1 );
14288
		} else {
14289
			next = item[ direction + "All" ]( filter ).eq( 0 );
14290
		}
14291
 
14292
		if ( next.length ) {
14293
			this.menuInstance.focus( event, next );
14294
		}
14295
	},
14296
 
14297
	_getSelectedItem: function() {
14298
		return this.menuItems.eq( this.element[ 0 ].selectedIndex ).parent( "li" );
14299
	},
14300
 
14301
	_toggle: function( event ) {
14302
		this[ this.isOpen ? "close" : "open" ]( event );
14303
	},
14304
 
14305
	_setSelection: function() {
14306
		var selection;
14307
 
14308
		if ( !this.range ) {
14309
			return;
14310
		}
14311
 
14312
		selection = window.getSelection();
14313
		selection.removeAllRanges();
14314
		selection.addRange( this.range );
14315
	},
14316
 
14317
	_documentClick: {
14318
		mousedown: function( event ) {
14319
			if ( !this.isOpen ) {
14320
				return;
14321
			}
14322
 
14323
			if ( !$( event.target ).closest( ".ui-selectmenu-menu, #" +
14324
				CSS.escape( this.ids.button ) ).length ) {
14325
				this.close( event );
14326
			}
14327
		}
14328
	},
14329
 
14330
	_buttonEvents: {
14331
 
14332
		// Prevent text selection from being reset when interacting with the selectmenu (#10144)
14333
		mousedown: function() {
14334
			var selection = window.getSelection();
14335
			if ( selection.rangeCount ) {
14336
				this.range = selection.getRangeAt( 0 );
14337
			}
14338
		},
14339
 
14340
		click: function( event ) {
14341
			this._setSelection();
14342
			this._toggle( event );
14343
		},
14344
 
14345
		keydown: function( event ) {
14346
			var preventDefault = true;
14347
			switch ( event.keyCode ) {
14348
			case $.ui.keyCode.TAB:
14349
			case $.ui.keyCode.ESCAPE:
14350
				this.close( event );
14351
				preventDefault = false;
14352
				break;
14353
			case $.ui.keyCode.ENTER:
14354
				if ( this.isOpen ) {
14355
					this._selectFocusedItem( event );
14356
				}
14357
				break;
14358
			case $.ui.keyCode.UP:
14359
				if ( event.altKey ) {
14360
					this._toggle( event );
14361
				} else {
14362
					this._move( "prev", event );
14363
				}
14364
				break;
14365
			case $.ui.keyCode.DOWN:
14366
				if ( event.altKey ) {
14367
					this._toggle( event );
14368
				} else {
14369
					this._move( "next", event );
14370
				}
14371
				break;
14372
			case $.ui.keyCode.SPACE:
14373
				if ( this.isOpen ) {
14374
					this._selectFocusedItem( event );
14375
				} else {
14376
					this._toggle( event );
14377
				}
14378
				break;
14379
			case $.ui.keyCode.LEFT:
14380
				this._move( "prev", event );
14381
				break;
14382
			case $.ui.keyCode.RIGHT:
14383
				this._move( "next", event );
14384
				break;
14385
			case $.ui.keyCode.HOME:
14386
			case $.ui.keyCode.PAGE_UP:
14387
				this._move( "first", event );
14388
				break;
14389
			case $.ui.keyCode.END:
14390
			case $.ui.keyCode.PAGE_DOWN:
14391
				this._move( "last", event );
14392
				break;
14393
			default:
14394
				this.menu.trigger( event );
14395
				preventDefault = false;
14396
			}
14397
 
14398
			if ( preventDefault ) {
14399
				event.preventDefault();
14400
			}
14401
		}
14402
	},
14403
 
14404
	_selectFocusedItem: function( event ) {
14405
		var item = this.menuItems.eq( this.focusIndex ).parent( "li" );
14406
		if ( !item.hasClass( "ui-state-disabled" ) ) {
14407
			this._select( item.data( "ui-selectmenu-item" ), event );
14408
		}
14409
	},
14410
 
14411
	_select: function( item, event ) {
14412
		var oldIndex = this.element[ 0 ].selectedIndex;
14413
 
14414
		// Change native select element
14415
		this.element[ 0 ].selectedIndex = item.index;
14416
		this.buttonItem.replaceWith( this.buttonItem = this._renderButtonItem( item ) );
14417
		this._setAria( item );
14418
		this._trigger( "select", event, { item: item } );
14419
 
14420
		if ( item.index !== oldIndex ) {
14421
			this._trigger( "change", event, { item: item } );
14422
		}
14423
 
14424
		this.close( event );
14425
	},
14426
 
14427
	_setAria: function( item ) {
14428
		var id = this.menuItems.eq( item.index ).attr( "id" );
14429
 
14430
		this.button.attr( {
14431
			"aria-labelledby": id,
14432
			"aria-activedescendant": id
14433
		} );
14434
		this.menu.attr( "aria-activedescendant", id );
14435
	},
14436
 
14437
	_setOption: function( key, value ) {
14438
		if ( key === "icons" ) {
14439
			var icon = this.button.find( "span.ui-icon" );
14440
			this._removeClass( icon, null, this.options.icons.button )
14441
				._addClass( icon, null, value.button );
14442
		}
14443
 
14444
		this._super( key, value );
14445
 
14446
		if ( key === "appendTo" ) {
14447
			this.menuWrap.appendTo( this._appendTo() );
14448
		}
14449
 
14450
		if ( key === "width" ) {
14451
			this._resizeButton();
14452
		}
14453
	},
14454
 
14455
	_setOptionDisabled: function( value ) {
14456
		this._super( value );
14457
 
14458
		this.menuInstance.option( "disabled", value );
14459
		this.button.attr( "aria-disabled", value );
14460
		this._toggleClass( this.button, null, "ui-state-disabled", value );
14461
 
14462
		this.element.prop( "disabled", value );
14463
		if ( value ) {
14464
			this.button.attr( "tabindex", -1 );
14465
			this.close();
14466
		} else {
14467
			this.button.attr( "tabindex", 0 );
14468
		}
14469
	},
14470
 
14471
	_appendTo: function() {
14472
		var element = this.options.appendTo;
14473
 
14474
		if ( element ) {
14475
			element = element.jquery || element.nodeType ?
14476
				$( element ) :
14477
				this.document.find( element ).eq( 0 );
14478
		}
14479
 
14480
		if ( !element || !element[ 0 ] ) {
14481
			element = this.element.closest( ".ui-front, dialog" );
14482
		}
14483
 
14484
		if ( !element.length ) {
14485
			element = this.document[ 0 ].body;
14486
		}
14487
 
14488
		return element;
14489
	},
14490
 
14491
	_toggleAttr: function() {
14492
		this.button.attr( "aria-expanded", this.isOpen );
14493
 
14494
		// We can't use two _toggleClass() calls here, because we need to make sure
14495
		// we always remove classes first and add them second, otherwise if both classes have the
14496
		// same theme class, it will be removed after we add it.
14497
		this._removeClass( this.button, "ui-selectmenu-button-" +
14498
			( this.isOpen ? "closed" : "open" ) )
14499
			._addClass( this.button, "ui-selectmenu-button-" +
14500
				( this.isOpen ? "open" : "closed" ) )
14501
			._toggleClass( this.menuWrap, "ui-selectmenu-open", null, this.isOpen );
14502
 
14503
		this.menu.attr( "aria-hidden", !this.isOpen );
14504
	},
14505
 
14506
	_resizeButton: function() {
14507
		var width = this.options.width;
14508
 
14509
		// For `width: false`, just remove inline style and stop
14510
		if ( width === false ) {
14511
			this.button.css( "width", "" );
14512
			return;
14513
		}
14514
 
14515
		// For `width: null`, match the width of the original element
14516
		if ( width === null ) {
14517
			width = this.element.show().outerWidth();
14518
			this.element.hide();
14519
		}
14520
 
14521
		this.button.outerWidth( width );
14522
	},
14523
 
14524
	_resizeMenu: function() {
14525
		this.menu.outerWidth( Math.max(
14526
			this.button.outerWidth(),
14527
			this.menu.width( "" ).outerWidth()
14528
		) );
14529
	},
14530
 
14531
	_getCreateOptions: function() {
14532
		var options = this._super();
14533
 
14534
		options.disabled = this.element.prop( "disabled" );
14535
 
14536
		return options;
14537
	},
14538
 
14539
	_parseOptions: function( options ) {
14540
		var that = this,
14541
			data = [];
14542
		options.each( function( index, item ) {
14543
			data.push( that._parseOption( $( item ), index ) );
14544
		} );
14545
		this.items = data;
14546
	},
14547
 
14548
	_parseOption: function( option, index ) {
14549
		var optgroup = option.parent( "optgroup" );
14550
 
14551
		return {
14552
			element: option,
14553
			index: index,
14554
			value: option.val(),
14555
			label: option.text(),
14556
			hidden: optgroup.prop( "hidden" ) || option.prop( "hidden" ),
14557
			optgroup: optgroup.attr( "label" ) || "",
14558
			disabled: optgroup.prop( "disabled" ) || option.prop( "disabled" )
14559
		};
14560
	},
14561
 
14562
	_destroy: function() {
14563
		this._unbindFormResetHandler();
14564
		this.menuWrap.remove();
14565
		this.button.remove();
14566
		this.element.show();
14567
		this.element.removeUniqueId();
14568
		this.labels.attr( "for", this.ids.element );
14569
	}
14570
} ] );
14571
 
14572
 
14573
/*!
14574
 * jQuery UI Slider 1.14.1
14575
 * https://jqueryui.com
14576
 *
14577
 * Copyright OpenJS Foundation and other contributors
14578
 * Released under the MIT license.
14579
 * https://jquery.org/license
14580
 */
14581
 
14582
//>>label: Slider
14583
//>>group: Widgets
14584
//>>description: Displays a flexible slider with ranges and accessibility via keyboard.
14585
//>>docs: https://api.jqueryui.com/slider/
14586
//>>demos: https://jqueryui.com/slider/
14587
//>>css.structure: ../../themes/base/core.css
14588
//>>css.structure: ../../themes/base/slider.css
14589
//>>css.theme: ../../themes/base/theme.css
14590
 
14591
 
14592
var widgetsSlider = $.widget( "ui.slider", $.ui.mouse, {
14593
	version: "1.14.1",
14594
	widgetEventPrefix: "slide",
14595
 
14596
	options: {
14597
		animate: false,
14598
		classes: {
14599
			"ui-slider": "ui-corner-all",
14600
			"ui-slider-handle": "ui-corner-all",
14601
 
14602
			// Note: ui-widget-header isn't the most fittingly semantic framework class for this
14603
			// element, but worked best visually with a variety of themes
14604
			"ui-slider-range": "ui-corner-all ui-widget-header"
14605
		},
14606
		distance: 0,
14607
		max: 100,
14608
		min: 0,
14609
		orientation: "horizontal",
14610
		range: false,
14611
		step: 1,
14612
		value: 0,
14613
		values: null,
14614
 
14615
		// Callbacks
14616
		change: null,
14617
		slide: null,
14618
		start: null,
14619
		stop: null
14620
	},
14621
 
14622
	// Number of pages in a slider
14623
	// (how many times can you page up/down to go through the whole range)
14624
	numPages: 5,
14625
 
14626
	_create: function() {
14627
		this._keySliding = false;
14628
		this._mouseSliding = false;
14629
		this._animateOff = true;
14630
		this._handleIndex = null;
14631
		this._detectOrientation();
14632
		this._mouseInit();
14633
		this._calculateNewMax();
14634
 
14635
		this._addClass( "ui-slider ui-slider-" + this.orientation,
14636
			"ui-widget ui-widget-content" );
14637
 
14638
		this._refresh();
14639
 
14640
		this._animateOff = false;
14641
	},
14642
 
14643
	_refresh: function() {
14644
		this._createRange();
14645
		this._createHandles();
14646
		this._setupEvents();
14647
		this._refreshValue();
14648
	},
14649
 
14650
	_createHandles: function() {
14651
		var i, handleCount,
14652
			options = this.options,
14653
			existingHandles = this.element.find( ".ui-slider-handle" ),
14654
			handle = "<span tabindex='0'></span>",
14655
			handles = [];
14656
 
14657
		handleCount = ( options.values && options.values.length ) || 1;
14658
 
14659
		if ( existingHandles.length > handleCount ) {
14660
			existingHandles.slice( handleCount ).remove();
14661
			existingHandles = existingHandles.slice( 0, handleCount );
14662
		}
14663
 
14664
		for ( i = existingHandles.length; i < handleCount; i++ ) {
14665
			handles.push( handle );
14666
		}
14667
 
14668
		this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) );
14669
 
14670
		this._addClass( this.handles, "ui-slider-handle", "ui-state-default" );
14671
 
14672
		this.handle = this.handles.eq( 0 );
14673
 
14674
		this.handles.each( function( i ) {
14675
			$( this )
14676
				.data( "ui-slider-handle-index", i )
14677
				.attr( "tabIndex", 0 );
14678
		} );
14679
	},
14680
 
14681
	_createRange: function() {
14682
		var options = this.options;
14683
 
14684
		if ( options.range ) {
14685
			if ( options.range === true ) {
14686
				if ( !options.values ) {
14687
					options.values = [ this._valueMin(), this._valueMin() ];
14688
				} else if ( options.values.length && options.values.length !== 2 ) {
14689
					options.values = [ options.values[ 0 ], options.values[ 0 ] ];
14690
				} else if ( Array.isArray( options.values ) ) {
14691
					options.values = options.values.slice( 0 );
14692
				}
14693
			}
14694
 
14695
			if ( !this.range || !this.range.length ) {
14696
				this.range = $( "<div>" )
14697
					.appendTo( this.element );
14698
 
14699
				this._addClass( this.range, "ui-slider-range" );
14700
			} else {
14701
				this._removeClass( this.range, "ui-slider-range-min ui-slider-range-max" );
14702
 
14703
				// Handle range switching from true to min/max
14704
				this.range.css( {
14705
					"left": "",
14706
					"bottom": ""
14707
				} );
14708
			}
14709
			if ( options.range === "min" || options.range === "max" ) {
14710
				this._addClass( this.range, "ui-slider-range-" + options.range );
14711
			}
14712
		} else {
14713
			if ( this.range ) {
14714
				this.range.remove();
14715
			}
14716
			this.range = null;
14717
		}
14718
	},
14719
 
14720
	_setupEvents: function() {
14721
		this._off( this.handles );
14722
		this._on( this.handles, this._handleEvents );
14723
		this._hoverable( this.handles );
14724
		this._focusable( this.handles );
14725
	},
14726
 
14727
	_destroy: function() {
14728
		this.handles.remove();
14729
		if ( this.range ) {
14730
			this.range.remove();
14731
		}
14732
 
14733
		this._mouseDestroy();
14734
	},
14735
 
14736
	_mouseCapture: function( event ) {
14737
		var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle,
14738
			that = this,
14739
			o = this.options;
14740
 
14741
		if ( o.disabled ) {
14742
			return false;
14743
		}
14744
 
14745
		this.elementSize = {
14746
			width: this.element.outerWidth(),
14747
			height: this.element.outerHeight()
14748
		};
14749
		this.elementOffset = this.element.offset();
14750
 
14751
		position = { x: event.pageX, y: event.pageY };
14752
		normValue = this._normValueFromMouse( position );
14753
		distance = this._valueMax() - this._valueMin() + 1;
14754
		this.handles.each( function( i ) {
14755
			var thisDistance = Math.abs( normValue - that.values( i ) );
14756
			if ( ( distance > thisDistance ) ||
14757
				( distance === thisDistance &&
14758
					( i === that._lastChangedValue || that.values( i ) === o.min ) ) ) {
14759
				distance = thisDistance;
14760
				closestHandle = $( this );
14761
				index = i;
14762
			}
14763
		} );
14764
 
14765
		allowed = this._start( event, index );
14766
		if ( allowed === false ) {
14767
			return false;
14768
		}
14769
		this._mouseSliding = true;
14770
 
14771
		this._handleIndex = index;
14772
 
14773
		this._addClass( closestHandle, null, "ui-state-active" );
14774
		closestHandle.trigger( "focus" );
14775
 
14776
		offset = closestHandle.offset();
14777
		mouseOverHandle = !$( event.target ).parents().addBack().is( ".ui-slider-handle" );
14778
		this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
14779
			left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
14780
			top: event.pageY - offset.top -
14781
				( closestHandle.height() / 2 ) -
14782
				( parseInt( closestHandle.css( "borderTopWidth" ), 10 ) || 0 ) -
14783
				( parseInt( closestHandle.css( "borderBottomWidth" ), 10 ) || 0 ) +
14784
				( parseInt( closestHandle.css( "marginTop" ), 10 ) || 0 )
14785
		};
14786
 
14787
		if ( !this.handles.hasClass( "ui-state-hover" ) ) {
14788
			this._slide( event, index, normValue );
14789
		}
14790
		this._animateOff = true;
14791
		return true;
14792
	},
14793
 
14794
	_mouseStart: function() {
14795
		return true;
14796
	},
14797
 
14798
	_mouseDrag: function( event ) {
14799
		var position = { x: event.pageX, y: event.pageY },
14800
			normValue = this._normValueFromMouse( position );
14801
 
14802
		this._slide( event, this._handleIndex, normValue );
14803
 
14804
		return false;
14805
	},
14806
 
14807
	_mouseStop: function( event ) {
14808
		this._removeClass( this.handles, null, "ui-state-active" );
14809
		this._mouseSliding = false;
14810
 
14811
		this._stop( event, this._handleIndex );
14812
		this._change( event, this._handleIndex );
14813
 
14814
		this._handleIndex = null;
14815
		this._clickOffset = null;
14816
		this._animateOff = false;
14817
 
14818
		return false;
14819
	},
14820
 
14821
	_detectOrientation: function() {
14822
		this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
14823
	},
14824
 
14825
	_normValueFromMouse: function( position ) {
14826
		var pixelTotal,
14827
			pixelMouse,
14828
			percentMouse,
14829
			valueTotal,
14830
			valueMouse;
14831
 
14832
		if ( this.orientation === "horizontal" ) {
14833
			pixelTotal = this.elementSize.width;
14834
			pixelMouse = position.x - this.elementOffset.left -
14835
				( this._clickOffset ? this._clickOffset.left : 0 );
14836
		} else {
14837
			pixelTotal = this.elementSize.height;
14838
			pixelMouse = position.y - this.elementOffset.top -
14839
				( this._clickOffset ? this._clickOffset.top : 0 );
14840
		}
14841
 
14842
		percentMouse = ( pixelMouse / pixelTotal );
14843
		if ( percentMouse > 1 ) {
14844
			percentMouse = 1;
14845
		}
14846
		if ( percentMouse < 0 ) {
14847
			percentMouse = 0;
14848
		}
14849
		if ( this.orientation === "vertical" ) {
14850
			percentMouse = 1 - percentMouse;
14851
		}
14852
 
14853
		valueTotal = this._valueMax() - this._valueMin();
14854
		valueMouse = this._valueMin() + percentMouse * valueTotal;
14855
 
14856
		return this._trimAlignValue( valueMouse );
14857
	},
14858
 
14859
	_uiHash: function( index, value, values ) {
14860
		var uiHash = {
14861
			handle: this.handles[ index ],
14862
			handleIndex: index,
14863
			value: value !== undefined ? value : this.value()
14864
		};
14865
 
14866
		if ( this._hasMultipleValues() ) {
14867
			uiHash.value = value !== undefined ? value : this.values( index );
14868
			uiHash.values = values || this.values();
14869
		}
14870
 
14871
		return uiHash;
14872
	},
14873
 
14874
	_hasMultipleValues: function() {
14875
		return this.options.values && this.options.values.length;
14876
	},
14877
 
14878
	_start: function( event, index ) {
14879
		return this._trigger( "start", event, this._uiHash( index ) );
14880
	},
14881
 
14882
	_slide: function( event, index, newVal ) {
14883
		var allowed, otherVal,
14884
			currentValue = this.value(),
14885
			newValues = this.values();
14886
 
14887
		if ( this._hasMultipleValues() ) {
14888
			otherVal = this.values( index ? 0 : 1 );
14889
			currentValue = this.values( index );
14890
 
14891
			if ( this.options.values.length === 2 && this.options.range === true ) {
14892
				newVal =  index === 0 ? Math.min( otherVal, newVal ) : Math.max( otherVal, newVal );
14893
			}
14894
 
14895
			newValues[ index ] = newVal;
14896
		}
14897
 
14898
		if ( newVal === currentValue ) {
14899
			return;
14900
		}
14901
 
14902
		allowed = this._trigger( "slide", event, this._uiHash( index, newVal, newValues ) );
14903
 
14904
		// A slide can be canceled by returning false from the slide callback
14905
		if ( allowed === false ) {
14906
			return;
14907
		}
14908
 
14909
		if ( this._hasMultipleValues() ) {
14910
			this.values( index, newVal );
14911
		} else {
14912
			this.value( newVal );
14913
		}
14914
	},
14915
 
14916
	_stop: function( event, index ) {
14917
		this._trigger( "stop", event, this._uiHash( index ) );
14918
	},
14919
 
14920
	_change: function( event, index ) {
14921
		if ( !this._keySliding && !this._mouseSliding ) {
14922
 
14923
			//store the last changed value index for reference when handles overlap
14924
			this._lastChangedValue = index;
14925
			this._trigger( "change", event, this._uiHash( index ) );
14926
		}
14927
	},
14928
 
14929
	value: function( newValue ) {
14930
		if ( arguments.length ) {
14931
			this.options.value = this._trimAlignValue( newValue );
14932
			this._refreshValue();
14933
			this._change( null, 0 );
14934
			return;
14935
		}
14936
 
14937
		return this._value();
14938
	},
14939
 
14940
	values: function( index, newValue ) {
14941
		var vals,
14942
			newValues,
14943
			i;
14944
 
14945
		if ( arguments.length > 1 ) {
14946
			this.options.values[ index ] = this._trimAlignValue( newValue );
14947
			this._refreshValue();
14948
			this._change( null, index );
14949
			return;
14950
		}
14951
 
14952
		if ( arguments.length ) {
14953
			if ( Array.isArray( arguments[ 0 ] ) ) {
14954
				vals = this.options.values;
14955
				newValues = arguments[ 0 ];
14956
				for ( i = 0; i < vals.length; i += 1 ) {
14957
					vals[ i ] = this._trimAlignValue( newValues[ i ] );
14958
					this._change( null, i );
14959
				}
14960
				this._refreshValue();
14961
			} else {
14962
				if ( this._hasMultipleValues() ) {
14963
					return this._values( index );
14964
				} else {
14965
					return this.value();
14966
				}
14967
			}
14968
		} else {
14969
			return this._values();
14970
		}
14971
	},
14972
 
14973
	_setOption: function( key, value ) {
14974
		var i,
14975
			valsLength = 0;
14976
 
14977
		if ( key === "range" && this.options.range === true ) {
14978
			if ( value === "min" ) {
14979
				this.options.value = this._values( 0 );
14980
				this.options.values = null;
14981
			} else if ( value === "max" ) {
14982
				this.options.value = this._values( this.options.values.length - 1 );
14983
				this.options.values = null;
14984
			}
14985
		}
14986
 
14987
		if ( Array.isArray( this.options.values ) ) {
14988
			valsLength = this.options.values.length;
14989
		}
14990
 
14991
		this._super( key, value );
14992
 
14993
		switch ( key ) {
14994
			case "orientation":
14995
				this._detectOrientation();
14996
				this._removeClass( "ui-slider-horizontal ui-slider-vertical" )
14997
					._addClass( "ui-slider-" + this.orientation );
14998
				this._refreshValue();
14999
				if ( this.options.range ) {
15000
					this._refreshRange( value );
15001
				}
15002
 
15003
				// Reset positioning from previous orientation
15004
				this.handles.css( value === "horizontal" ? "bottom" : "left", "" );
15005
				break;
15006
			case "value":
15007
				this._animateOff = true;
15008
				this._refreshValue();
15009
				this._change( null, 0 );
15010
				this._animateOff = false;
15011
				break;
15012
			case "values":
15013
				this._animateOff = true;
15014
				this._refreshValue();
15015
 
15016
				// Start from the last handle to prevent unreachable handles (#9046)
15017
				for ( i = valsLength - 1; i >= 0; i-- ) {
15018
					this._change( null, i );
15019
				}
15020
				this._animateOff = false;
15021
				break;
15022
			case "step":
15023
			case "min":
15024
			case "max":
15025
				this._animateOff = true;
15026
				this._calculateNewMax();
15027
				this._refreshValue();
15028
				this._animateOff = false;
15029
				break;
15030
			case "range":
15031
				this._animateOff = true;
15032
				this._refresh();
15033
				this._animateOff = false;
15034
				break;
15035
		}
15036
	},
15037
 
15038
	_setOptionDisabled: function( value ) {
15039
		this._super( value );
15040
 
15041
		this._toggleClass( null, "ui-state-disabled", !!value );
15042
	},
15043
 
15044
	//internal value getter
15045
	// _value() returns value trimmed by min and max, aligned by step
15046
	_value: function() {
15047
		var val = this.options.value;
15048
		val = this._trimAlignValue( val );
15049
 
15050
		return val;
15051
	},
15052
 
15053
	//internal values getter
15054
	// _values() returns array of values trimmed by min and max, aligned by step
15055
	// _values( index ) returns single value trimmed by min and max, aligned by step
15056
	_values: function( index ) {
15057
		var val,
15058
			vals,
15059
			i;
15060
 
15061
		if ( arguments.length ) {
15062
			val = this.options.values[ index ];
15063
			val = this._trimAlignValue( val );
15064
 
15065
			return val;
15066
		} else if ( this._hasMultipleValues() ) {
15067
 
15068
			// .slice() creates a copy of the array
15069
			// this copy gets trimmed by min and max and then returned
15070
			vals = this.options.values.slice();
15071
			for ( i = 0; i < vals.length; i += 1 ) {
15072
				vals[ i ] = this._trimAlignValue( vals[ i ] );
15073
			}
15074
 
15075
			return vals;
15076
		} else {
15077
			return [];
15078
		}
15079
	},
15080
 
15081
	// Returns the step-aligned value that val is closest to, between (inclusive) min and max
15082
	_trimAlignValue: function( val ) {
15083
		if ( val <= this._valueMin() ) {
15084
			return this._valueMin();
15085
		}
15086
		if ( val >= this._valueMax() ) {
15087
			return this._valueMax();
15088
		}
15089
		var step = ( this.options.step > 0 ) ? this.options.step : 1,
15090
			valModStep = ( val - this._valueMin() ) % step,
15091
			alignValue = val - valModStep;
15092
 
15093
		if ( Math.abs( valModStep ) * 2 >= step ) {
15094
			alignValue += ( valModStep > 0 ) ? step : ( -step );
15095
		}
15096
 
15097
		// Since JavaScript has problems with large floats, round
15098
		// the final value to 5 digits after the decimal point (see #4124)
15099
		return parseFloat( alignValue.toFixed( 5 ) );
15100
	},
15101
 
15102
	_calculateNewMax: function() {
15103
		var max = this.options.max,
15104
			min = this._valueMin(),
15105
			step = this.options.step,
15106
			aboveMin = Math.round( ( max - min ) / step ) * step;
15107
		max = aboveMin + min;
15108
		if ( max > this.options.max ) {
15109
 
15110
			//If max is not divisible by step, rounding off may increase its value
15111
			max -= step;
15112
		}
15113
		this.max = parseFloat( max.toFixed( this._precision() ) );
15114
	},
15115
 
15116
	_precision: function() {
15117
		var precision = this._precisionOf( this.options.step );
15118
		if ( this.options.min !== null ) {
15119
			precision = Math.max( precision, this._precisionOf( this.options.min ) );
15120
		}
15121
		return precision;
15122
	},
15123
 
15124
	_precisionOf: function( num ) {
15125
		var str = num.toString(),
15126
			decimal = str.indexOf( "." );
15127
		return decimal === -1 ? 0 : str.length - decimal - 1;
15128
	},
15129
 
15130
	_valueMin: function() {
15131
		return this.options.min;
15132
	},
15133
 
15134
	_valueMax: function() {
15135
		return this.max;
15136
	},
15137
 
15138
	_refreshRange: function( orientation ) {
15139
		if ( orientation === "vertical" ) {
15140
			this.range.css( { "width": "", "left": "" } );
15141
		}
15142
		if ( orientation === "horizontal" ) {
15143
			this.range.css( { "height": "", "bottom": "" } );
15144
		}
15145
	},
15146
 
15147
	_refreshValue: function() {
15148
		var lastValPercent, valPercent, value, valueMin, valueMax,
15149
			oRange = this.options.range,
15150
			o = this.options,
15151
			that = this,
15152
			animate = ( !this._animateOff ) ? o.animate : false,
15153
			_set = {};
15154
 
15155
		if ( this._hasMultipleValues() ) {
15156
			this.handles.each( function( i ) {
15157
				valPercent = ( that.values( i ) - that._valueMin() ) / ( that._valueMax() -
15158
					that._valueMin() ) * 100;
15159
				_set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
15160
				$( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
15161
				if ( that.options.range === true ) {
15162
					if ( that.orientation === "horizontal" ) {
15163
						if ( i === 0 ) {
15164
							that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
15165
								left: valPercent + "%"
15166
							}, o.animate );
15167
						}
15168
						if ( i === 1 ) {
15169
							that.range[ animate ? "animate" : "css" ]( {
15170
								width: ( valPercent - lastValPercent ) + "%"
15171
							}, {
15172
								queue: false,
15173
								duration: o.animate
15174
							} );
15175
						}
15176
					} else {
15177
						if ( i === 0 ) {
15178
							that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
15179
								bottom: ( valPercent ) + "%"
15180
							}, o.animate );
15181
						}
15182
						if ( i === 1 ) {
15183
							that.range[ animate ? "animate" : "css" ]( {
15184
								height: ( valPercent - lastValPercent ) + "%"
15185
							}, {
15186
								queue: false,
15187
								duration: o.animate
15188
							} );
15189
						}
15190
					}
15191
				}
15192
				lastValPercent = valPercent;
15193
			} );
15194
		} else {
15195
			value = this.value();
15196
			valueMin = this._valueMin();
15197
			valueMax = this._valueMax();
15198
			valPercent = ( valueMax !== valueMin ) ?
15199
					( value - valueMin ) / ( valueMax - valueMin ) * 100 :
15200
					0;
15201
			_set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
15202
			this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
15203
 
15204
			if ( oRange === "min" && this.orientation === "horizontal" ) {
15205
				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
15206
					width: valPercent + "%"
15207
				}, o.animate );
15208
			}
15209
			if ( oRange === "max" && this.orientation === "horizontal" ) {
15210
				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
15211
					width: ( 100 - valPercent ) + "%"
15212
				}, o.animate );
15213
			}
15214
			if ( oRange === "min" && this.orientation === "vertical" ) {
15215
				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
15216
					height: valPercent + "%"
15217
				}, o.animate );
15218
			}
15219
			if ( oRange === "max" && this.orientation === "vertical" ) {
15220
				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
15221
					height: ( 100 - valPercent ) + "%"
15222
				}, o.animate );
15223
			}
15224
		}
15225
	},
15226
 
15227
	_handleEvents: {
15228
		keydown: function( event ) {
15229
			var allowed, curVal, newVal, step,
15230
				index = $( event.target ).data( "ui-slider-handle-index" );
15231
 
15232
			switch ( event.keyCode ) {
15233
				case $.ui.keyCode.HOME:
15234
				case $.ui.keyCode.END:
15235
				case $.ui.keyCode.PAGE_UP:
15236
				case $.ui.keyCode.PAGE_DOWN:
15237
				case $.ui.keyCode.UP:
15238
				case $.ui.keyCode.RIGHT:
15239
				case $.ui.keyCode.DOWN:
15240
				case $.ui.keyCode.LEFT:
15241
					event.preventDefault();
15242
					if ( !this._keySliding ) {
15243
						this._keySliding = true;
15244
						this._addClass( $( event.target ), null, "ui-state-active" );
15245
						allowed = this._start( event, index );
15246
						if ( allowed === false ) {
15247
							return;
15248
						}
15249
					}
15250
					break;
15251
			}
15252
 
15253
			step = this.options.step;
15254
			if ( this._hasMultipleValues() ) {
15255
				curVal = newVal = this.values( index );
15256
			} else {
15257
				curVal = newVal = this.value();
15258
			}
15259
 
15260
			switch ( event.keyCode ) {
15261
				case $.ui.keyCode.HOME:
15262
					newVal = this._valueMin();
15263
					break;
15264
				case $.ui.keyCode.END:
15265
					newVal = this._valueMax();
15266
					break;
15267
				case $.ui.keyCode.PAGE_UP:
15268
					newVal = this._trimAlignValue(
15269
						curVal + ( ( this._valueMax() - this._valueMin() ) / this.numPages )
15270
					);
15271
					break;
15272
				case $.ui.keyCode.PAGE_DOWN:
15273
					newVal = this._trimAlignValue(
15274
						curVal - ( ( this._valueMax() - this._valueMin() ) / this.numPages ) );
15275
					break;
15276
				case $.ui.keyCode.UP:
15277
				case $.ui.keyCode.RIGHT:
15278
					if ( curVal === this._valueMax() ) {
15279
						return;
15280
					}
15281
					newVal = this._trimAlignValue( curVal + step );
15282
					break;
15283
				case $.ui.keyCode.DOWN:
15284
				case $.ui.keyCode.LEFT:
15285
					if ( curVal === this._valueMin() ) {
15286
						return;
15287
					}
15288
					newVal = this._trimAlignValue( curVal - step );
15289
					break;
15290
			}
15291
 
15292
			this._slide( event, index, newVal );
15293
		},
15294
		keyup: function( event ) {
15295
			var index = $( event.target ).data( "ui-slider-handle-index" );
15296
 
15297
			if ( this._keySliding ) {
15298
				this._keySliding = false;
15299
				this._stop( event, index );
15300
				this._change( event, index );
15301
				this._removeClass( $( event.target ), null, "ui-state-active" );
15302
			}
15303
		}
15304
	}
15305
} );
15306
 
15307
 
15308
/*!
15309
 * jQuery UI Sortable 1.14.1
15310
 * https://jqueryui.com
15311
 *
15312
 * Copyright OpenJS Foundation and other contributors
15313
 * Released under the MIT license.
15314
 * https://jquery.org/license
15315
 */
15316
 
15317
//>>label: Sortable
15318
//>>group: Interactions
15319
//>>description: Enables items in a list to be sorted using the mouse.
15320
//>>docs: https://api.jqueryui.com/sortable/
15321
//>>demos: https://jqueryui.com/sortable/
15322
//>>css.structure: ../../themes/base/sortable.css
15323
 
15324
 
15325
var widgetsSortable = $.widget( "ui.sortable", $.ui.mouse, {
15326
	version: "1.14.1",
15327
	widgetEventPrefix: "sort",
15328
	ready: false,
15329
	options: {
15330
		appendTo: "parent",
15331
		axis: false,
15332
		connectWith: false,
15333
		containment: false,
15334
		cursor: "auto",
15335
		cursorAt: false,
15336
		dropOnEmpty: true,
15337
		forcePlaceholderSize: false,
15338
		forceHelperSize: false,
15339
		grid: false,
15340
		handle: false,
15341
		helper: "original",
15342
		items: "> *",
15343
		opacity: false,
15344
		placeholder: false,
15345
		revert: false,
15346
		scroll: true,
15347
		scrollSensitivity: 20,
15348
		scrollSpeed: 20,
15349
		scope: "default",
15350
		tolerance: "intersect",
15351
		zIndex: 1000,
15352
 
15353
		// Callbacks
15354
		activate: null,
15355
		beforeStop: null,
15356
		change: null,
15357
		deactivate: null,
15358
		out: null,
15359
		over: null,
15360
		receive: null,
15361
		remove: null,
15362
		sort: null,
15363
		start: null,
15364
		stop: null,
15365
		update: null
15366
	},
15367
 
15368
	_isOverAxis: function( x, reference, size ) {
15369
		return ( x >= reference ) && ( x < ( reference + size ) );
15370
	},
15371
 
15372
	_isFloating: function( item ) {
15373
		return ( /left|right/ ).test( item.css( "float" ) ) ||
15374
			( /inline|table-cell/ ).test( item.css( "display" ) );
15375
	},
15376
 
15377
	_create: function() {
15378
		this.containerCache = {};
15379
		this._addClass( "ui-sortable" );
15380
 
15381
		//Get the items
15382
		this.refresh();
15383
 
15384
		//Let's determine the parent's offset
15385
		this.offset = this.element.offset();
15386
 
15387
		//Initialize mouse events for interaction
15388
		this._mouseInit();
15389
 
15390
		this._setHandleClassName();
15391
 
15392
		//We're ready to go
15393
		this.ready = true;
15394
 
15395
	},
15396
 
15397
	_setOption: function( key, value ) {
15398
		this._super( key, value );
15399
 
15400
		if ( key === "handle" ) {
15401
			this._setHandleClassName();
15402
		}
15403
	},
15404
 
15405
	_setHandleClassName: function() {
15406
		var that = this;
15407
		this._removeClass( this.element.find( ".ui-sortable-handle" ), "ui-sortable-handle" );
15408
		$.each( this.items, function() {
15409
			that._addClass(
15410
				this.instance.options.handle ?
15411
					this.item.find( this.instance.options.handle ) :
15412
					this.item,
15413
				"ui-sortable-handle"
15414
			);
15415
		} );
15416
	},
15417
 
15418
	_destroy: function() {
15419
		this._mouseDestroy();
15420
 
15421
		for ( var i = this.items.length - 1; i >= 0; i-- ) {
15422
			this.items[ i ].item.removeData( this.widgetName + "-item" );
15423
		}
15424
 
15425
		return this;
15426
	},
15427
 
15428
	_mouseCapture: function( event, overrideHandle ) {
15429
		var currentItem = null,
15430
			validHandle = false,
15431
			that = this;
15432
 
15433
		if ( this.reverting ) {
15434
			return false;
15435
		}
15436
 
15437
		if ( this.options.disabled || this.options.type === "static" ) {
15438
			return false;
15439
		}
15440
 
15441
		//We have to refresh the items data once first
15442
		this._refreshItems( event );
15443
 
15444
		//Find out if the clicked node (or one of its parents) is a actual item in this.items
15445
		$( event.target ).parents().each( function() {
15446
			if ( $.data( this, that.widgetName + "-item" ) === that ) {
15447
				currentItem = $( this );
15448
				return false;
15449
			}
15450
		} );
15451
		if ( $.data( event.target, that.widgetName + "-item" ) === that ) {
15452
			currentItem = $( event.target );
15453
		}
15454
 
15455
		if ( !currentItem ) {
15456
			return false;
15457
		}
15458
		if ( this.options.handle && !overrideHandle ) {
15459
			$( this.options.handle, currentItem ).find( "*" ).addBack().each( function() {
15460
				if ( this === event.target ) {
15461
					validHandle = true;
15462
				}
15463
			} );
15464
			if ( !validHandle ) {
15465
				return false;
15466
			}
15467
		}
15468
 
15469
		this.currentItem = currentItem;
15470
		this._removeCurrentsFromItems();
15471
		return true;
15472
 
15473
	},
15474
 
15475
	_mouseStart: function( event, overrideHandle, noActivation ) {
15476
 
15477
		var i, body,
15478
			o = this.options;
15479
 
15480
		this.currentContainer = this;
15481
 
15482
		//We only need to call refreshPositions, because the refreshItems call has been moved to
15483
		// mouseCapture
15484
		this.refreshPositions();
15485
 
15486
		//Prepare the dragged items parent
15487
		this.appendTo = $( o.appendTo !== "parent" ?
15488
				o.appendTo :
15489
				this.currentItem.parent() );
15490
 
15491
		//Create and append the visible helper
15492
		this.helper = this._createHelper( event );
15493
 
15494
		//Cache the helper size
15495
		this._cacheHelperProportions();
15496
 
15497
		/*
15498
		 * - Position generation -
15499
		 * This block generates everything position related - it's the core of draggables.
15500
		 */
15501
 
15502
		//Cache the margins of the original element
15503
		this._cacheMargins();
15504
 
15505
		//The element's absolute position on the page minus margins
15506
		this.offset = this.currentItem.offset();
15507
		this.offset = {
15508
			top: this.offset.top - this.margins.top,
15509
			left: this.offset.left - this.margins.left
15510
		};
15511
 
15512
		$.extend( this.offset, {
15513
			click: { //Where the click happened, relative to the element
15514
				left: event.pageX - this.offset.left,
15515
				top: event.pageY - this.offset.top
15516
			},
15517
 
15518
			// This is a relative to absolute position minus the actual position calculation -
15519
			// only used for relative positioned helper
15520
			relative: this._getRelativeOffset()
15521
		} );
15522
 
15523
		// After we get the helper offset, but before we get the parent offset we can
15524
		// change the helper's position to absolute
15525
		// TODO: Still need to figure out a way to make relative sorting possible
15526
		this.helper.css( "position", "absolute" );
15527
		this.cssPosition = this.helper.css( "position" );
15528
 
15529
		//Adjust the mouse offset relative to the helper if "cursorAt" is supplied
15530
		if ( o.cursorAt ) {
15531
			this._adjustOffsetFromHelper( o.cursorAt );
15532
		}
15533
 
15534
		//Cache the former DOM position
15535
		this.domPosition = {
15536
			prev: this.currentItem.prev()[ 0 ],
15537
			parent: this.currentItem.parent()[ 0 ]
15538
		};
15539
 
15540
		// If the helper is not the original, hide the original so it's not playing any role during
15541
		// the drag, won't cause anything bad this way
15542
		if ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) {
15543
			this.currentItem.hide();
15544
		}
15545
 
15546
		//Create the placeholder
15547
		this._createPlaceholder();
15548
 
15549
		//Get the next scrolling parent
15550
		this.scrollParent = this.placeholder.scrollParent();
15551
 
15552
		$.extend( this.offset, {
15553
			parent: this._getParentOffset()
15554
		} );
15555
 
15556
		//Set a containment if given in the options
15557
		if ( o.containment ) {
15558
			this._setContainment();
15559
		}
15560
 
15561
		if ( o.cursor && o.cursor !== "auto" ) { // cursor option
15562
			body = this.document.find( "body" );
15563
 
15564
			this._storedStylesheet =
15565
				$( "<style>*{ cursor: " + o.cursor + " !important; }</style>" ).appendTo( body );
15566
		}
15567
 
15568
		// We need to make sure to grab the zIndex before setting the
15569
		// opacity, because setting the opacity to anything lower than 1
15570
		// causes the zIndex to change from "auto" to 0.
15571
		if ( o.zIndex ) { // zIndex option
15572
			if ( this.helper.css( "zIndex" ) ) {
15573
				this._storedZIndex = this.helper.css( "zIndex" );
15574
			}
15575
			this.helper.css( "zIndex", o.zIndex );
15576
		}
15577
 
15578
		if ( o.opacity ) { // opacity option
15579
			if ( this.helper.css( "opacity" ) ) {
15580
				this._storedOpacity = this.helper.css( "opacity" );
15581
			}
15582
			this.helper.css( "opacity", o.opacity );
15583
		}
15584
 
15585
		//Prepare scrolling
15586
		if ( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
15587
				this.scrollParent[ 0 ].tagName !== "HTML" ) {
15588
			this.overflowOffset = this.scrollParent.offset();
15589
		}
15590
 
15591
		//Call callbacks
15592
		this._trigger( "start", event, this._uiHash() );
15593
 
15594
		//Recache the helper size
15595
		if ( !this._preserveHelperProportions ) {
15596
			this._cacheHelperProportions();
15597
		}
15598
 
15599
		//Post "activate" events to possible containers
15600
		if ( !noActivation ) {
15601
			for ( i = this.containers.length - 1; i >= 0; i-- ) {
15602
				this.containers[ i ]._trigger( "activate", event, this._uiHash( this ) );
15603
			}
15604
		}
15605
 
15606
		//Prepare possible droppables
15607
		if ( $.ui.ddmanager ) {
15608
			$.ui.ddmanager.current = this;
15609
		}
15610
 
15611
		if ( $.ui.ddmanager && !o.dropBehaviour ) {
15612
			$.ui.ddmanager.prepareOffsets( this, event );
15613
		}
15614
 
15615
		this.dragging = true;
15616
 
15617
		this._addClass( this.helper, "ui-sortable-helper" );
15618
 
15619
		//Move the helper, if needed
15620
		if ( !this.helper.parent().is( this.appendTo ) ) {
15621
			this.helper.detach().appendTo( this.appendTo );
15622
 
15623
			//Update position
15624
			this.offset.parent = this._getParentOffset();
15625
		}
15626
 
15627
		//Generate the original position
15628
		this.position = this.originalPosition = this._generatePosition( event );
15629
		this.originalPageX = event.pageX;
15630
		this.originalPageY = event.pageY;
15631
		this.lastPositionAbs = this.positionAbs = this._convertPositionTo( "absolute" );
15632
 
15633
		this._mouseDrag( event );
15634
 
15635
		return true;
15636
 
15637
	},
15638
 
15639
	_scroll: function( event ) {
15640
		var o = this.options,
15641
			scrolled = false;
15642
 
15643
		if ( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
15644
				this.scrollParent[ 0 ].tagName !== "HTML" ) {
15645
 
15646
			if ( ( this.overflowOffset.top + this.scrollParent[ 0 ].offsetHeight ) -
15647
					event.pageY < o.scrollSensitivity ) {
15648
				this.scrollParent[ 0 ].scrollTop =
15649
					scrolled = this.scrollParent[ 0 ].scrollTop + o.scrollSpeed;
15650
			} else if ( event.pageY - this.overflowOffset.top < o.scrollSensitivity ) {
15651
				this.scrollParent[ 0 ].scrollTop =
15652
					scrolled = this.scrollParent[ 0 ].scrollTop - o.scrollSpeed;
15653
			}
15654
 
15655
			if ( ( this.overflowOffset.left + this.scrollParent[ 0 ].offsetWidth ) -
15656
					event.pageX < o.scrollSensitivity ) {
15657
				this.scrollParent[ 0 ].scrollLeft = scrolled =
15658
					this.scrollParent[ 0 ].scrollLeft + o.scrollSpeed;
15659
			} else if ( event.pageX - this.overflowOffset.left < o.scrollSensitivity ) {
15660
				this.scrollParent[ 0 ].scrollLeft = scrolled =
15661
					this.scrollParent[ 0 ].scrollLeft - o.scrollSpeed;
15662
			}
15663
 
15664
		} else {
15665
 
15666
			if ( event.pageY - this.document.scrollTop() < o.scrollSensitivity ) {
15667
				scrolled = this.document.scrollTop( this.document.scrollTop() - o.scrollSpeed );
15668
			} else if ( this.window.height() - ( event.pageY - this.document.scrollTop() ) <
15669
					o.scrollSensitivity ) {
15670
				scrolled = this.document.scrollTop( this.document.scrollTop() + o.scrollSpeed );
15671
			}
15672
 
15673
			if ( event.pageX - this.document.scrollLeft() < o.scrollSensitivity ) {
15674
				scrolled = this.document.scrollLeft(
15675
					this.document.scrollLeft() - o.scrollSpeed
15676
				);
15677
			} else if ( this.window.width() - ( event.pageX - this.document.scrollLeft() ) <
15678
					o.scrollSensitivity ) {
15679
				scrolled = this.document.scrollLeft(
15680
					this.document.scrollLeft() + o.scrollSpeed
15681
				);
15682
			}
15683
 
15684
		}
15685
 
15686
		return scrolled;
15687
	},
15688
 
15689
	_mouseDrag: function( event ) {
15690
		var i, item, itemElement, intersection,
15691
			o = this.options;
15692
 
15693
		//Compute the helpers position
15694
		this.position = this._generatePosition( event );
15695
		this.positionAbs = this._convertPositionTo( "absolute" );
15696
 
15697
		//Set the helper position
15698
		if ( !this.options.axis || this.options.axis !== "y" ) {
15699
			this.helper[ 0 ].style.left = this.position.left + "px";
15700
		}
15701
		if ( !this.options.axis || this.options.axis !== "x" ) {
15702
			this.helper[ 0 ].style.top = this.position.top + "px";
15703
		}
15704
 
15705
		//Do scrolling
15706
		if ( o.scroll ) {
15707
			if ( this._scroll( event ) !== false ) {
15708
 
15709
				//Update item positions used in position checks
15710
				this._refreshItemPositions( true );
15711
 
15712
				if ( $.ui.ddmanager && !o.dropBehaviour ) {
15713
					$.ui.ddmanager.prepareOffsets( this, event );
15714
				}
15715
			}
15716
		}
15717
 
15718
		this.dragDirection = {
15719
			vertical: this._getDragVerticalDirection(),
15720
			horizontal: this._getDragHorizontalDirection()
15721
		};
15722
 
15723
		//Rearrange
15724
		for ( i = this.items.length - 1; i >= 0; i-- ) {
15725
 
15726
			//Cache variables and intersection, continue if no intersection
15727
			item = this.items[ i ];
15728
			itemElement = item.item[ 0 ];
15729
			intersection = this._intersectsWithPointer( item );
15730
			if ( !intersection ) {
15731
				continue;
15732
			}
15733
 
15734
			// Only put the placeholder inside the current Container, skip all
15735
			// items from other containers. This works because when moving
15736
			// an item from one container to another the
15737
			// currentContainer is switched before the placeholder is moved.
15738
			//
15739
			// Without this, moving items in "sub-sortables" can cause
15740
			// the placeholder to jitter between the outer and inner container.
15741
			if ( item.instance !== this.currentContainer ) {
15742
				continue;
15743
			}
15744
 
15745
			// Cannot intersect with itself
15746
			// no useless actions that have been done before
15747
			// no action if the item moved is the parent of the item checked
15748
			if ( itemElement !== this.currentItem[ 0 ] &&
15749
				this.placeholder[ intersection === 1 ?
15750
				"next" : "prev" ]()[ 0 ] !== itemElement &&
15751
				!$.contains( this.placeholder[ 0 ], itemElement ) &&
15752
				( this.options.type === "semi-dynamic" ?
15753
					!$.contains( this.element[ 0 ], itemElement ) :
15754
					true
15755
				)
15756
			) {
15757
 
15758
				this.direction = intersection === 1 ? "down" : "up";
15759
 
15760
				if ( this.options.tolerance === "pointer" ||
15761
						this._intersectsWithSides( item ) ) {
15762
					this._rearrange( event, item );
15763
				} else {
15764
					break;
15765
				}
15766
 
15767
				this._trigger( "change", event, this._uiHash() );
15768
				break;
15769
			}
15770
		}
15771
 
15772
		//Post events to containers
15773
		this._contactContainers( event );
15774
 
15775
		//Interconnect with droppables
15776
		if ( $.ui.ddmanager ) {
15777
			$.ui.ddmanager.drag( this, event );
15778
		}
15779
 
15780
		//Call callbacks
15781
		this._trigger( "sort", event, this._uiHash() );
15782
 
15783
		this.lastPositionAbs = this.positionAbs;
15784
		return false;
15785
 
15786
	},
15787
 
15788
	_mouseStop: function( event, noPropagation ) {
15789
 
15790
		if ( !event ) {
15791
			return;
15792
		}
15793
 
15794
		//If we are using droppables, inform the manager about the drop
15795
		if ( $.ui.ddmanager && !this.options.dropBehaviour ) {
15796
			$.ui.ddmanager.drop( this, event );
15797
		}
15798
 
15799
		if ( this.options.revert ) {
15800
			var that = this,
15801
				cur = this.placeholder.offset(),
15802
				axis = this.options.axis,
15803
				animation = {};
15804
 
15805
			if ( !axis || axis === "x" ) {
15806
				animation.left = cur.left - this.offset.parent.left - this.margins.left +
15807
					( this.offsetParent[ 0 ] === this.document[ 0 ].body ?
15808
 
15809
						this.offsetParent[ 0 ].scrollLeft
15810
					);
15811
			}
15812
			if ( !axis || axis === "y" ) {
15813
				animation.top = cur.top - this.offset.parent.top - this.margins.top +
15814
					( this.offsetParent[ 0 ] === this.document[ 0 ].body ?
15815
 
15816
						this.offsetParent[ 0 ].scrollTop
15817
					);
15818
			}
15819
			this.reverting = true;
15820
			$( this.helper ).animate(
15821
				animation,
15822
				parseInt( this.options.revert, 10 ) || 500,
15823
				function() {
15824
					that._clear( event );
15825
				}
15826
			);
15827
		} else {
15828
			this._clear( event, noPropagation );
15829
		}
15830
 
15831
		return false;
15832
 
15833
	},
15834
 
15835
	cancel: function() {
15836
 
15837
		if ( this.dragging ) {
15838
 
15839
			this._mouseUp( new $.Event( "mouseup", { target: null } ) );
15840
 
15841
			if ( this.options.helper === "original" ) {
15842
				this.currentItem.css( this._storedCSS );
15843
				this._removeClass( this.currentItem, "ui-sortable-helper" );
15844
			} else {
15845
				this.currentItem.show();
15846
			}
15847
 
15848
			//Post deactivating events to containers
15849
			for ( var i = this.containers.length - 1; i >= 0; i-- ) {
15850
				this.containers[ i ]._trigger( "deactivate", null, this._uiHash( this ) );
15851
				if ( this.containers[ i ].containerCache.over ) {
15852
					this.containers[ i ]._trigger( "out", null, this._uiHash( this ) );
15853
					this.containers[ i ].containerCache.over = 0;
15854
				}
15855
			}
15856
 
15857
		}
15858
 
15859
		if ( this.placeholder ) {
15860
 
15861
			//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately,
15862
			// it unbinds ALL events from the original node!
15863
			if ( this.placeholder[ 0 ].parentNode ) {
15864
				this.placeholder[ 0 ].parentNode.removeChild( this.placeholder[ 0 ] );
15865
			}
15866
			if ( this.options.helper !== "original" && this.helper &&
15867
					this.helper[ 0 ].parentNode ) {
15868
				this.helper.remove();
15869
			}
15870
 
15871
			$.extend( this, {
15872
				helper: null,
15873
				dragging: false,
15874
				reverting: false,
15875
				_noFinalSort: null
15876
			} );
15877
 
15878
			if ( this.domPosition.prev ) {
15879
				$( this.domPosition.prev ).after( this.currentItem );
15880
			} else {
15881
				$( this.domPosition.parent ).prepend( this.currentItem );
15882
			}
15883
		}
15884
 
15885
		return this;
15886
 
15887
	},
15888
 
15889
	serialize: function( o ) {
15890
 
15891
		var items = this._getItemsAsjQuery( o && o.connected ),
15892
			str = [];
15893
		o = o || {};
15894
 
15895
		$( items ).each( function() {
15896
			var res = ( $( o.item || this ).attr( o.attribute || "id" ) || "" )
15897
				.match( o.expression || ( /(.+)[\-=_](.+)/ ) );
15898
			if ( res ) {
15899
				str.push(
15900
					( o.key || res[ 1 ] + "[]" ) +
15901
					"=" + ( o.key && o.expression ? res[ 1 ] : res[ 2 ] ) );
15902
			}
15903
		} );
15904
 
15905
		if ( !str.length && o.key ) {
15906
			str.push( o.key + "=" );
15907
		}
15908
 
15909
		return str.join( "&" );
15910
 
15911
	},
15912
 
15913
	toArray: function( o ) {
15914
 
15915
		var items = this._getItemsAsjQuery( o && o.connected ),
15916
			ret = [];
15917
 
15918
		o = o || {};
15919
 
15920
		items.each( function() {
15921
			ret.push( $( o.item || this ).attr( o.attribute || "id" ) || "" );
15922
		} );
15923
		return ret;
15924
 
15925
	},
15926
 
15927
	/* Be careful with the following core functions */
15928
	_intersectsWith: function( item ) {
15929
 
15930
		var x1 = this.positionAbs.left,
15931
			x2 = x1 + this.helperProportions.width,
15932
			y1 = this.positionAbs.top,
15933
			y2 = y1 + this.helperProportions.height,
15934
			l = item.left,
15935
			r = l + item.width,
15936
			t = item.top,
15937
			b = t + item.height,
15938
			dyClick = this.offset.click.top,
15939
			dxClick = this.offset.click.left,
15940
			isOverElementHeight = ( this.options.axis === "x" ) || ( ( y1 + dyClick ) > t &&
15941
				( y1 + dyClick ) < b ),
15942
			isOverElementWidth = ( this.options.axis === "y" ) || ( ( x1 + dxClick ) > l &&
15943
				( x1 + dxClick ) < r ),
15944
			isOverElement = isOverElementHeight && isOverElementWidth;
15945
 
15946
		if ( this.options.tolerance === "pointer" ||
15947
			this.options.forcePointerForContainers ||
15948
			( this.options.tolerance !== "pointer" &&
15949
				this.helperProportions[ this.floating ? "width" : "height" ] >
15950
				item[ this.floating ? "width" : "height" ] )
15951
		) {
15952
			return isOverElement;
15953
		} else {
15954
 
15955
			return ( l < x1 + ( this.helperProportions.width / 2 ) && // Right Half
15956
				x2 - ( this.helperProportions.width / 2 ) < r && // Left Half
15957
				t < y1 + ( this.helperProportions.height / 2 ) && // Bottom Half
15958
				y2 - ( this.helperProportions.height / 2 ) < b ); // Top Half
15959
 
15960
		}
15961
	},
15962
 
15963
	_intersectsWithPointer: function( item ) {
15964
		var verticalDirection, horizontalDirection,
15965
			isOverElementHeight = ( this.options.axis === "x" ) ||
15966
				this._isOverAxis(
15967
					this.positionAbs.top + this.offset.click.top, item.top, item.height ),
15968
			isOverElementWidth = ( this.options.axis === "y" ) ||
15969
				this._isOverAxis(
15970
					this.positionAbs.left + this.offset.click.left, item.left, item.width ),
15971
			isOverElement = isOverElementHeight && isOverElementWidth;
15972
 
15973
		if ( !isOverElement ) {
15974
			return false;
15975
		}
15976
 
15977
		verticalDirection = this.dragDirection.vertical;
15978
		horizontalDirection = this.dragDirection.horizontal;
15979
 
15980
		return this.floating ?
15981
			( ( horizontalDirection === "right" || verticalDirection === "down" ) ? 2 : 1 ) :
15982
			( verticalDirection && ( verticalDirection === "down" ? 2 : 1 ) );
15983
 
15984
	},
15985
 
15986
	_intersectsWithSides: function( item ) {
15987
 
15988
		var isOverBottomHalf = this._isOverAxis( this.positionAbs.top +
15989
				this.offset.click.top, item.top + ( item.height / 2 ), item.height ),
15990
			isOverRightHalf = this._isOverAxis( this.positionAbs.left +
15991
				this.offset.click.left, item.left + ( item.width / 2 ), item.width ),
15992
			verticalDirection = this.dragDirection.vertical,
15993
			horizontalDirection = this.dragDirection.horizontal;
15994
 
15995
		if ( this.floating && horizontalDirection ) {
15996
			return ( ( horizontalDirection === "right" && isOverRightHalf ) ||
15997
				( horizontalDirection === "left" && !isOverRightHalf ) );
15998
		} else {
15999
			return verticalDirection && ( ( verticalDirection === "down" && isOverBottomHalf ) ||
16000
				( verticalDirection === "up" && !isOverBottomHalf ) );
16001
		}
16002
 
16003
	},
16004
 
16005
	_getDragVerticalDirection: function() {
16006
		var delta = this.positionAbs.top - this.lastPositionAbs.top;
16007
		return delta !== 0 && ( delta > 0 ? "down" : "up" );
16008
	},
16009
 
16010
	_getDragHorizontalDirection: function() {
16011
		var delta = this.positionAbs.left - this.lastPositionAbs.left;
16012
		return delta !== 0 && ( delta > 0 ? "right" : "left" );
16013
	},
16014
 
16015
	refresh: function( event ) {
16016
		this._refreshItems( event );
16017
		this._setHandleClassName();
16018
		this.refreshPositions();
16019
		return this;
16020
	},
16021
 
16022
	_connectWith: function() {
16023
		var options = this.options;
16024
		return options.connectWith.constructor === String ?
16025
			[ options.connectWith ] :
16026
			options.connectWith;
16027
	},
16028
 
16029
	_getItemsAsjQuery: function( connected ) {
16030
 
16031
		var i, j, cur, inst,
16032
			items = [],
16033
			queries = [],
16034
			connectWith = this._connectWith();
16035
 
16036
		if ( connectWith && connected ) {
16037
			for ( i = connectWith.length - 1; i >= 0; i-- ) {
16038
				cur = $( connectWith[ i ], this.document[ 0 ] );
16039
				for ( j = cur.length - 1; j >= 0; j-- ) {
16040
					inst = $.data( cur[ j ], this.widgetFullName );
16041
					if ( inst && inst !== this && !inst.options.disabled ) {
16042
						queries.push( [ typeof inst.options.items === "function" ?
16043
							inst.options.items.call( inst.element ) :
16044
							$( inst.options.items, inst.element )
16045
								.not( ".ui-sortable-helper" )
16046
								.not( ".ui-sortable-placeholder" ), inst ] );
16047
					}
16048
				}
16049
			}
16050
		}
16051
 
16052
		queries.push( [ typeof this.options.items === "function" ?
16053
			this.options.items
16054
				.call( this.element, null, { options: this.options, item: this.currentItem } ) :
16055
			$( this.options.items, this.element )
16056
				.not( ".ui-sortable-helper" )
16057
				.not( ".ui-sortable-placeholder" ), this ] );
16058
 
16059
		function addItems() {
16060
			items.push( this );
16061
		}
16062
		for ( i = queries.length - 1; i >= 0; i-- ) {
16063
			queries[ i ][ 0 ].each( addItems );
16064
		}
16065
 
16066
		return $( items );
16067
 
16068
	},
16069
 
16070
	_removeCurrentsFromItems: function() {
16071
 
16072
		var list = this.currentItem.find( ":data(" + this.widgetName + "-item)" );
16073
 
16074
		this.items = $.grep( this.items, function( item ) {
16075
			for ( var j = 0; j < list.length; j++ ) {
16076
				if ( list[ j ] === item.item[ 0 ] ) {
16077
					return false;
16078
				}
16079
			}
16080
			return true;
16081
		} );
16082
 
16083
	},
16084
 
16085
	_refreshItems: function( event ) {
16086
 
16087
		this.items = [];
16088
		this.containers = [ this ];
16089
 
16090
		var i, j, cur, inst, targetData, _queries, item, queriesLength,
16091
			items = this.items,
16092
			queries = [ [ typeof this.options.items === "function" ?
16093
				this.options.items.call( this.element[ 0 ], event, { item: this.currentItem } ) :
16094
				$( this.options.items, this.element ), this ] ],
16095
			connectWith = this._connectWith();
16096
 
16097
		//Shouldn't be run the first time through due to massive slow-down
16098
		if ( connectWith && this.ready ) {
16099
			for ( i = connectWith.length - 1; i >= 0; i-- ) {
16100
				cur = $( connectWith[ i ], this.document[ 0 ] );
16101
				for ( j = cur.length - 1; j >= 0; j-- ) {
16102
					inst = $.data( cur[ j ], this.widgetFullName );
16103
					if ( inst && inst !== this && !inst.options.disabled ) {
16104
						queries.push( [ typeof inst.options.items === "function" ?
16105
							inst.options.items
16106
								.call( inst.element[ 0 ], event, { item: this.currentItem } ) :
16107
							$( inst.options.items, inst.element ), inst ] );
16108
						this.containers.push( inst );
16109
					}
16110
				}
16111
			}
16112
		}
16113
 
16114
		for ( i = queries.length - 1; i >= 0; i-- ) {
16115
			targetData = queries[ i ][ 1 ];
16116
			_queries = queries[ i ][ 0 ];
16117
 
16118
			for ( j = 0, queriesLength = _queries.length; j < queriesLength; j++ ) {
16119
				item = $( _queries[ j ] );
16120
 
16121
				// Data for target checking (mouse manager)
16122
				item.data( this.widgetName + "-item", targetData );
16123
 
16124
				items.push( {
16125
					item: item,
16126
					instance: targetData,
16127
					width: 0, height: 0,
16128
					left: 0, top: 0
16129
				} );
16130
			}
16131
		}
16132
 
16133
	},
16134
 
16135
	_refreshItemPositions: function( fast ) {
16136
		var i, item, t, p;
16137
 
16138
		for ( i = this.items.length - 1; i >= 0; i-- ) {
16139
			item = this.items[ i ];
16140
 
16141
			//We ignore calculating positions of all connected containers when we're not over them
16142
			if ( this.currentContainer && item.instance !== this.currentContainer &&
16143
					item.item[ 0 ] !== this.currentItem[ 0 ] ) {
16144
				continue;
16145
			}
16146
 
16147
			t = this.options.toleranceElement ?
16148
				$( this.options.toleranceElement, item.item ) :
16149
				item.item;
16150
 
16151
			if ( !fast ) {
16152
				item.width = t.outerWidth();
16153
				item.height = t.outerHeight();
16154
			}
16155
 
16156
			p = t.offset();
16157
			item.left = p.left;
16158
			item.top = p.top;
16159
		}
16160
	},
16161
 
16162
	refreshPositions: function( fast ) {
16163
 
16164
		// Determine whether items are being displayed horizontally
16165
		this.floating = this.items.length ?
16166
			this.options.axis === "x" || this._isFloating( this.items[ 0 ].item ) :
16167
			false;
16168
 
16169
		// This has to be redone because due to the item being moved out/into the offsetParent,
16170
		// the offsetParent's position will change
16171
		if ( this.offsetParent && this.helper ) {
16172
			this.offset.parent = this._getParentOffset();
16173
		}
16174
 
16175
		this._refreshItemPositions( fast );
16176
 
16177
		var i, p;
16178
 
16179
		if ( this.options.custom && this.options.custom.refreshContainers ) {
16180
			this.options.custom.refreshContainers.call( this );
16181
		} else {
16182
			for ( i = this.containers.length - 1; i >= 0; i-- ) {
16183
				p = this.containers[ i ].element.offset();
16184
				this.containers[ i ].containerCache.left = p.left;
16185
				this.containers[ i ].containerCache.top = p.top;
16186
				this.containers[ i ].containerCache.width =
16187
					this.containers[ i ].element.outerWidth();
16188
				this.containers[ i ].containerCache.height =
16189
					this.containers[ i ].element.outerHeight();
16190
			}
16191
		}
16192
 
16193
		return this;
16194
	},
16195
 
16196
	_createPlaceholder: function( that ) {
16197
		that = that || this;
16198
		var className, nodeName,
16199
			o = that.options;
16200
 
16201
		if ( !o.placeholder || o.placeholder.constructor === String ) {
16202
			className = o.placeholder;
16203
			nodeName = that.currentItem[ 0 ].nodeName.toLowerCase();
16204
			o.placeholder = {
16205
				element: function() {
16206
 
16207
					var element = $( "<" + nodeName + ">", that.document[ 0 ] );
16208
 
16209
					that._addClass( element, "ui-sortable-placeholder",
16210
							className || that.currentItem[ 0 ].className )
16211
						._removeClass( element, "ui-sortable-helper" );
16212
 
16213
					if ( nodeName === "tbody" ) {
16214
						that._createTrPlaceholder(
16215
							that.currentItem.find( "tr" ).eq( 0 ),
16216
							$( "<tr>", that.document[ 0 ] ).appendTo( element )
16217
						);
16218
					} else if ( nodeName === "tr" ) {
16219
						that._createTrPlaceholder( that.currentItem, element );
16220
					} else if ( nodeName === "img" ) {
16221
						element.attr( "src", that.currentItem.attr( "src" ) );
16222
					}
16223
 
16224
					if ( !className ) {
16225
						element.css( "visibility", "hidden" );
16226
					}
16227
 
16228
					return element;
16229
				},
16230
				update: function( container, p ) {
16231
 
16232
					// 1. If a className is set as 'placeholder option, we don't force sizes -
16233
					// the class is responsible for that
16234
					// 2. The option 'forcePlaceholderSize can be enabled to force it even if a
16235
					// class name is specified
16236
					if ( className && !o.forcePlaceholderSize ) {
16237
						return;
16238
					}
16239
 
16240
					// If the element doesn't have a actual height or width by itself (without
16241
					// styles coming from a stylesheet), it receives the inline height and width
16242
					// from the dragged item. Or, if it's a tbody or tr, it's going to have a height
16243
					// anyway since we're populating them with <td>s above, but they're unlikely to
16244
					// be the correct height on their own if the row heights are dynamic, so we'll
16245
					// always assign the height of the dragged item given forcePlaceholderSize
16246
					// is true.
16247
					if ( !p.height() || ( o.forcePlaceholderSize &&
16248
							( nodeName === "tbody" || nodeName === "tr" ) ) ) {
16249
						p.height(
16250
							that.currentItem.innerHeight() -
16251
							parseInt( that.currentItem.css( "paddingTop" ) || 0, 10 ) -
16252
							parseInt( that.currentItem.css( "paddingBottom" ) || 0, 10 ) );
16253
					}
16254
					if ( !p.width() ) {
16255
						p.width(
16256
							that.currentItem.innerWidth() -
16257
							parseInt( that.currentItem.css( "paddingLeft" ) || 0, 10 ) -
16258
							parseInt( that.currentItem.css( "paddingRight" ) || 0, 10 ) );
16259
					}
16260
				}
16261
			};
16262
		}
16263
 
16264
		//Create the placeholder
16265
		that.placeholder = $( o.placeholder.element.call( that.element, that.currentItem ) );
16266
 
16267
		//Append it after the actual current item
16268
		that.currentItem.after( that.placeholder );
16269
 
16270
		//Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
16271
		o.placeholder.update( that, that.placeholder );
16272
 
16273
	},
16274
 
16275
	_createTrPlaceholder: function( sourceTr, targetTr ) {
16276
		var that = this;
16277
 
16278
		sourceTr.children().each( function() {
16279
			$( "<td>&#160;</td>", that.document[ 0 ] )
16280
				.attr( "colspan", $( this ).attr( "colspan" ) || 1 )
16281
				.appendTo( targetTr );
16282
		} );
16283
	},
16284
 
16285
	_contactContainers: function( event ) {
16286
		var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, cur, nearBottom,
16287
			floating, axis,
16288
			innermostContainer = null,
16289
			innermostIndex = null;
16290
 
16291
		// Get innermost container that intersects with item
16292
		for ( i = this.containers.length - 1; i >= 0; i-- ) {
16293
 
16294
			// Never consider a container that's located within the item itself
16295
			if ( $.contains( this.currentItem[ 0 ], this.containers[ i ].element[ 0 ] ) ) {
16296
				continue;
16297
			}
16298
 
16299
			if ( this._intersectsWith( this.containers[ i ].containerCache ) ) {
16300
 
16301
				// If we've already found a container and it's more "inner" than this, then continue
16302
				if ( innermostContainer &&
16303
						$.contains(
16304
							this.containers[ i ].element[ 0 ],
16305
							innermostContainer.element[ 0 ] ) ) {
16306
					continue;
16307
				}
16308
 
16309
				innermostContainer = this.containers[ i ];
16310
				innermostIndex = i;
16311
 
16312
			} else {
16313
 
16314
				// container doesn't intersect. trigger "out" event if necessary
16315
				if ( this.containers[ i ].containerCache.over ) {
16316
					this.containers[ i ]._trigger( "out", event, this._uiHash( this ) );
16317
					this.containers[ i ].containerCache.over = 0;
16318
				}
16319
			}
16320
 
16321
		}
16322
 
16323
		// If no intersecting containers found, return
16324
		if ( !innermostContainer ) {
16325
			return;
16326
		}
16327
 
16328
		// Move the item into the container if it's not there already
16329
		if ( this.containers.length === 1 ) {
16330
			if ( !this.containers[ innermostIndex ].containerCache.over ) {
16331
				this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash( this ) );
16332
				this.containers[ innermostIndex ].containerCache.over = 1;
16333
			}
16334
		} else {
16335
 
16336
			// When entering a new container, we will find the item with the least distance and
16337
			// append our item near it
16338
			dist = 10000;
16339
			itemWithLeastDistance = null;
16340
			floating = innermostContainer.floating || this._isFloating( this.currentItem );
16341
			posProperty = floating ? "left" : "top";
16342
			sizeProperty = floating ? "width" : "height";
16343
			axis = floating ? "pageX" : "pageY";
16344
 
16345
			for ( j = this.items.length - 1; j >= 0; j-- ) {
16346
				if ( !$.contains(
16347
						this.containers[ innermostIndex ].element[ 0 ], this.items[ j ].item[ 0 ] )
16348
				) {
16349
					continue;
16350
				}
16351
				if ( this.items[ j ].item[ 0 ] === this.currentItem[ 0 ] ) {
16352
					continue;
16353
				}
16354
 
16355
				cur = this.items[ j ].item.offset()[ posProperty ];
16356
				nearBottom = false;
16357
				if ( event[ axis ] - cur > this.items[ j ][ sizeProperty ] / 2 ) {
16358
					nearBottom = true;
16359
				}
16360
 
16361
				if ( Math.abs( event[ axis ] - cur ) < dist ) {
16362
					dist = Math.abs( event[ axis ] - cur );
16363
					itemWithLeastDistance = this.items[ j ];
16364
					this.direction = nearBottom ? "up" : "down";
16365
				}
16366
			}
16367
 
16368
			//Check if dropOnEmpty is enabled
16369
			if ( !itemWithLeastDistance && !this.options.dropOnEmpty ) {
16370
				return;
16371
			}
16372
 
16373
			if ( this.currentContainer === this.containers[ innermostIndex ] ) {
16374
				if ( !this.currentContainer.containerCache.over ) {
16375
					this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash() );
16376
					this.currentContainer.containerCache.over = 1;
16377
				}
16378
				return;
16379
			}
16380
 
16381
			if ( itemWithLeastDistance ) {
16382
				this._rearrange( event, itemWithLeastDistance, null, true );
16383
			} else {
16384
				this._rearrange( event, null, this.containers[ innermostIndex ].element, true );
16385
			}
16386
			this._trigger( "change", event, this._uiHash() );
16387
			this.containers[ innermostIndex ]._trigger( "change", event, this._uiHash( this ) );
16388
			this.currentContainer = this.containers[ innermostIndex ];
16389
 
16390
			//Update the placeholder
16391
			this.options.placeholder.update( this.currentContainer, this.placeholder );
16392
 
16393
			//Update scrollParent
16394
			this.scrollParent = this.placeholder.scrollParent();
16395
 
16396
			//Update overflowOffset
16397
			if ( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
16398
					this.scrollParent[ 0 ].tagName !== "HTML" ) {
16399
				this.overflowOffset = this.scrollParent.offset();
16400
			}
16401
 
16402
			this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash( this ) );
16403
			this.containers[ innermostIndex ].containerCache.over = 1;
16404
		}
16405
 
16406
	},
16407
 
16408
	_createHelper: function( event ) {
16409
 
16410
		var o = this.options,
16411
			helper = typeof o.helper === "function" ?
16412
				$( o.helper.apply( this.element[ 0 ], [ event, this.currentItem ] ) ) :
16413
				( o.helper === "clone" ? this.currentItem.clone() : this.currentItem );
16414
 
16415
		//Add the helper to the DOM if that didn't happen already
16416
		if ( !helper.parents( "body" ).length ) {
16417
			this.appendTo[ 0 ].appendChild( helper[ 0 ] );
16418
		}
16419
 
16420
		if ( helper[ 0 ] === this.currentItem[ 0 ] ) {
16421
			this._storedCSS = {
16422
				width: this.currentItem[ 0 ].style.width,
16423
				height: this.currentItem[ 0 ].style.height,
16424
				position: this.currentItem.css( "position" ),
16425
				top: this.currentItem.css( "top" ),
16426
				left: this.currentItem.css( "left" )
16427
			};
16428
		}
16429
 
16430
		if ( !helper[ 0 ].style.width || o.forceHelperSize ) {
16431
			helper.width( this.currentItem.width() );
16432
		}
16433
		if ( !helper[ 0 ].style.height || o.forceHelperSize ) {
16434
			helper.height( this.currentItem.height() );
16435
		}
16436
 
16437
		return helper;
16438
 
16439
	},
16440
 
16441
	_adjustOffsetFromHelper: function( obj ) {
16442
		if ( typeof obj === "string" ) {
16443
			obj = obj.split( " " );
16444
		}
16445
		if ( Array.isArray( obj ) ) {
16446
			obj = { left: +obj[ 0 ], top: +obj[ 1 ] || 0 };
16447
		}
16448
		if ( "left" in obj ) {
16449
			this.offset.click.left = obj.left + this.margins.left;
16450
		}
16451
		if ( "right" in obj ) {
16452
			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
16453
		}
16454
		if ( "top" in obj ) {
16455
			this.offset.click.top = obj.top + this.margins.top;
16456
		}
16457
		if ( "bottom" in obj ) {
16458
			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
16459
		}
16460
	},
16461
 
16462
	_getParentOffset: function() {
16463
 
16464
		//Get the offsetParent and cache its position
16465
		this.offsetParent = this.helper.offsetParent();
16466
		var po = this.offsetParent.offset();
16467
 
16468
		// This is a special case where we need to modify a offset calculated on start, since the
16469
		// following happened:
16470
		// 1. The position of the helper is absolute, so it's position is calculated based on the
16471
		// next positioned parent
16472
		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't
16473
		// the document, which means that the scroll is included in the initial calculation of the
16474
		// offset of the parent, and never recalculated upon drag
16475
		if ( this.cssPosition === "absolute" && this.scrollParent[ 0 ] !== this.document[ 0 ] &&
16476
				$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) {
16477
			po.left += this.scrollParent.scrollLeft();
16478
			po.top += this.scrollParent.scrollTop();
16479
		}
16480
 
16481
		// This needs to be actually done for all browsers, since pageX/pageY includes
16482
		// this information.
16483
		if ( this.offsetParent[ 0 ] === this.document[ 0 ].body ) {
16484
			po = { top: 0, left: 0 };
16485
		}
16486
 
16487
		return {
16488
			top: po.top + ( parseInt( this.offsetParent.css( "borderTopWidth" ), 10 ) || 0 ),
16489
			left: po.left + ( parseInt( this.offsetParent.css( "borderLeftWidth" ), 10 ) || 0 )
16490
		};
16491
 
16492
	},
16493
 
16494
	_getRelativeOffset: function() {
16495
 
16496
		if ( this.cssPosition === "relative" ) {
16497
			var p = this.currentItem.position();
16498
			return {
16499
				top: p.top - ( parseInt( this.helper.css( "top" ), 10 ) || 0 ) +
16500
					this.scrollParent.scrollTop(),
16501
				left: p.left - ( parseInt( this.helper.css( "left" ), 10 ) || 0 ) +
16502
					this.scrollParent.scrollLeft()
16503
			};
16504
		} else {
16505
			return { top: 0, left: 0 };
16506
		}
16507
 
16508
	},
16509
 
16510
	_cacheMargins: function() {
16511
		this.margins = {
16512
			left: ( parseInt( this.currentItem.css( "marginLeft" ), 10 ) || 0 ),
16513
			top: ( parseInt( this.currentItem.css( "marginTop" ), 10 ) || 0 )
16514
		};
16515
	},
16516
 
16517
	_cacheHelperProportions: function() {
16518
		this.helperProportions = {
16519
			width: this.helper.outerWidth(),
16520
			height: this.helper.outerHeight()
16521
		};
16522
	},
16523
 
16524
	_setContainment: function() {
16525
 
16526
		var ce, co, over,
16527
			o = this.options;
16528
		if ( o.containment === "parent" ) {
16529
			o.containment = this.helper[ 0 ].parentNode;
16530
		}
16531
		if ( o.containment === "document" || o.containment === "window" ) {
16532
			this.containment = [
16533
 
16534
 
16535
				o.containment === "document" ?
16536
					this.document.width() :
16537
					this.window.width() - this.helperProportions.width - this.margins.left,
16538
				( o.containment === "document" ?
16539
					( this.document.height() || document.body.parentNode.scrollHeight ) :
16540
					this.window.height() || this.document[ 0 ].body.parentNode.scrollHeight
16541
				) - this.helperProportions.height - this.margins.top
16542
			];
16543
		}
16544
 
16545
		if ( !( /^(document|window|parent)$/ ).test( o.containment ) ) {
16546
			ce = $( o.containment )[ 0 ];
16547
			co = $( o.containment ).offset();
16548
			over = ( $( ce ).css( "overflow" ) !== "hidden" );
16549
 
16550
			this.containment = [
16551
				co.left + ( parseInt( $( ce ).css( "borderLeftWidth" ), 10 ) || 0 ) +
16552
					( parseInt( $( ce ).css( "paddingLeft" ), 10 ) || 0 ) - this.margins.left,
16553
				co.top + ( parseInt( $( ce ).css( "borderTopWidth" ), 10 ) || 0 ) +
16554
					( parseInt( $( ce ).css( "paddingTop" ), 10 ) || 0 ) - this.margins.top,
16555
				co.left + ( over ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) -
16556
					( parseInt( $( ce ).css( "borderLeftWidth" ), 10 ) || 0 ) -
16557
					( parseInt( $( ce ).css( "paddingRight" ), 10 ) || 0 ) -
16558
					this.helperProportions.width - this.margins.left,
16559
				co.top + ( over ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) -
16560
					( parseInt( $( ce ).css( "borderTopWidth" ), 10 ) || 0 ) -
16561
					( parseInt( $( ce ).css( "paddingBottom" ), 10 ) || 0 ) -
16562
					this.helperProportions.height - this.margins.top
16563
			];
16564
		}
16565
 
16566
	},
16567
 
16568
	_convertPositionTo: function( d, pos ) {
16569
 
16570
		if ( !pos ) {
16571
			pos = this.position;
16572
		}
16573
		var mod = d === "absolute" ? 1 : -1,
16574
			scroll = this.cssPosition === "absolute" &&
16575
				!( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
16576
				$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ?
16577
					this.offsetParent :
16578
					this.scrollParent,
16579
			scrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName );
16580
 
16581
		return {
16582
			top: (
16583
 
16584
				// The absolute mouse position
16585
				pos.top	+
16586
 
16587
				// Only for relative positioned nodes: Relative offset from element to offset parent
16588
				this.offset.relative.top * mod +
16589
 
16590
				// The offsetParent's offset without borders (offset + border)
16591
				this.offset.parent.top * mod -
16592
				( ( this.cssPosition === "fixed" ?
16593
					-this.scrollParent.scrollTop() :
16594
					( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod )
16595
			),
16596
			left: (
16597
 
16598
				// The absolute mouse position
16599
				pos.left +
16600
 
16601
				// Only for relative positioned nodes: Relative offset from element to offset parent
16602
				this.offset.relative.left * mod +
16603
 
16604
				// The offsetParent's offset without borders (offset + border)
16605
				this.offset.parent.left * mod	-
16606
				( ( this.cssPosition === "fixed" ?
16607
					-this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 :
16608
					scroll.scrollLeft() ) * mod )
16609
			)
16610
		};
16611
 
16612
	},
16613
 
16614
	_generatePosition: function( event ) {
16615
 
16616
		var top, left,
16617
			o = this.options,
16618
			pageX = event.pageX,
16619
			pageY = event.pageY,
16620
			scroll = this.cssPosition === "absolute" &&
16621
				!( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
16622
				$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ?
16623
					this.offsetParent :
16624
					this.scrollParent,
16625
				scrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName );
16626
 
16627
		// This is another very weird special case that only happens for relative elements:
16628
		// 1. If the css position is relative
16629
		// 2. and the scroll parent is the document or similar to the offset parent
16630
		// we have to refresh the relative offset during the scroll so there are no jumps
16631
		if ( this.cssPosition === "relative" && !( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
16632
				this.scrollParent[ 0 ] !== this.offsetParent[ 0 ] ) ) {
16633
			this.offset.relative = this._getRelativeOffset();
16634
		}
16635
 
16636
		/*
16637
		 * - Position constraining -
16638
		 * Constrain the position to a mix of grid, containment.
16639
		 */
16640
 
16641
		if ( this.originalPosition ) { //If we are not dragging yet, we won't check for options
16642
 
16643
			if ( this.containment ) {
16644
				if ( event.pageX - this.offset.click.left < this.containment[ 0 ] ) {
16645
					pageX = this.containment[ 0 ] + this.offset.click.left;
16646
				}
16647
				if ( event.pageY - this.offset.click.top < this.containment[ 1 ] ) {
16648
					pageY = this.containment[ 1 ] + this.offset.click.top;
16649
				}
16650
				if ( event.pageX - this.offset.click.left > this.containment[ 2 ] ) {
16651
					pageX = this.containment[ 2 ] + this.offset.click.left;
16652
				}
16653
				if ( event.pageY - this.offset.click.top > this.containment[ 3 ] ) {
16654
					pageY = this.containment[ 3 ] + this.offset.click.top;
16655
				}
16656
			}
16657
 
16658
			if ( o.grid ) {
16659
				top = this.originalPageY + Math.round( ( pageY - this.originalPageY ) /
16660
					o.grid[ 1 ] ) * o.grid[ 1 ];
16661
				pageY = this.containment ?
16662
					( ( top - this.offset.click.top >= this.containment[ 1 ] &&
16663
						top - this.offset.click.top <= this.containment[ 3 ] ) ?
16664
							top :
16665
							( ( top - this.offset.click.top >= this.containment[ 1 ] ) ?
16666
								top - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) :
16667
								top;
16668
 
16669
				left = this.originalPageX + Math.round( ( pageX - this.originalPageX ) /
16670
					o.grid[ 0 ] ) * o.grid[ 0 ];
16671
				pageX = this.containment ?
16672
					( ( left - this.offset.click.left >= this.containment[ 0 ] &&
16673
						left - this.offset.click.left <= this.containment[ 2 ] ) ?
16674
							left :
16675
							( ( left - this.offset.click.left >= this.containment[ 0 ] ) ?
16676
								left - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) :
16677
								left;
16678
			}
16679
 
16680
		}
16681
 
16682
		return {
16683
			top: (
16684
 
16685
				// The absolute mouse position
16686
				pageY -
16687
 
16688
				// Click offset (relative to the element)
16689
				this.offset.click.top -
16690
 
16691
				// Only for relative positioned nodes: Relative offset from element to offset parent
16692
				this.offset.relative.top -
16693
 
16694
				// The offsetParent's offset without borders (offset + border)
16695
				this.offset.parent.top +
16696
				( ( this.cssPosition === "fixed" ?
16697
					-this.scrollParent.scrollTop() :
16698
					( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) )
16699
			),
16700
			left: (
16701
 
16702
				// The absolute mouse position
16703
				pageX -
16704
 
16705
				// Click offset (relative to the element)
16706
				this.offset.click.left -
16707
 
16708
				// Only for relative positioned nodes: Relative offset from element to offset parent
16709
				this.offset.relative.left -
16710
 
16711
				// The offsetParent's offset without borders (offset + border)
16712
				this.offset.parent.left +
16713
				( ( this.cssPosition === "fixed" ?
16714
					-this.scrollParent.scrollLeft() :
16715
					scrollIsRootNode ? 0 : scroll.scrollLeft() ) )
16716
			)
16717
		};
16718
 
16719
	},
16720
 
16721
	_rearrange: function( event, i, a, hardRefresh ) {
16722
 
16723
		if ( a ) {
16724
			a[ 0 ].appendChild( this.placeholder[ 0 ] );
16725
		} else {
16726
			i.item[ 0 ].parentNode.insertBefore( this.placeholder[ 0 ],
16727
				( this.direction === "down" ? i.item[ 0 ] : i.item[ 0 ].nextSibling ) );
16728
		}
16729
 
16730
		//Various things done here to improve the performance:
16731
		// 1. we create a setTimeout, that calls refreshPositions
16732
		// 2. on the instance, we have a counter variable, that get's higher after every append
16733
		// 3. on the local scope, we copy the counter variable, and check in the timeout,
16734
		// if it's still the same
16735
		// 4. this lets only the last addition to the timeout stack through
16736
		this.counter = this.counter ? ++this.counter : 1;
16737
		var counter = this.counter;
16738
 
16739
		this._delay( function() {
16740
			if ( counter === this.counter ) {
16741
 
16742
				//Precompute after each DOM insertion, NOT on mousemove
16743
				this.refreshPositions( !hardRefresh );
16744
			}
16745
		} );
16746
 
16747
	},
16748
 
16749
	_clear: function( event, noPropagation ) {
16750
 
16751
		this.reverting = false;
16752
 
16753
		// We delay all events that have to be triggered to after the point where the placeholder
16754
		// has been removed and everything else normalized again
16755
		var i,
16756
			delayedTriggers = [];
16757
 
16758
		// We first have to update the dom position of the actual currentItem
16759
		// Note: don't do it if the current item is already removed (by a user), or it gets
16760
		// reappended (see #4088)
16761
		if ( !this._noFinalSort && this.currentItem.parent().length ) {
16762
			this.placeholder.before( this.currentItem );
16763
		}
16764
		this._noFinalSort = null;
16765
 
16766
		if ( this.helper[ 0 ] === this.currentItem[ 0 ] ) {
16767
			for ( i in this._storedCSS ) {
16768
				if ( this._storedCSS[ i ] === "auto" || this._storedCSS[ i ] === "static" ) {
16769
					this._storedCSS[ i ] = "";
16770
				}
16771
			}
16772
			this.currentItem.css( this._storedCSS );
16773
			this._removeClass( this.currentItem, "ui-sortable-helper" );
16774
		} else {
16775
			this.currentItem.show();
16776
		}
16777
 
16778
		if ( this.fromOutside && !noPropagation ) {
16779
			delayedTriggers.push( function( event ) {
16780
				this._trigger( "receive", event, this._uiHash( this.fromOutside ) );
16781
			} );
16782
		}
16783
		if ( ( this.fromOutside ||
16784
				this.domPosition.prev !==
16785
				this.currentItem.prev().not( ".ui-sortable-helper" )[ 0 ] ||
16786
				this.domPosition.parent !== this.currentItem.parent()[ 0 ] ) && !noPropagation ) {
16787
 
16788
			// Trigger update callback if the DOM position has changed
16789
			delayedTriggers.push( function( event ) {
16790
				this._trigger( "update", event, this._uiHash() );
16791
			} );
16792
		}
16793
 
16794
		// Check if the items Container has Changed and trigger appropriate
16795
		// events.
16796
		if ( this !== this.currentContainer ) {
16797
			if ( !noPropagation ) {
16798
				delayedTriggers.push( function( event ) {
16799
					this._trigger( "remove", event, this._uiHash() );
16800
				} );
16801
				delayedTriggers.push( ( function( c ) {
16802
					return function( event ) {
16803
						c._trigger( "receive", event, this._uiHash( this ) );
16804
					};
16805
				} ).call( this, this.currentContainer ) );
16806
				delayedTriggers.push( ( function( c ) {
16807
					return function( event ) {
16808
						c._trigger( "update", event, this._uiHash( this ) );
16809
					};
16810
				} ).call( this, this.currentContainer ) );
16811
			}
16812
		}
16813
 
16814
		//Post events to containers
16815
		function delayEvent( type, instance, container ) {
16816
			return function( event ) {
16817
				container._trigger( type, event, instance._uiHash( instance ) );
16818
			};
16819
		}
16820
		for ( i = this.containers.length - 1; i >= 0; i-- ) {
16821
			if ( !noPropagation ) {
16822
				delayedTriggers.push( delayEvent( "deactivate", this, this.containers[ i ] ) );
16823
			}
16824
			if ( this.containers[ i ].containerCache.over ) {
16825
				delayedTriggers.push( delayEvent( "out", this, this.containers[ i ] ) );
16826
				this.containers[ i ].containerCache.over = 0;
16827
			}
16828
		}
16829
 
16830
		//Do what was originally in plugins
16831
		if ( this._storedStylesheet ) {
16832
			this._storedStylesheet.remove();
16833
			this._storedStylesheet = null;
16834
		}
16835
		if ( this._storedOpacity ) {
16836
			this.helper.css( "opacity", this._storedOpacity );
16837
		}
16838
		if ( this._storedZIndex ) {
16839
			this.helper.css( "zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex );
16840
		}
16841
 
16842
		this.dragging = false;
16843
 
16844
		if ( !noPropagation ) {
16845
			this._trigger( "beforeStop", event, this._uiHash() );
16846
		}
16847
 
16848
		//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately,
16849
		// it unbinds ALL events from the original node!
16850
		this.placeholder[ 0 ].parentNode.removeChild( this.placeholder[ 0 ] );
16851
 
16852
		if ( !this.cancelHelperRemoval ) {
16853
			if ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) {
16854
				this.helper.remove();
16855
			}
16856
			this.helper = null;
16857
		}
16858
 
16859
		if ( !noPropagation ) {
16860
			for ( i = 0; i < delayedTriggers.length; i++ ) {
16861
 
16862
				// Trigger all delayed events
16863
				delayedTriggers[ i ].call( this, event );
16864
			}
16865
			this._trigger( "stop", event, this._uiHash() );
16866
		}
16867
 
16868
		this.fromOutside = false;
16869
		return !this.cancelHelperRemoval;
16870
 
16871
	},
16872
 
16873
	_trigger: function() {
16874
		if ( $.Widget.prototype._trigger.apply( this, arguments ) === false ) {
16875
			this.cancel();
16876
		}
16877
	},
16878
 
16879
	_uiHash: function( _inst ) {
16880
		var inst = _inst || this;
16881
		return {
16882
			helper: inst.helper,
16883
			placeholder: inst.placeholder || $( [] ),
16884
			position: inst.position,
16885
			originalPosition: inst.originalPosition,
16886
			offset: inst.positionAbs,
16887
			item: inst.currentItem,
16888
			sender: _inst ? _inst.element : null
16889
		};
16890
	}
16891
 
16892
} );
16893
 
16894
 
16895
/*!
16896
 * jQuery UI Spinner 1.14.1
16897
 * https://jqueryui.com
16898
 *
16899
 * Copyright OpenJS Foundation and other contributors
16900
 * Released under the MIT license.
16901
 * https://jquery.org/license
16902
 */
16903
 
16904
//>>label: Spinner
16905
//>>group: Widgets
16906
//>>description: Displays buttons to easily input numbers via the keyboard or mouse.
16907
//>>docs: https://api.jqueryui.com/spinner/
16908
//>>demos: https://jqueryui.com/spinner/
16909
//>>css.structure: ../../themes/base/core.css
16910
//>>css.structure: ../../themes/base/spinner.css
16911
//>>css.theme: ../../themes/base/theme.css
16912
 
16913
 
16914
function spinnerModifier( fn ) {
16915
	return function() {
16916
		var previous = this.element.val();
16917
		fn.apply( this, arguments );
16918
		this._refresh();
16919
		if ( previous !== this.element.val() ) {
16920
			this._trigger( "change" );
16921
		}
16922
	};
16923
}
16924
 
16925
$.widget( "ui.spinner", {
16926
	version: "1.14.1",
16927
	defaultElement: "<input>",
16928
	widgetEventPrefix: "spin",
16929
	options: {
16930
		classes: {
16931
			"ui-spinner": "ui-corner-all",
16932
			"ui-spinner-down": "ui-corner-br",
16933
			"ui-spinner-up": "ui-corner-tr"
16934
		},
16935
		culture: null,
16936
		icons: {
16937
			down: "ui-icon-triangle-1-s",
16938
			up: "ui-icon-triangle-1-n"
16939
		},
16940
		incremental: true,
16941
		max: null,
16942
		min: null,
16943
		numberFormat: null,
16944
		page: 10,
16945
		step: 1,
16946
 
16947
		change: null,
16948
		spin: null,
16949
		start: null,
16950
		stop: null
16951
	},
16952
 
16953
	_create: function() {
16954
 
16955
		// handle string values that need to be parsed
16956
		this._setOption( "max", this.options.max );
16957
		this._setOption( "min", this.options.min );
16958
		this._setOption( "step", this.options.step );
16959
 
16960
		// Only format if there is a value, prevents the field from being marked
16961
		// as invalid in Firefox, see #9573.
16962
		if ( this.value() !== "" ) {
16963
 
16964
			// Format the value, but don't constrain.
16965
			this._value( this.element.val(), true );
16966
		}
16967
 
16968
		this._draw();
16969
		this._on( this._events );
16970
		this._refresh();
16971
 
16972
		// Turning off autocomplete prevents the browser from remembering the
16973
		// value when navigating through history, so we re-enable autocomplete
16974
		// if the page is unloaded before the widget is destroyed. #7790
16975
		this._on( this.window, {
16976
			beforeunload: function() {
16977
				this.element.removeAttr( "autocomplete" );
16978
			}
16979
		} );
16980
	},
16981
 
16982
	_getCreateOptions: function() {
16983
		var options = this._super();
16984
		var element = this.element;
16985
 
16986
		$.each( [ "min", "max", "step" ], function( i, option ) {
16987
			var value = element.attr( option );
16988
			if ( value != null && value.length ) {
16989
				options[ option ] = value;
16990
			}
16991
		} );
16992
 
16993
		return options;
16994
	},
16995
 
16996
	_events: {
16997
		keydown: function( event ) {
16998
			if ( this._start( event ) && this._keydown( event ) ) {
16999
				event.preventDefault();
17000
			}
17001
		},
17002
		keyup: "_stop",
17003
		focus: function() {
17004
			this.previous = this.element.val();
17005
		},
17006
		blur: function( event ) {
17007
			this._stop();
17008
			this._refresh();
17009
			if ( this.previous !== this.element.val() ) {
17010
				this._trigger( "change", event );
17011
			}
17012
		},
17013
		mousewheel: function( event, delta ) {
17014
			var activeElement = this.document[ 0 ].activeElement;
17015
			var isActive = this.element[ 0 ] === activeElement;
17016
 
17017
			if ( !isActive || !delta ) {
17018
				return;
17019
			}
17020
 
17021
			if ( !this.spinning && !this._start( event ) ) {
17022
				return false;
17023
			}
17024
 
17025
			this._spin( ( delta > 0 ? 1 : -1 ) * this.options.step, event );
17026
			clearTimeout( this.mousewheelTimer );
17027
			this.mousewheelTimer = this._delay( function() {
17028
				if ( this.spinning ) {
17029
					this._stop( event );
17030
				}
17031
			}, 100 );
17032
			event.preventDefault();
17033
		},
17034
		"mousedown .ui-spinner-button": function( event ) {
17035
			var previous;
17036
 
17037
			// We never want the buttons to have focus; whenever the user is
17038
			// interacting with the spinner, the focus should be on the input.
17039
			// If the input is focused then this.previous is properly set from
17040
			// when the input first received focus. If the input is not focused
17041
			// then we need to set this.previous based on the value before spinning.
17042
			previous = this.element[ 0 ] === this.document[ 0 ].activeElement ?
17043
				this.previous : this.element.val();
17044
			function checkFocus() {
17045
				var isActive = this.element[ 0 ] === this.document[ 0 ].activeElement;
17046
				if ( !isActive ) {
17047
					this.element.trigger( "focus" );
17048
					this.previous = previous;
17049
				}
17050
			}
17051
 
17052
			// Ensure focus is on (or stays on) the text field
17053
			event.preventDefault();
17054
			checkFocus.call( this );
17055
 
17056
			if ( this._start( event ) === false ) {
17057
				return;
17058
			}
17059
 
17060
			this._repeat( null, $( event.currentTarget )
17061
				.hasClass( "ui-spinner-up" ) ? 1 : -1, event );
17062
		},
17063
		"mouseup .ui-spinner-button": "_stop",
17064
		"mouseenter .ui-spinner-button": function( event ) {
17065
 
17066
			// button will add ui-state-active if mouse was down while mouseleave and kept down
17067
			if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) {
17068
				return;
17069
			}
17070
 
17071
			if ( this._start( event ) === false ) {
17072
				return false;
17073
			}
17074
			this._repeat( null, $( event.currentTarget )
17075
				.hasClass( "ui-spinner-up" ) ? 1 : -1, event );
17076
		},
17077
 
17078
		// TODO: do we really want to consider this a stop?
17079
		// shouldn't we just stop the repeater and wait until mouseup before
17080
		// we trigger the stop event?
17081
		"mouseleave .ui-spinner-button": "_stop"
17082
	},
17083
 
17084
	// Support mobile enhanced option and make backcompat more sane
17085
	_enhance: function() {
17086
		this.uiSpinner = this.element
17087
			.attr( "autocomplete", "off" )
17088
			.wrap( "<span>" )
17089
			.parent()
17090
 
17091
				// Add buttons
17092
				.append(
17093
					"<a></a><a></a>"
17094
				);
17095
	},
17096
 
17097
	_draw: function() {
17098
		this._enhance();
17099
 
17100
		this._addClass( this.uiSpinner, "ui-spinner", "ui-widget ui-widget-content" );
17101
		this._addClass( "ui-spinner-input" );
17102
 
17103
		this.element.attr( "role", "spinbutton" );
17104
 
17105
		// Button bindings
17106
		this.buttons = this.uiSpinner.children( "a" )
17107
			.attr( "tabIndex", -1 )
17108
			.attr( "aria-hidden", true )
17109
			.button( {
17110
				classes: {
17111
					"ui-button": ""
17112
				}
17113
			} );
17114
 
17115
		// TODO: Right now button does not support classes this is already updated in button PR
17116
		this._removeClass( this.buttons, "ui-corner-all" );
17117
 
17118
		this._addClass( this.buttons.first(), "ui-spinner-button ui-spinner-up" );
17119
		this._addClass( this.buttons.last(), "ui-spinner-button ui-spinner-down" );
17120
		this.buttons.first().button( {
17121
			"icon": this.options.icons.up,
17122
			"showLabel": false
17123
		} );
17124
		this.buttons.last().button( {
17125
			"icon": this.options.icons.down,
17126
			"showLabel": false
17127
		} );
17128
 
17129
		// IE 6 doesn't understand height: 50% for the buttons
17130
		// unless the wrapper has an explicit height
17131
		if ( this.buttons.height() > Math.ceil( this.uiSpinner.height() * 0.5 ) &&
17132
				this.uiSpinner.height() > 0 ) {
17133
			this.uiSpinner.height( this.uiSpinner.height() );
17134
		}
17135
	},
17136
 
17137
	_keydown: function( event ) {
17138
		var options = this.options,
17139
			keyCode = $.ui.keyCode;
17140
 
17141
		switch ( event.keyCode ) {
17142
		case keyCode.UP:
17143
			this._repeat( null, 1, event );
17144
			return true;
17145
		case keyCode.DOWN:
17146
			this._repeat( null, -1, event );
17147
			return true;
17148
		case keyCode.PAGE_UP:
17149
			this._repeat( null, options.page, event );
17150
			return true;
17151
		case keyCode.PAGE_DOWN:
17152
			this._repeat( null, -options.page, event );
17153
			return true;
17154
		}
17155
 
17156
		return false;
17157
	},
17158
 
17159
	_start: function( event ) {
17160
		if ( !this.spinning && this._trigger( "start", event ) === false ) {
17161
			return false;
17162
		}
17163
 
17164
		if ( !this.counter ) {
17165
			this.counter = 1;
17166
		}
17167
		this.spinning = true;
17168
		return true;
17169
	},
17170
 
17171
	_repeat: function( i, steps, event ) {
17172
		i = i || 500;
17173
 
17174
		clearTimeout( this.timer );
17175
		this.timer = this._delay( function() {
17176
			this._repeat( 40, steps, event );
17177
		}, i );
17178
 
17179
		this._spin( steps * this.options.step, event );
17180
	},
17181
 
17182
	_spin: function( step, event ) {
17183
		var value = this.value() || 0;
17184
 
17185
		if ( !this.counter ) {
17186
			this.counter = 1;
17187
		}
17188
 
17189
		value = this._adjustValue( value + step * this._increment( this.counter ) );
17190
 
17191
		if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false ) {
17192
			this._value( value );
17193
			this.counter++;
17194
		}
17195
	},
17196
 
17197
	_increment: function( i ) {
17198
		var incremental = this.options.incremental;
17199
 
17200
		if ( incremental ) {
17201
			return typeof incremental === "function" ?
17202
				incremental( i ) :
17203
				Math.floor( i * i * i / 50000 - i * i / 500 + 17 * i / 200 + 1 );
17204
		}
17205
 
17206
		return 1;
17207
	},
17208
 
17209
	_precision: function() {
17210
		var precision = this._precisionOf( this.options.step );
17211
		if ( this.options.min !== null ) {
17212
			precision = Math.max( precision, this._precisionOf( this.options.min ) );
17213
		}
17214
		return precision;
17215
	},
17216
 
17217
	_precisionOf: function( num ) {
17218
		var str = num.toString(),
17219
			decimal = str.indexOf( "." );
17220
		return decimal === -1 ? 0 : str.length - decimal - 1;
17221
	},
17222
 
17223
	_adjustValue: function( value ) {
17224
		var base, aboveMin,
17225
			options = this.options;
17226
 
17227
		// Make sure we're at a valid step
17228
		// - find out where we are relative to the base (min or 0)
17229
		base = options.min !== null ? options.min : 0;
17230
		aboveMin = value - base;
17231
 
17232
		// - round to the nearest step
17233
		aboveMin = Math.round( aboveMin / options.step ) * options.step;
17234
 
17235
		// - rounding is based on 0, so adjust back to our base
17236
		value = base + aboveMin;
17237
 
17238
		// Fix precision from bad JS floating point math
17239
		value = parseFloat( value.toFixed( this._precision() ) );
17240
 
17241
		// Clamp the value
17242
		if ( options.max !== null && value > options.max ) {
17243
			return options.max;
17244
		}
17245
		if ( options.min !== null && value < options.min ) {
17246
			return options.min;
17247
		}
17248
 
17249
		return value;
17250
	},
17251
 
17252
	_stop: function( event ) {
17253
		if ( !this.spinning ) {
17254
			return;
17255
		}
17256
 
17257
		clearTimeout( this.timer );
17258
		clearTimeout( this.mousewheelTimer );
17259
		this.counter = 0;
17260
		this.spinning = false;
17261
		this._trigger( "stop", event );
17262
	},
17263
 
17264
	_setOption: function( key, value ) {
17265
		var prevValue, first, last;
17266
 
17267
		if ( key === "culture" || key === "numberFormat" ) {
17268
			prevValue = this._parse( this.element.val() );
17269
			this.options[ key ] = value;
17270
			this.element.val( this._format( prevValue ) );
17271
			return;
17272
		}
17273
 
17274
		if ( key === "max" || key === "min" || key === "step" ) {
17275
			if ( typeof value === "string" ) {
17276
				value = this._parse( value );
17277
			}
17278
		}
17279
		if ( key === "icons" ) {
17280
			first = this.buttons.first().find( ".ui-icon" );
17281
			this._removeClass( first, null, this.options.icons.up );
17282
			this._addClass( first, null, value.up );
17283
			last = this.buttons.last().find( ".ui-icon" );
17284
			this._removeClass( last, null, this.options.icons.down );
17285
			this._addClass( last, null, value.down );
17286
		}
17287
 
17288
		this._super( key, value );
17289
	},
17290
 
17291
	_setOptionDisabled: function( value ) {
17292
		this._super( value );
17293
 
17294
		this._toggleClass( this.uiSpinner, null, "ui-state-disabled", !!value );
17295
		this.element.prop( "disabled", !!value );
17296
		this.buttons.button( value ? "disable" : "enable" );
17297
	},
17298
 
17299
	_setOptions: spinnerModifier( function( options ) {
17300
		this._super( options );
17301
	} ),
17302
 
17303
	_parse: function( val ) {
17304
		if ( typeof val === "string" && val !== "" ) {
17305
			val = window.Globalize && this.options.numberFormat ?
17306
				Globalize.parseFloat( val, 10, this.options.culture ) : +val;
17307
		}
17308
		return val === "" || isNaN( val ) ? null : val;
17309
	},
17310
 
17311
	_format: function( value ) {
17312
		if ( value === "" ) {
17313
			return "";
17314
		}
17315
		return window.Globalize && this.options.numberFormat ?
17316
			Globalize.format( value, this.options.numberFormat, this.options.culture ) :
17317
			value;
17318
	},
17319
 
17320
	_refresh: function() {
17321
		this.element.attr( {
17322
			"aria-valuemin": this.options.min,
17323
			"aria-valuemax": this.options.max,
17324
 
17325
			// TODO: what should we do with values that can't be parsed?
17326
			"aria-valuenow": this._parse( this.element.val() )
17327
		} );
17328
	},
17329
 
17330
	isValid: function() {
17331
		var value = this.value();
17332
 
17333
		// Null is invalid
17334
		if ( value === null ) {
17335
			return false;
17336
		}
17337
 
17338
		// If value gets adjusted, it's invalid
17339
		return value === this._adjustValue( value );
17340
	},
17341
 
17342
	// Update the value without triggering change
17343
	_value: function( value, allowAny ) {
17344
		var parsed;
17345
		if ( value !== "" ) {
17346
			parsed = this._parse( value );
17347
			if ( parsed !== null ) {
17348
				if ( !allowAny ) {
17349
					parsed = this._adjustValue( parsed );
17350
				}
17351
				value = this._format( parsed );
17352
			}
17353
		}
17354
		this.element.val( value );
17355
		this._refresh();
17356
	},
17357
 
17358
	_destroy: function() {
17359
		this.element
17360
			.prop( "disabled", false )
17361
			.removeAttr( "autocomplete role aria-valuemin aria-valuemax aria-valuenow" );
17362
 
17363
		this.uiSpinner.replaceWith( this.element );
17364
	},
17365
 
17366
	stepUp: spinnerModifier( function( steps ) {
17367
		this._stepUp( steps );
17368
	} ),
17369
	_stepUp: function( steps ) {
17370
		if ( this._start() ) {
17371
			this._spin( ( steps || 1 ) * this.options.step );
17372
			this._stop();
17373
		}
17374
	},
17375
 
17376
	stepDown: spinnerModifier( function( steps ) {
17377
		this._stepDown( steps );
17378
	} ),
17379
	_stepDown: function( steps ) {
17380
		if ( this._start() ) {
17381
			this._spin( ( steps || 1 ) * -this.options.step );
17382
			this._stop();
17383
		}
17384
	},
17385
 
17386
	pageUp: spinnerModifier( function( pages ) {
17387
		this._stepUp( ( pages || 1 ) * this.options.page );
17388
	} ),
17389
 
17390
	pageDown: spinnerModifier( function( pages ) {
17391
		this._stepDown( ( pages || 1 ) * this.options.page );
17392
	} ),
17393
 
17394
	value: function( newVal ) {
17395
		if ( !arguments.length ) {
17396
			return this._parse( this.element.val() );
17397
		}
17398
		spinnerModifier( this._value ).call( this, newVal );
17399
	},
17400
 
17401
	widget: function() {
17402
		return this.uiSpinner;
17403
	}
17404
} );
17405
 
17406
// DEPRECATED
17407
// TODO: switch return back to widget declaration at top of file when this is removed
17408
if ( $.uiBackCompat === true ) {
17409
 
17410
	// Backcompat for spinner html extension points
17411
	$.widget( "ui.spinner", $.ui.spinner, {
17412
		_enhance: function() {
17413
			this.uiSpinner = this.element
17414
				.attr( "autocomplete", "off" )
17415
				.wrap( this._uiSpinnerHtml() )
17416
				.parent()
17417
 
17418
					// Add buttons
17419
					.append( this._buttonHtml() );
17420
		},
17421
		_uiSpinnerHtml: function() {
17422
			return "<span>";
17423
		},
17424
 
17425
		_buttonHtml: function() {
17426
			return "<a></a><a></a>";
17427
		}
17428
	} );
17429
}
17430
 
17431
var widgetsSpinner = $.ui.spinner;
17432
 
17433
 
17434
/*!
17435
 * jQuery UI Tabs 1.14.1
17436
 * https://jqueryui.com
17437
 *
17438
 * Copyright OpenJS Foundation and other contributors
17439
 * Released under the MIT license.
17440
 * https://jquery.org/license
17441
 */
17442
 
17443
//>>label: Tabs
17444
//>>group: Widgets
17445
//>>description: Transforms a set of container elements into a tab structure.
17446
//>>docs: https://api.jqueryui.com/tabs/
17447
//>>demos: https://jqueryui.com/tabs/
17448
//>>css.structure: ../../themes/base/core.css
17449
//>>css.structure: ../../themes/base/tabs.css
17450
//>>css.theme: ../../themes/base/theme.css
17451
 
17452
 
17453
$.widget( "ui.tabs", {
17454
	version: "1.14.1",
17455
	delay: 300,
17456
	options: {
17457
		active: null,
17458
		classes: {
17459
			"ui-tabs": "ui-corner-all",
17460
			"ui-tabs-nav": "ui-corner-all",
17461
			"ui-tabs-panel": "ui-corner-bottom",
17462
			"ui-tabs-tab": "ui-corner-top"
17463
		},
17464
		collapsible: false,
17465
		event: "click",
17466
		heightStyle: "content",
17467
		hide: null,
17468
		show: null,
17469
 
17470
		// Callbacks
17471
		activate: null,
17472
		beforeActivate: null,
17473
		beforeLoad: null,
17474
		load: null
17475
	},
17476
 
17477
	_isLocal: ( function() {
17478
		var rhash = /#.*$/;
17479
 
17480
		return function( anchor ) {
17481
			var anchorUrl, locationUrl;
17482
 
17483
			anchorUrl = anchor.href.replace( rhash, "" );
17484
			locationUrl = location.href.replace( rhash, "" );
17485
 
17486
			// Decoding may throw an error if the URL isn't UTF-8 (#9518)
17487
			try {
17488
				anchorUrl = decodeURIComponent( anchorUrl );
17489
			} catch ( error ) {}
17490
			try {
17491
				locationUrl = decodeURIComponent( locationUrl );
17492
			} catch ( error ) {}
17493
 
17494
			return anchor.hash.length > 1 && anchorUrl === locationUrl;
17495
		};
17496
	} )(),
17497
 
17498
	_create: function() {
17499
		var that = this,
17500
			options = this.options;
17501
 
17502
		this.running = false;
17503
 
17504
		this._addClass( "ui-tabs", "ui-widget ui-widget-content" );
17505
		this._toggleClass( "ui-tabs-collapsible", null, options.collapsible );
17506
 
17507
		this._processTabs();
17508
		options.active = this._initialActive();
17509
 
17510
		// Take disabling tabs via class attribute from HTML
17511
		// into account and update option properly.
17512
		if ( Array.isArray( options.disabled ) ) {
17513
			options.disabled = $.uniqueSort( options.disabled.concat(
17514
				$.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) {
17515
					return that.tabs.index( li );
17516
				} )
17517
			) ).sort();
17518
		}
17519
 
17520
		// Check for length avoids error when initializing empty list
17521
		if ( this.options.active !== false && this.anchors.length ) {
17522
			this.active = this._findActive( options.active );
17523
		} else {
17524
			this.active = $();
17525
		}
17526
 
17527
		this._refresh();
17528
 
17529
		if ( this.active.length ) {
17530
			this.load( options.active );
17531
		}
17532
	},
17533
 
17534
	_initialActive: function() {
17535
		var active = this.options.active,
17536
			collapsible = this.options.collapsible,
17537
			locationHashDecoded = decodeURIComponent( location.hash.substring( 1 ) );
17538
 
17539
		if ( active === null ) {
17540
 
17541
			// check the fragment identifier in the URL
17542
			if ( locationHashDecoded ) {
17543
				this.tabs.each( function( i, tab ) {
17544
					if ( $( tab ).attr( "aria-controls" ) === locationHashDecoded ) {
17545
						active = i;
17546
						return false;
17547
					}
17548
				} );
17549
			}
17550
 
17551
			// Check for a tab marked active via a class
17552
			if ( active === null ) {
17553
				active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) );
17554
			}
17555
 
17556
			// No active tab, set to false
17557
			if ( active === null || active === -1 ) {
17558
				active = this.tabs.length ? 0 : false;
17559
			}
17560
		}
17561
 
17562
		// Handle numbers: negative, out of range
17563
		if ( active !== false ) {
17564
			active = this.tabs.index( this.tabs.eq( active ) );
17565
			if ( active === -1 ) {
17566
				active = collapsible ? false : 0;
17567
			}
17568
		}
17569
 
17570
		// Don't allow collapsible: false and active: false
17571
		if ( !collapsible && active === false && this.anchors.length ) {
17572
			active = 0;
17573
		}
17574
 
17575
		return active;
17576
	},
17577
 
17578
	_getCreateEventData: function() {
17579
		return {
17580
			tab: this.active,
17581
			panel: !this.active.length ? $() : this._getPanelForTab( this.active )
17582
		};
17583
	},
17584
 
17585
	_tabKeydown: function( event ) {
17586
		var focusedTab = $( this.document[ 0 ].activeElement ).closest( "li" ),
17587
			selectedIndex = this.tabs.index( focusedTab ),
17588
			goingForward = true;
17589
 
17590
		if ( this._handlePageNav( event ) ) {
17591
			return;
17592
		}
17593
 
17594
		switch ( event.keyCode ) {
17595
		case $.ui.keyCode.RIGHT:
17596
		case $.ui.keyCode.DOWN:
17597
			selectedIndex++;
17598
			break;
17599
		case $.ui.keyCode.UP:
17600
		case $.ui.keyCode.LEFT:
17601
			goingForward = false;
17602
			selectedIndex--;
17603
			break;
17604
		case $.ui.keyCode.END:
17605
			selectedIndex = this.anchors.length - 1;
17606
			break;
17607
		case $.ui.keyCode.HOME:
17608
			selectedIndex = 0;
17609
			break;
17610
		case $.ui.keyCode.SPACE:
17611
 
17612
			// Activate only, no collapsing
17613
			event.preventDefault();
17614
			clearTimeout( this.activating );
17615
			this._activate( selectedIndex );
17616
			return;
17617
		case $.ui.keyCode.ENTER:
17618
 
17619
			// Toggle (cancel delayed activation, allow collapsing)
17620
			event.preventDefault();
17621
			clearTimeout( this.activating );
17622
 
17623
			// Determine if we should collapse or activate
17624
			this._activate( selectedIndex === this.options.active ? false : selectedIndex );
17625
			return;
17626
		default:
17627
			return;
17628
		}
17629
 
17630
		// Focus the appropriate tab, based on which key was pressed
17631
		event.preventDefault();
17632
		clearTimeout( this.activating );
17633
		selectedIndex = this._focusNextTab( selectedIndex, goingForward );
17634
 
17635
		// Navigating with control/command key will prevent automatic activation
17636
		if ( !event.ctrlKey && !event.metaKey ) {
17637
 
17638
			// Update aria-selected immediately so that AT think the tab is already selected.
17639
			// Otherwise AT may confuse the user by stating that they need to activate the tab,
17640
			// but the tab will already be activated by the time the announcement finishes.
17641
			focusedTab.attr( "aria-selected", "false" );
17642
			this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" );
17643
 
17644
			this.activating = this._delay( function() {
17645
				this.option( "active", selectedIndex );
17646
			}, this.delay );
17647
		}
17648
	},
17649
 
17650
	_panelKeydown: function( event ) {
17651
		if ( this._handlePageNav( event ) ) {
17652
			return;
17653
		}
17654
 
17655
		// Ctrl+up moves focus to the current tab
17656
		if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) {
17657
			event.preventDefault();
17658
			this.active.trigger( "focus" );
17659
		}
17660
	},
17661
 
17662
	// Alt+page up/down moves focus to the previous/next tab (and activates)
17663
	_handlePageNav: function( event ) {
17664
		if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) {
17665
			this._activate( this._focusNextTab( this.options.active - 1, false ) );
17666
			return true;
17667
		}
17668
		if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) {
17669
			this._activate( this._focusNextTab( this.options.active + 1, true ) );
17670
			return true;
17671
		}
17672
	},
17673
 
17674
	_findNextTab: function( index, goingForward ) {
17675
		var lastTabIndex = this.tabs.length - 1;
17676
 
17677
		function constrain() {
17678
			if ( index > lastTabIndex ) {
17679
				index = 0;
17680
			}
17681
			if ( index < 0 ) {
17682
				index = lastTabIndex;
17683
			}
17684
			return index;
17685
		}
17686
 
17687
		while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) {
17688
			index = goingForward ? index + 1 : index - 1;
17689
		}
17690
 
17691
		return index;
17692
	},
17693
 
17694
	_focusNextTab: function( index, goingForward ) {
17695
		index = this._findNextTab( index, goingForward );
17696
		this.tabs.eq( index ).trigger( "focus" );
17697
		return index;
17698
	},
17699
 
17700
	_setOption: function( key, value ) {
17701
		if ( key === "active" ) {
17702
 
17703
			// _activate() will handle invalid values and update this.options
17704
			this._activate( value );
17705
			return;
17706
		}
17707
 
17708
		this._super( key, value );
17709
 
17710
		if ( key === "collapsible" ) {
17711
			this._toggleClass( "ui-tabs-collapsible", null, value );
17712
 
17713
			// Setting collapsible: false while collapsed; open first panel
17714
			if ( !value && this.options.active === false ) {
17715
				this._activate( 0 );
17716
			}
17717
		}
17718
 
17719
		if ( key === "event" ) {
17720
			this._setupEvents( value );
17721
		}
17722
 
17723
		if ( key === "heightStyle" ) {
17724
			this._setupHeightStyle( value );
17725
		}
17726
	},
17727
 
17728
	refresh: function() {
17729
		var options = this.options,
17730
			lis = this.tablist.children( ":has(a[href])" );
17731
 
17732
		// Get disabled tabs from class attribute from HTML
17733
		// this will get converted to a boolean if needed in _refresh()
17734
		options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) {
17735
			return lis.index( tab );
17736
		} );
17737
 
17738
		this._processTabs();
17739
 
17740
		// Was collapsed or no tabs
17741
		if ( options.active === false || !this.anchors.length ) {
17742
			options.active = false;
17743
			this.active = $();
17744
 
17745
		// was active, but active tab is gone
17746
		} else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) {
17747
 
17748
			// all remaining tabs are disabled
17749
			if ( this.tabs.length === options.disabled.length ) {
17750
				options.active = false;
17751
				this.active = $();
17752
 
17753
			// activate previous tab
17754
			} else {
17755
				this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) );
17756
			}
17757
 
17758
		// was active, active tab still exists
17759
		} else {
17760
 
17761
			// make sure active index is correct
17762
			options.active = this.tabs.index( this.active );
17763
		}
17764
 
17765
		this._refresh();
17766
	},
17767
 
17768
	_refresh: function() {
17769
		this._setOptionDisabled( this.options.disabled );
17770
		this._setupEvents( this.options.event );
17771
		this._setupHeightStyle( this.options.heightStyle );
17772
 
17773
		this.tabs.not( this.active ).attr( {
17774
			"aria-selected": "false",
17775
			"aria-expanded": "false",
17776
			tabIndex: -1
17777
		} );
17778
		this.panels.not( this._getPanelForTab( this.active ) )
17779
			.hide()
17780
			.attr( {
17781
				"aria-hidden": "true"
17782
			} );
17783
 
17784
		// Make sure one tab is in the tab order
17785
		if ( !this.active.length ) {
17786
			this.tabs.eq( 0 ).attr( "tabIndex", 0 );
17787
		} else {
17788
			this.active
17789
				.attr( {
17790
					"aria-selected": "true",
17791
					"aria-expanded": "true",
17792
					tabIndex: 0
17793
				} );
17794
			this._addClass( this.active, "ui-tabs-active", "ui-state-active" );
17795
			this._getPanelForTab( this.active )
17796
				.show()
17797
				.attr( {
17798
					"aria-hidden": "false"
17799
				} );
17800
		}
17801
	},
17802
 
17803
	_processTabs: function() {
17804
		var that = this,
17805
			prevTabs = this.tabs,
17806
			prevAnchors = this.anchors,
17807
			prevPanels = this.panels;
17808
 
17809
		this.tablist = this._getList().attr( "role", "tablist" );
17810
		this._addClass( this.tablist, "ui-tabs-nav",
17811
			"ui-helper-reset ui-helper-clearfix ui-widget-header" );
17812
 
17813
		// Prevent users from focusing disabled tabs via click
17814
		this.tablist
17815
			.on( "mousedown" + this.eventNamespace, "> li", function( event ) {
17816
				if ( $( this ).is( ".ui-state-disabled" ) ) {
17817
					event.preventDefault();
17818
				}
17819
			} );
17820
 
17821
		this.tabs = this.tablist.find( "> li:has(a[href])" )
17822
			.attr( {
17823
				role: "tab",
17824
				tabIndex: -1
17825
			} );
17826
		this._addClass( this.tabs, "ui-tabs-tab", "ui-state-default" );
17827
 
17828
		this.anchors = this.tabs.map( function() {
17829
			return $( "a", this )[ 0 ];
17830
		} )
17831
			.attr( {
17832
				tabIndex: -1
17833
			} );
17834
		this._addClass( this.anchors, "ui-tabs-anchor" );
17835
 
17836
		this.panels = $();
17837
 
17838
		this.anchors.each( function( i, anchor ) {
17839
			var selector, panel, panelId,
17840
				anchorId = $( anchor ).uniqueId().attr( "id" ),
17841
				tab = $( anchor ).closest( "li" ),
17842
				originalAriaControls = tab.attr( "aria-controls" );
17843
 
17844
			// Inline tab
17845
			if ( that._isLocal( anchor ) ) {
17846
				selector = decodeURIComponent( anchor.hash );
17847
				panelId = selector.substring( 1 );
17848
				panel = that.element.find( "#" + CSS.escape( panelId ) );
17849
 
17850
			// remote tab
17851
			} else {
17852
 
17853
				// If the tab doesn't already have aria-controls,
17854
				// generate an id by using a throw-away element
17855
				panelId = tab.attr( "aria-controls" ) || $( {} ).uniqueId()[ 0 ].id;
17856
				selector = "#" + panelId;
17857
				panel = that.element.find( selector );
17858
				if ( !panel.length ) {
17859
					panel = that._createPanel( panelId );
17860
					panel.insertAfter( that.panels[ i - 1 ] || that.tablist );
17861
				}
17862
				panel.attr( "aria-live", "polite" );
17863
			}
17864
 
17865
			if ( panel.length ) {
17866
				that.panels = that.panels.add( panel );
17867
			}
17868
			if ( originalAriaControls ) {
17869
				tab.data( "ui-tabs-aria-controls", originalAriaControls );
17870
			}
17871
			tab.attr( {
17872
				"aria-controls": panelId,
17873
				"aria-labelledby": anchorId
17874
			} );
17875
			panel.attr( "aria-labelledby", anchorId );
17876
		} );
17877
 
17878
		this.panels.attr( "role", "tabpanel" );
17879
		this._addClass( this.panels, "ui-tabs-panel", "ui-widget-content" );
17880
 
17881
		// Avoid memory leaks (#10056)
17882
		if ( prevTabs ) {
17883
			this._off( prevTabs.not( this.tabs ) );
17884
			this._off( prevAnchors.not( this.anchors ) );
17885
			this._off( prevPanels.not( this.panels ) );
17886
		}
17887
	},
17888
 
17889
	// Allow overriding how to find the list for rare usage scenarios (#7715)
17890
	_getList: function() {
17891
		return this.tablist || this.element.find( "ol, ul" ).eq( 0 );
17892
	},
17893
 
17894
	_createPanel: function( id ) {
17895
		return $( "<div>" )
17896
			.attr( "id", id )
17897
			.data( "ui-tabs-destroy", true );
17898
	},
17899
 
17900
	_setOptionDisabled: function( disabled ) {
17901
		var currentItem, li, i;
17902
 
17903
		if ( Array.isArray( disabled ) ) {
17904
			if ( !disabled.length ) {
17905
				disabled = false;
17906
			} else if ( disabled.length === this.anchors.length ) {
17907
				disabled = true;
17908
			}
17909
		}
17910
 
17911
		// Disable tabs
17912
		for ( i = 0; ( li = this.tabs[ i ] ); i++ ) {
17913
			currentItem = $( li );
17914
			if ( disabled === true || $.inArray( i, disabled ) !== -1 ) {
17915
				currentItem.attr( "aria-disabled", "true" );
17916
				this._addClass( currentItem, null, "ui-state-disabled" );
17917
			} else {
17918
				currentItem.removeAttr( "aria-disabled" );
17919
				this._removeClass( currentItem, null, "ui-state-disabled" );
17920
			}
17921
		}
17922
 
17923
		this.options.disabled = disabled;
17924
 
17925
		this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null,
17926
			disabled === true );
17927
	},
17928
 
17929
	_setupEvents: function( event ) {
17930
		var events = {};
17931
		if ( event ) {
17932
			$.each( event.split( " " ), function( index, eventName ) {
17933
				events[ eventName ] = "_eventHandler";
17934
			} );
17935
		}
17936
 
17937
		this._off( this.anchors.add( this.tabs ).add( this.panels ) );
17938
 
17939
		// Always prevent the default action, even when disabled
17940
		this._on( true, this.anchors, {
17941
			click: function( event ) {
17942
				event.preventDefault();
17943
			}
17944
		} );
17945
		this._on( this.anchors, events );
17946
		this._on( this.tabs, { keydown: "_tabKeydown" } );
17947
		this._on( this.panels, { keydown: "_panelKeydown" } );
17948
 
17949
		this._focusable( this.tabs );
17950
		this._hoverable( this.tabs );
17951
	},
17952
 
17953
	_setupHeightStyle: function( heightStyle ) {
17954
		var maxHeight,
17955
			parent = this.element.parent();
17956
 
17957
		if ( heightStyle === "fill" ) {
17958
			maxHeight = parent.height();
17959
			maxHeight -= this.element.outerHeight() - this.element.height();
17960
 
17961
			this.element.siblings( ":visible" ).each( function() {
17962
				var elem = $( this ),
17963
					position = elem.css( "position" );
17964
 
17965
				if ( position === "absolute" || position === "fixed" ) {
17966
					return;
17967
				}
17968
				maxHeight -= elem.outerHeight( true );
17969
			} );
17970
 
17971
			this.element.children().not( this.panels ).each( function() {
17972
				maxHeight -= $( this ).outerHeight( true );
17973
			} );
17974
 
17975
			this.panels.each( function() {
17976
				$( this ).height( Math.max( 0, maxHeight -
17977
					$( this ).innerHeight() + $( this ).height() ) );
17978
			} )
17979
				.css( "overflow", "auto" );
17980
		} else if ( heightStyle === "auto" ) {
17981
			maxHeight = 0;
17982
			this.panels.each( function() {
17983
				maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
17984
			} ).height( maxHeight );
17985
		}
17986
	},
17987
 
17988
	_eventHandler: function( event ) {
17989
		var options = this.options,
17990
			active = this.active,
17991
			anchor = $( event.currentTarget ),
17992
			tab = anchor.closest( "li" ),
17993
			clickedIsActive = tab[ 0 ] === active[ 0 ],
17994
			collapsing = clickedIsActive && options.collapsible,
17995
			toShow = collapsing ? $() : this._getPanelForTab( tab ),
17996
			toHide = !active.length ? $() : this._getPanelForTab( active ),
17997
			eventData = {
17998
				oldTab: active,
17999
				oldPanel: toHide,
18000
				newTab: collapsing ? $() : tab,
18001
				newPanel: toShow
18002
			};
18003
 
18004
		event.preventDefault();
18005
 
18006
		if ( tab.hasClass( "ui-state-disabled" ) ||
18007
 
18008
				// tab is already loading
18009
				tab.hasClass( "ui-tabs-loading" ) ||
18010
 
18011
				// can't switch durning an animation
18012
				this.running ||
18013
 
18014
				// click on active header, but not collapsible
18015
				( clickedIsActive && !options.collapsible ) ||
18016
 
18017
				// allow canceling activation
18018
				( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
18019
			return;
18020
		}
18021
 
18022
		options.active = collapsing ? false : this.tabs.index( tab );
18023
 
18024
		this.active = clickedIsActive ? $() : tab;
18025
		if ( this.xhr ) {
18026
			this.xhr.abort();
18027
		}
18028
 
18029
		if ( !toHide.length && !toShow.length ) {
18030
			$.error( "jQuery UI Tabs: Mismatching fragment identifier." );
18031
		}
18032
 
18033
		if ( toShow.length ) {
18034
			this.load( this.tabs.index( tab ), event );
18035
		}
18036
		this._toggle( event, eventData );
18037
	},
18038
 
18039
	// Handles show/hide for selecting tabs
18040
	_toggle: function( event, eventData ) {
18041
		var that = this,
18042
			toShow = eventData.newPanel,
18043
			toHide = eventData.oldPanel;
18044
 
18045
		this.running = true;
18046
 
18047
		function complete() {
18048
			that.running = false;
18049
			that._trigger( "activate", event, eventData );
18050
		}
18051
 
18052
		function show() {
18053
			that._addClass( eventData.newTab.closest( "li" ), "ui-tabs-active", "ui-state-active" );
18054
 
18055
			if ( toShow.length && that.options.show ) {
18056
				that._show( toShow, that.options.show, complete );
18057
			} else {
18058
				toShow.show();
18059
				complete();
18060
			}
18061
		}
18062
 
18063
		// Start out by hiding, then showing, then completing
18064
		if ( toHide.length && this.options.hide ) {
18065
			this._hide( toHide, this.options.hide, function() {
18066
				that._removeClass( eventData.oldTab.closest( "li" ),
18067
					"ui-tabs-active", "ui-state-active" );
18068
				show();
18069
			} );
18070
		} else {
18071
			this._removeClass( eventData.oldTab.closest( "li" ),
18072
				"ui-tabs-active", "ui-state-active" );
18073
			toHide.hide();
18074
			show();
18075
		}
18076
 
18077
		toHide.attr( "aria-hidden", "true" );
18078
		eventData.oldTab.attr( {
18079
			"aria-selected": "false",
18080
			"aria-expanded": "false"
18081
		} );
18082
 
18083
		// If we're switching tabs, remove the old tab from the tab order.
18084
		// If we're opening from collapsed state, remove the previous tab from the tab order.
18085
		// If we're collapsing, then keep the collapsing tab in the tab order.
18086
		if ( toShow.length && toHide.length ) {
18087
			eventData.oldTab.attr( "tabIndex", -1 );
18088
		} else if ( toShow.length ) {
18089
			this.tabs.filter( function() {
18090
				return $( this ).attr( "tabIndex" ) === 0;
18091
			} )
18092
				.attr( "tabIndex", -1 );
18093
		}
18094
 
18095
		toShow.attr( "aria-hidden", "false" );
18096
		eventData.newTab.attr( {
18097
			"aria-selected": "true",
18098
			"aria-expanded": "true",
18099
			tabIndex: 0
18100
		} );
18101
	},
18102
 
18103
	_activate: function( index ) {
18104
		var anchor,
18105
			active = this._findActive( index );
18106
 
18107
		// Trying to activate the already active panel
18108
		if ( active[ 0 ] === this.active[ 0 ] ) {
18109
			return;
18110
		}
18111
 
18112
		// Trying to collapse, simulate a click on the current active header
18113
		if ( !active.length ) {
18114
			active = this.active;
18115
		}
18116
 
18117
		anchor = active.find( ".ui-tabs-anchor" )[ 0 ];
18118
		this._eventHandler( {
18119
			target: anchor,
18120
			currentTarget: anchor,
18121
			preventDefault: $.noop
18122
		} );
18123
	},
18124
 
18125
	_findActive: function( index ) {
18126
		return index === false ? $() : this.tabs.eq( index );
18127
	},
18128
 
18129
	_getIndex: function( index ) {
18130
 
18131
		// meta-function to give users option to provide a href string instead of a numerical index.
18132
		if ( typeof index === "string" ) {
18133
			index = this.anchors.index( this.anchors.filter( "[href$='" +
18134
				CSS.escape( index ) + "']" ) );
18135
		}
18136
 
18137
		return index;
18138
	},
18139
 
18140
	_destroy: function() {
18141
		if ( this.xhr ) {
18142
			this.xhr.abort();
18143
		}
18144
 
18145
		this.tablist
18146
			.removeAttr( "role" )
18147
			.off( this.eventNamespace );
18148
 
18149
		this.anchors
18150
			.removeAttr( "role tabIndex" )
18151
			.removeUniqueId();
18152
 
18153
		this.tabs.add( this.panels ).each( function() {
18154
			if ( $.data( this, "ui-tabs-destroy" ) ) {
18155
				$( this ).remove();
18156
			} else {
18157
				$( this ).removeAttr( "role tabIndex " +
18158
					"aria-live aria-busy aria-selected aria-labelledby aria-hidden aria-expanded" );
18159
			}
18160
		} );
18161
 
18162
		this.tabs.each( function() {
18163
			var li = $( this ),
18164
				prev = li.data( "ui-tabs-aria-controls" );
18165
			if ( prev ) {
18166
				li
18167
					.attr( "aria-controls", prev )
18168
					.removeData( "ui-tabs-aria-controls" );
18169
			} else {
18170
				li.removeAttr( "aria-controls" );
18171
			}
18172
		} );
18173
 
18174
		this.panels.show();
18175
 
18176
		if ( this.options.heightStyle !== "content" ) {
18177
			this.panels.css( "height", "" );
18178
		}
18179
	},
18180
 
18181
	enable: function( index ) {
18182
		var disabled = this.options.disabled;
18183
		if ( disabled === false ) {
18184
			return;
18185
		}
18186
 
18187
		if ( index === undefined ) {
18188
			disabled = false;
18189
		} else {
18190
			index = this._getIndex( index );
18191
			if ( Array.isArray( disabled ) ) {
18192
				disabled = $.map( disabled, function( num ) {
18193
					return num !== index ? num : null;
18194
				} );
18195
			} else {
18196
				disabled = $.map( this.tabs, function( li, num ) {
18197
					return num !== index ? num : null;
18198
				} );
18199
			}
18200
		}
18201
		this._setOptionDisabled( disabled );
18202
	},
18203
 
18204
	disable: function( index ) {
18205
		var disabled = this.options.disabled;
18206
		if ( disabled === true ) {
18207
			return;
18208
		}
18209
 
18210
		if ( index === undefined ) {
18211
			disabled = true;
18212
		} else {
18213
			index = this._getIndex( index );
18214
			if ( $.inArray( index, disabled ) !== -1 ) {
18215
				return;
18216
			}
18217
			if ( Array.isArray( disabled ) ) {
18218
				disabled = $.merge( [ index ], disabled ).sort();
18219
			} else {
18220
				disabled = [ index ];
18221
			}
18222
		}
18223
		this._setOptionDisabled( disabled );
18224
	},
18225
 
18226
	load: function( index, event ) {
18227
		index = this._getIndex( index );
18228
		var that = this,
18229
			tab = this.tabs.eq( index ),
18230
			anchor = tab.find( ".ui-tabs-anchor" ),
18231
			panel = this._getPanelForTab( tab ),
18232
			eventData = {
18233
				tab: tab,
18234
				panel: panel
18235
			},
18236
			complete = function( jqXHR, status ) {
18237
				if ( status === "abort" ) {
18238
					that.panels.stop( false, true );
18239
				}
18240
 
18241
				that._removeClass( tab, "ui-tabs-loading" );
18242
				panel.removeAttr( "aria-busy" );
18243
 
18244
				if ( jqXHR === that.xhr ) {
18245
					delete that.xhr;
18246
				}
18247
			};
18248
 
18249
		// Not remote
18250
		if ( this._isLocal( anchor[ 0 ] ) ) {
18251
			return;
18252
		}
18253
 
18254
		this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) );
18255
 
18256
		if ( this.xhr.statusText !== "canceled" ) {
18257
			this._addClass( tab, "ui-tabs-loading" );
18258
			panel.attr( "aria-busy", "true" );
18259
 
18260
			this.xhr
18261
				.done( function( response, status, jqXHR ) {
18262
					panel.html( response );
18263
					that._trigger( "load", event, eventData );
18264
 
18265
					complete( jqXHR, status );
18266
				} )
18267
				.fail( function( jqXHR, status ) {
18268
					complete( jqXHR, status );
18269
				} );
18270
		}
18271
	},
18272
 
18273
	_ajaxSettings: function( anchor, event, eventData ) {
18274
		var that = this;
18275
		return {
18276
			url: anchor.attr( "href" ),
18277
			beforeSend: function( jqXHR, settings ) {
18278
				return that._trigger( "beforeLoad", event,
18279
					$.extend( { jqXHR: jqXHR, ajaxSettings: settings }, eventData ) );
18280
			}
18281
		};
18282
	},
18283
 
18284
	_getPanelForTab: function( tab ) {
18285
		var id = $( tab ).attr( "aria-controls" );
18286
		return this.element.find( "#" + CSS.escape( id ) );
18287
	}
18288
} );
18289
 
18290
// DEPRECATED
18291
// TODO: Switch return back to widget declaration at top of file when this is removed
18292
if ( $.uiBackCompat === true ) {
18293
 
18294
	// Backcompat for ui-tab class (now ui-tabs-tab)
18295
	$.widget( "ui.tabs", $.ui.tabs, {
18296
		_processTabs: function() {
18297
			this._superApply( arguments );
18298
			this._addClass( this.tabs, "ui-tab" );
18299
		}
18300
	} );
18301
}
18302
 
18303
var widgetsTabs = $.ui.tabs;
18304
 
18305
 
18306
/*!
18307
 * jQuery UI Tooltip 1.14.1
18308
 * https://jqueryui.com
18309
 *
18310
 * Copyright OpenJS Foundation and other contributors
18311
 * Released under the MIT license.
18312
 * https://jquery.org/license
18313
 */
18314
 
18315
//>>label: Tooltip
18316
//>>group: Widgets
18317
//>>description: Shows additional information for any element on hover or focus.
18318
//>>docs: https://api.jqueryui.com/tooltip/
18319
//>>demos: https://jqueryui.com/tooltip/
18320
//>>css.structure: ../../themes/base/core.css
18321
//>>css.structure: ../../themes/base/tooltip.css
18322
//>>css.theme: ../../themes/base/theme.css
18323
 
18324
 
18325
$.widget( "ui.tooltip", {
18326
	version: "1.14.1",
18327
	options: {
18328
		classes: {
18329
			"ui-tooltip": "ui-corner-all ui-widget-shadow"
18330
		},
18331
		content: function() {
18332
			var title = $( this ).attr( "title" );
18333
 
18334
			// Escape title, since we're going from an attribute to raw HTML
18335
			return $( "<a>" ).text( title ).html();
18336
		},
18337
		hide: true,
18338
 
18339
		// Disabled elements have inconsistent behavior across browsers (#8661)
18340
		items: "[title]:not([disabled])",
18341
		position: {
18342
			my: "left top+15",
18343
			at: "left bottom",
18344
			collision: "flipfit flip"
18345
		},
18346
		show: true,
18347
		track: false,
18348
 
18349
		// Callbacks
18350
		close: null,
18351
		open: null
18352
	},
18353
 
18354
	_addDescribedBy: function( elem, id ) {
18355
		var describedby = ( elem.attr( "aria-describedby" ) || "" ).split( /\s+/ );
18356
		describedby.push( id );
18357
		elem
18358
			.data( "ui-tooltip-id", id )
18359
			.attr( "aria-describedby", String.prototype.trim.call( describedby.join( " " ) ) );
18360
	},
18361
 
18362
	_removeDescribedBy: function( elem ) {
18363
		var id = elem.data( "ui-tooltip-id" ),
18364
			describedby = ( elem.attr( "aria-describedby" ) || "" ).split( /\s+/ ),
18365
			index = $.inArray( id, describedby );
18366
 
18367
		if ( index !== -1 ) {
18368
			describedby.splice( index, 1 );
18369
		}
18370
 
18371
		elem.removeData( "ui-tooltip-id" );
18372
		describedby = String.prototype.trim.call( describedby.join( " " ) );
18373
		if ( describedby ) {
18374
			elem.attr( "aria-describedby", describedby );
18375
		} else {
18376
			elem.removeAttr( "aria-describedby" );
18377
		}
18378
	},
18379
 
18380
	_create: function() {
18381
		this._on( {
18382
			mouseover: "open",
18383
			focusin: "open"
18384
		} );
18385
 
18386
		// IDs of generated tooltips, needed for destroy
18387
		this.tooltips = {};
18388
 
18389
		// IDs of parent tooltips where we removed the title attribute
18390
		this.parents = {};
18391
 
18392
		// Append the aria-live region so tooltips announce correctly
18393
		this.liveRegion = $( "<div>" )
18394
			.attr( {
18395
				role: "log",
18396
				"aria-live": "assertive",
18397
				"aria-relevant": "additions"
18398
			} )
18399
			.appendTo( this.document[ 0 ].body );
18400
		this._addClass( this.liveRegion, null, "ui-helper-hidden-accessible" );
18401
 
18402
		this.disabledTitles = $( [] );
18403
	},
18404
 
18405
	_setOption: function( key, value ) {
18406
		var that = this;
18407
 
18408
		this._super( key, value );
18409
 
18410
		if ( key === "content" ) {
18411
			$.each( this.tooltips, function( id, tooltipData ) {
18412
				that._updateContent( tooltipData.element );
18413
			} );
18414
		}
18415
	},
18416
 
18417
	_setOptionDisabled: function( value ) {
18418
		this[ value ? "_disable" : "_enable" ]();
18419
	},
18420
 
18421
	_disable: function() {
18422
		var that = this;
18423
 
18424
		// Close open tooltips
18425
		$.each( this.tooltips, function( id, tooltipData ) {
18426
			var event = $.Event( "blur" );
18427
			event.target = event.currentTarget = tooltipData.element[ 0 ];
18428
			that.close( event, true );
18429
		} );
18430
 
18431
		// Remove title attributes to prevent native tooltips
18432
		this.disabledTitles = this.disabledTitles.add(
18433
			this.element.find( this.options.items ).addBack()
18434
				.filter( function() {
18435
					var element = $( this );
18436
					if ( element.is( "[title]" ) ) {
18437
						return element
18438
							.data( "ui-tooltip-title", element.attr( "title" ) )
18439
							.removeAttr( "title" );
18440
					}
18441
				} )
18442
		);
18443
	},
18444
 
18445
	_enable: function() {
18446
 
18447
		// restore title attributes
18448
		this.disabledTitles.each( function() {
18449
			var element = $( this );
18450
			if ( element.data( "ui-tooltip-title" ) ) {
18451
				element.attr( "title", element.data( "ui-tooltip-title" ) );
18452
			}
18453
		} );
18454
		this.disabledTitles = $( [] );
18455
	},
18456
 
18457
	open: function( event ) {
18458
		var that = this,
18459
			target = $( event ? event.target : this.element )
18460
 
18461
				// we need closest here due to mouseover bubbling,
18462
				// but always pointing at the same event target
18463
				.closest( this.options.items );
18464
 
18465
		// No element to show a tooltip for or the tooltip is already open
18466
		if ( !target.length || target.data( "ui-tooltip-id" ) ) {
18467
			return;
18468
		}
18469
 
18470
		if ( target.attr( "title" ) ) {
18471
			target.data( "ui-tooltip-title", target.attr( "title" ) );
18472
		}
18473
 
18474
		target.data( "ui-tooltip-open", true );
18475
 
18476
		// Kill parent tooltips, custom or native, for hover
18477
		if ( event && event.type === "mouseover" ) {
18478
			target.parents().each( function() {
18479
				var parent = $( this ),
18480
					blurEvent;
18481
				if ( parent.data( "ui-tooltip-open" ) ) {
18482
					blurEvent = $.Event( "blur" );
18483
					blurEvent.target = blurEvent.currentTarget = this;
18484
					that.close( blurEvent, true );
18485
				}
18486
				if ( parent.attr( "title" ) ) {
18487
					parent.uniqueId();
18488
					that.parents[ this.id ] = {
18489
						element: this,
18490
						title: parent.attr( "title" )
18491
					};
18492
					parent.attr( "title", "" );
18493
				}
18494
			} );
18495
		}
18496
 
18497
		this._registerCloseHandlers( event, target );
18498
		this._updateContent( target, event );
18499
	},
18500
 
18501
	_updateContent: function( target, event ) {
18502
		var content,
18503
			contentOption = this.options.content,
18504
			that = this,
18505
			eventType = event ? event.type : null;
18506
 
18507
		if ( typeof contentOption === "string" || contentOption.nodeType ||
18508
				contentOption.jquery ) {
18509
			return this._open( event, target, contentOption );
18510
		}
18511
 
18512
		content = contentOption.call( target[ 0 ], function( response ) {
18513
 
18514
			// Ignore async response if tooltip was closed already
18515
			if ( !target.data( "ui-tooltip-open" ) ) {
18516
				return;
18517
			}
18518
 
18519
			// JQuery creates a special event for focusin when it doesn't
18520
			// exist natively. To improve performance, the native event
18521
			// object is reused and the type is changed. Therefore, we can't
18522
			// rely on the type being correct after the event finished
18523
			// bubbling, so we set it back to the previous value. (#8740)
18524
			if ( event ) {
18525
				event.type = eventType;
18526
			}
18527
			that._open( event, target, response );
18528
		} );
18529
		if ( content ) {
18530
			this._open( event, target, content );
18531
		}
18532
	},
18533
 
18534
	_open: function( event, target, content ) {
18535
		var tooltipData, tooltip, delayedShow, a11yContent,
18536
			positionOption = $.extend( {}, this.options.position );
18537
 
18538
		if ( !content ) {
18539
			return;
18540
		}
18541
 
18542
		// Content can be updated multiple times. If the tooltip already
18543
		// exists, then just update the content and bail.
18544
		tooltipData = this._find( target );
18545
		if ( tooltipData ) {
18546
			tooltipData.tooltip.find( ".ui-tooltip-content" ).html( content );
18547
			return;
18548
		}
18549
 
18550
		// If we have a title, clear it to prevent the native tooltip
18551
		// we have to check first to avoid defining a title if none exists
18552
		// (we don't want to cause an element to start matching [title])
18553
		//
18554
		// We use removeAttr only for key events, to allow IE to export the correct
18555
		// accessible attributes. For mouse events, set to empty string to avoid
18556
		// native tooltip showing up (happens only when removing inside mouseover).
18557
		if ( target.is( "[title]" ) ) {
18558
			if ( event && event.type === "mouseover" ) {
18559
				target.attr( "title", "" );
18560
			} else {
18561
				target.removeAttr( "title" );
18562
			}
18563
		}
18564
 
18565
		tooltipData = this._tooltip( target );
18566
		tooltip = tooltipData.tooltip;
18567
		this._addDescribedBy( target, tooltip.attr( "id" ) );
18568
		tooltip.find( ".ui-tooltip-content" ).html( content );
18569
 
18570
		// Support: Voiceover on OS X, JAWS on IE <= 9
18571
		// JAWS announces deletions even when aria-relevant="additions"
18572
		// Voiceover will sometimes re-read the entire log region's contents from the beginning
18573
		this.liveRegion.children().hide();
18574
		a11yContent = $( "<div>" ).html( tooltip.find( ".ui-tooltip-content" ).html() );
18575
		a11yContent.removeAttr( "name" ).find( "[name]" ).removeAttr( "name" );
18576
		a11yContent.removeAttr( "id" ).find( "[id]" ).removeAttr( "id" );
18577
		a11yContent.appendTo( this.liveRegion );
18578
 
18579
		function position( event ) {
18580
			positionOption.of = event;
18581
			if ( tooltip.is( ":hidden" ) ) {
18582
				return;
18583
			}
18584
			tooltip.position( positionOption );
18585
		}
18586
		if ( this.options.track && event && /^mouse/.test( event.type ) ) {
18587
			this._on( this.document, {
18588
				mousemove: position
18589
			} );
18590
 
18591
			// trigger once to override element-relative positioning
18592
			position( event );
18593
		} else {
18594
			tooltip.position( $.extend( {
18595
				of: target
18596
			}, this.options.position ) );
18597
		}
18598
 
18599
		tooltip.hide();
18600
 
18601
		this._show( tooltip, this.options.show );
18602
 
18603
		// Handle tracking tooltips that are shown with a delay (#8644). As soon
18604
		// as the tooltip is visible, position the tooltip using the most recent
18605
		// event.
18606
		// Adds the check to add the timers only when both delay and track options are set (#14682)
18607
		if ( this.options.track && this.options.show && this.options.show.delay ) {
18608
			delayedShow = this.delayedShow = setInterval( function() {
18609
				if ( tooltip.is( ":visible" ) ) {
18610
					position( positionOption.of );
18611
					clearInterval( delayedShow );
18612
				}
18613
			}, 13 );
18614
		}
18615
 
18616
		this._trigger( "open", event, { tooltip: tooltip } );
18617
	},
18618
 
18619
	_registerCloseHandlers: function( event, target ) {
18620
		var events = {
18621
			keyup: function( event ) {
18622
				if ( event.keyCode === $.ui.keyCode.ESCAPE ) {
18623
					var fakeEvent = $.Event( event );
18624
					fakeEvent.currentTarget = target[ 0 ];
18625
					this.close( fakeEvent, true );
18626
				}
18627
			}
18628
		};
18629
 
18630
		// Only bind remove handler for delegated targets. Non-delegated
18631
		// tooltips will handle this in destroy.
18632
		if ( target[ 0 ] !== this.element[ 0 ] ) {
18633
			events.remove = function() {
18634
				var targetElement = this._find( target );
18635
				if ( targetElement ) {
18636
					this._removeTooltip( targetElement.tooltip );
18637
				}
18638
			};
18639
		}
18640
 
18641
		if ( !event || event.type === "mouseover" ) {
18642
			events.mouseleave = "close";
18643
		}
18644
		if ( !event || event.type === "focusin" ) {
18645
			events.focusout = "close";
18646
		}
18647
		this._on( true, target, events );
18648
	},
18649
 
18650
	close: function( event ) {
18651
		var tooltip,
18652
			that = this,
18653
			target = $( event ? event.currentTarget : this.element ),
18654
			tooltipData = this._find( target );
18655
 
18656
		// The tooltip may already be closed
18657
		if ( !tooltipData ) {
18658
 
18659
			// We set ui-tooltip-open immediately upon open (in open()), but only set the
18660
			// additional data once there's actually content to show (in _open()). So even if the
18661
			// tooltip doesn't have full data, we always remove ui-tooltip-open in case we're in
18662
			// the period between open() and _open().
18663
			target.removeData( "ui-tooltip-open" );
18664
			return;
18665
		}
18666
 
18667
		tooltip = tooltipData.tooltip;
18668
 
18669
		// Disabling closes the tooltip, so we need to track when we're closing
18670
		// to avoid an infinite loop in case the tooltip becomes disabled on close
18671
		if ( tooltipData.closing ) {
18672
			return;
18673
		}
18674
 
18675
		// Clear the interval for delayed tracking tooltips
18676
		clearInterval( this.delayedShow );
18677
 
18678
		// Only set title if we had one before (see comment in _open())
18679
		// If the title attribute has changed since open(), don't restore
18680
		if ( target.data( "ui-tooltip-title" ) && !target.attr( "title" ) ) {
18681
			target.attr( "title", target.data( "ui-tooltip-title" ) );
18682
		}
18683
 
18684
		this._removeDescribedBy( target );
18685
 
18686
		tooltipData.hiding = true;
18687
		tooltip.stop( true );
18688
		this._hide( tooltip, this.options.hide, function() {
18689
			that._removeTooltip( $( this ) );
18690
		} );
18691
 
18692
		target.removeData( "ui-tooltip-open" );
18693
		this._off( target, "mouseleave focusout keyup" );
18694
 
18695
		// Remove 'remove' binding only on delegated targets
18696
		if ( target[ 0 ] !== this.element[ 0 ] ) {
18697
			this._off( target, "remove" );
18698
		}
18699
		this._off( this.document, "mousemove" );
18700
 
18701
		if ( event && event.type === "mouseleave" ) {
18702
			$.each( this.parents, function( id, parent ) {
18703
				$( parent.element ).attr( "title", parent.title );
18704
				delete that.parents[ id ];
18705
			} );
18706
		}
18707
 
18708
		tooltipData.closing = true;
18709
		this._trigger( "close", event, { tooltip: tooltip } );
18710
		if ( !tooltipData.hiding ) {
18711
			tooltipData.closing = false;
18712
		}
18713
	},
18714
 
18715
	_tooltip: function( element ) {
18716
		var tooltip = $( "<div>" ).attr( "role", "tooltip" ),
18717
			content = $( "<div>" ).appendTo( tooltip ),
18718
			id = tooltip.uniqueId().attr( "id" );
18719
 
18720
		this._addClass( content, "ui-tooltip-content" );
18721
		this._addClass( tooltip, "ui-tooltip", "ui-widget ui-widget-content" );
18722
 
18723
		tooltip.appendTo( this._appendTo( element ) );
18724
 
18725
		return this.tooltips[ id ] = {
18726
			element: element,
18727
			tooltip: tooltip
18728
		};
18729
	},
18730
 
18731
	_find: function( target ) {
18732
		var id = target.data( "ui-tooltip-id" );
18733
		return id ? this.tooltips[ id ] : null;
18734
	},
18735
 
18736
	_removeTooltip: function( tooltip ) {
18737
 
18738
		// Clear the interval for delayed tracking tooltips
18739
		clearInterval( this.delayedShow );
18740
 
18741
		tooltip.remove();
18742
		delete this.tooltips[ tooltip.attr( "id" ) ];
18743
	},
18744
 
18745
	_appendTo: function( target ) {
18746
		var element = target.closest( ".ui-front, dialog" );
18747
 
18748
		if ( !element.length ) {
18749
			element = this.document[ 0 ].body;
18750
		}
18751
 
18752
		return element;
18753
	},
18754
 
18755
	_destroy: function() {
18756
		var that = this;
18757
 
18758
		// Close open tooltips
18759
		$.each( this.tooltips, function( id, tooltipData ) {
18760
 
18761
			// Delegate to close method to handle common cleanup
18762
			var event = $.Event( "blur" ),
18763
				element = tooltipData.element;
18764
			event.target = event.currentTarget = element[ 0 ];
18765
			that.close( event, true );
18766
 
18767
			// Remove immediately; destroying an open tooltip doesn't use the
18768
			// hide animation
18769
			$( "#" + id ).remove();
18770
 
18771
			// Restore the title
18772
			if ( element.data( "ui-tooltip-title" ) ) {
18773
 
18774
				// If the title attribute has changed since open(), don't restore
18775
				if ( !element.attr( "title" ) ) {
18776
					element.attr( "title", element.data( "ui-tooltip-title" ) );
18777
				}
18778
				element.removeData( "ui-tooltip-title" );
18779
			}
18780
		} );
18781
		this.liveRegion.remove();
18782
	}
18783
} );
18784
 
18785
// DEPRECATED
18786
// TODO: Switch return back to widget declaration at top of file when this is removed
18787
if ( $.uiBackCompat === true ) {
18788
 
18789
	// Backcompat for tooltipClass option
18790
	$.widget( "ui.tooltip", $.ui.tooltip, {
18791
		options: {
18792
			tooltipClass: null
18793
		},
18794
		_tooltip: function() {
18795
			var tooltipData = this._superApply( arguments );
18796
			if ( this.options.tooltipClass ) {
18797
				tooltipData.tooltip.addClass( this.options.tooltipClass );
18798
			}
18799
			return tooltipData;
18800
		}
18801
	} );
18802
}
18803
 
18804
var widgetsTooltip = $.ui.tooltip;
18805
 
18806
 
18807
 
18808
 
18809
} );