PageSourceSearch

https://steveescoffery.com/about/

html steveescoffery.com collected 2026-10-04 03:52:13 UTC 438,527 bytes, 14,092 lines download raw bytes

1<!DOCTYPE html>
2<html lang="en-US">
3<head>
4<meta charset="UTF-8" />
5<title>About - Steve Escoffery</title><meta name="viewport" content="width=device-width, initial-scale=1" />
6
7	<!-- This site is optimized with the Yoast SEO plugin v14.2 - https://yoast.com/wordpress/plugins/seo/ -->
8	<meta name="robots" content="index, follow" />
9	<meta name="googlebot" content="index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1" />
10	<meta name="bingbot" content="index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1" />
11	<link rel="canonical" href="https://steveescoffery.com/about/" />
12	<meta property="og:locale" content="en_US" />
13	<meta property="og:type" content="article" />
14	<meta property="og:title" content="About - Steve Escoffery" />
15	<meta property="og:description" content="&nbsp; I was born in 1978 in St. Louis, Missouri, and my family had recently moved to the United States from Jamaica (after spending about three years in Canada). The first piece of music I ever wrote, probably when I was about 7 years old, was based on the chords – that one of my brothers [&hellip;]" />
16	<meta property="og:url" content="https://steveescoffery.com/about/" />
17	<meta property="og:site_name" content="Steve Escoffery" />
18	<meta property="article:modified_time" content="2017-12-22T13:13:09+00:00" />
19	<meta property="og:image" content="https://steveescoffery.com/wp-content/uploads/2014/08/10568740_10152597720848659_468870234_n.jpg" />
20	
20<script type="application/ld+json" class="yoast-schema-graph">{"@context":"https://schema.org","@graph":[{"@type":"WebSite","@id":"https://steveescoffery.com/#website","url":"https://steveescoffery.com/","name":"Steve Escoffery","description":"composer \u2022 pianist \u2022 music teacher","potentialAction":[{"@type":"SearchAction","target":"https://steveescoffery.com/?s={search_term_string}","query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"ImageObject","@id":"https://steveescoffery.com/about/#primaryimage","inLanguage":"en-US","url":"https://steveescoffery.com/wp-content/uploads/2014/08/10568740_10152597720848659_468870234_n.jpg"},{"@type":"WebPage","@id":"https://steveescoffery.com/about/#webpage","url":"https://steveescoffery.com/about/","name":"About - Steve Escoffery","isPartOf":{"@id":"https://steveescoffery.com/#website"},"primaryImageOfPage":{"@id":"https://steveescoffery.com/about/#primaryimage"},"datePublished":"2014-08-28T21:17:14+00:00","dateModified":"2017-12-22T13:13:09+00:00","inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https://steveescoffery.com/about/"]}]}]}</script>
20
21	<!-- / Yoast SEO plugin. -->
22
23
24<link rel='dns-prefetch' href='//cdnjs.cloudflare.com' />
25<link rel='dns-prefetch' href='//fonts.googleapis.com' />
26<link rel='dns-prefetch' href='//ajax.googleapis.com' />
27<link rel='dns-prefetch' href='//s.w.org' />
28<link rel="alternate" type="application/rss+xml" title="Steve Escoffery &raquo; Feed" href="https://steveescoffery.com/feed/" />
29<link rel="alternate" type="application/rss+xml" title="Steve Escoffery &raquo; Comments Feed" href="https://steveescoffery.com/comments/feed/" />
30<link rel="alternate" type="application/rss+xml" title="Steve Escoffery &raquo; About Comments Feed" href="https://steveescoffery.com/about/feed/" />
31		
31<script type="text/javascript">
32			window._wpemojiSettings = {"baseUrl":"https:\/\/s.w.org\/images\/core\/emoji\/12.0.0-1\/72x72\/","ext":".png","svgUrl":"https:\/\/s.w.org\/images\/core\/emoji\/12.0.0-1\/svg\/","svgExt":".svg","source":{"concatemoji":"https:\/\/steveescoffery.com\/wp-includes\/js\/wp-emoji-release.min.js?ver=5.4.23"}};
33			/*! This file is auto-generated */
34			!function(e,a,t){var n,r,o,i=a.createElement("canvas"),p=i.getContext&&i.getContext("2d");function s(e,t){var a=String.fromCharCode;p.clearRect(0,0,i.width,i.height),p.fillText(a.apply(this,e),0,0);e=i.toDataURL();return p.clearRect(0,0,i.width,i.height),p.fillText(a.apply(this,t),0,0),e===i.toDataURL()}function c(e){var t=a.createElement("script");t.src=e,t.defer=t.type="text/javascript",a.getElementsByTagName("head")[0].appendChild(t)}for(o=Array("flag","emoji"),t.supports={everything:!0,everythingExceptFlag:!0},r=0;r<o.length;r++)t.supports[o[r]]=function(e){if(!p||!p.fillText)return!1;switch(p.textBaseline="top",p.font="600 32px Arial",e){case"flag":return s([127987,65039,8205,9895,65039],[127987,65039,8203,9895,65039])?!1:!s([55356,56826,55356,56819],[55356,56826,8203,55356,56819])&&!s([55356,57332,56128,56423,56128,56418,56128,56421,56128,56430,56128,56423,56128,56447],[55356,57332,8203,56128,56423,8203,56128,56418,8203,56128,56421,8203,56128,56430,8203,56128,56423,8203,56128,56447]);case"emoji":return!s([55357,56424,55356,57342,8205,55358,56605,8205,55357,56424,55356,57340],[55357,56424,55356,57342,8203,55358,56605,8203,55357,56424,55356,57340])}return!1}(o[r]),t.supports.everything=t.supports.everything&&t.supports[o[r]],"flag"!==o[r]&&(t.supports.everythingExceptFlag=t.supports.everythingExceptFlag&&t.supports[o[r]]);t.supports.everythingExceptFlag=t.supports.everythingExceptFlag&&!t.supports.flag,t.DOMReady=!1,t.readyCallback=function(){t.DOMReady=!0},t.supports.everything||(n=function(){t.readyCallback()},a.addEventListener?(a.addEventListener("DOMContentLoaded",n,!1),e.addEventListener("load",n,!1)):(e.attachEvent("onload",n),a.attachEvent("onreadystatechange",function(){"complete"===a.readyState&&t.readyCallback()})),(n=t.source||{}).concatemoji?c(n.concatemoji):n.wpemoji&&n.twemoji&&(c(n.twemoji),c(n.wpemoji)))}(window,document,window._wpemojiSettings);
35		</script>
35
36		<style type="text/css">
37img.wp-smiley,
38img.emoji {
39	display: inline !important;
40	border: none !important;
41	box-shadow: none !important;
42	height: 1em !important;
43	width: 1em !important;
44	margin: 0 .07em !important;
45	vertical-align: -0.1em !important;
46	background: none !important;
47	padding: 0 !important;
48}
49</style>
50	<link rel='stylesheet' id='validate-engine-css-css'  href='https://steveescoffery.com/wp-content/plugins/wysija-newsletters/css/validationEngine.jquery.css?ver=2.13' type='text/css' media='all' />
51<link rel='stylesheet' id='swank-theme-css'  href='https://steveescoffery.com/wp-content/themes/swank/style.css?ver=1.0.0' type='text/css' media='all' />
52<link rel='stylesheet' id='wp-block-library-css'  href='https://steveescoffery.com/wp-includes/css/dist/block-library/style.min.css?ver=5.4.23' type='text/css' media='all' />
53<link rel='stylesheet' id='apss-font-awesome-four-css'  href='https://steveescoffery.com/wp-content/plugins/accesspress-social-share/css/font-awesome.min.css?ver=4.5.2' type='text/css' media='all' />
54<link rel='stylesheet' id='apss-frontend-css-css'  href='https://steveescoffery.com/wp-content/plugins/accesspress-social-share/css/frontend.css?ver=4.5.2' type='text/css' media='all' />
55<link rel='stylesheet' id='apss-font-opensans-css'  href='//fonts.googleapis.com/css?family=Open+Sans&#038;ver=5.4.23' type='text/css' media='all' />
56<link rel='stylesheet' id='tm_clicktotweet-css'  href='https://steveescoffery.com/wp-content/plugins/click-to-tweet-by-todaymade/assets/css/styles.css?ver=5.4.23' type='text/css' media='all' />
57<link rel='stylesheet' id='contact-form-7-css'  href='https://steveescoffery.com/wp-content/plugins/contact-form-7/includes/css/styles.css?ver=5.1.9' type='text/css' media='all' />
58<link rel='stylesheet' id='jquery-ui-standard-css-css'  href='//ajax.googleapis.com/ajax/libs/jqueryui/1.11.2/themes/smoothness/jquery-ui.css?ver=5.4.23' type='text/css' media='all' />
59<link rel='stylesheet' id='toc-screen-css'  href='https://steveescoffery.com/wp-content/plugins/table-of-contents-plus/screen.min.css?ver=2002' type='text/css' media='all' />
60<link rel='stylesheet' id='swank-google-fonts-css'  href='//fonts.googleapis.com/css?family=Old+Standard+TT%3A400%2C400italic%2C700%7CMontserrat%3A400%2C700&#038;ver=1.0.0' type='text/css' media='all' />
61<link rel='stylesheet' id='tocify-css-css'  href='https://cdnjs.cloudflare.com/ajax/libs/jquery.tocify/1.9.0/stylesheets/jquery.tocify.min.css?ver=5.4.23' type='text/css' media='all' />
62<link rel='stylesheet' id='msl-main-css'  href='https://steveescoffery.com/wp-content/plugins/master-slider/public/assets/css/masterslider.main.css?ver=3.5.8' type='text/css' media='all' />
63<link rel='stylesheet' id='msl-custom-css'  href='https://steveescoffery.com/wp-content/uploads/master-slider/custom.css?ver=2.4' type='text/css' media='all' />
64<script>if (document.location.protocol != "https:") {document.location = document.URL.replace(/^http:/i, "https:");}</script>
64<script type='text/javascript' src='https://steveescoffery.com/wp-includes/js/jquery/jquery.js?ver=1.12.4-wp'></script>
vendor: 1 bytes, line 64
64
65<script type='text/javascript' src='https://steveescoffery.com/wp-includes/js/jquery/jquery-migrate.min.js?ver=1.4.1'></script>
65
66<link rel='https://api.w.org/' href='https://steveescoffery.com/wp-json/' />
67<link rel="EditURI" type="application/rsd+xml" title="RSD" href="https://steveescoffery.com/xmlrpc.php?rsd" />
68<link rel="wlwmanifest" type="application/wlwmanifest+xml" href="https://steveescoffery.com/wp-includes/wlwmanifest.xml" /> 
69<meta name="generator" content="WordPress 5.4.23" />
70<link rel='shortlink' href='https://steveescoffery.com/?p=8' />
71<link rel="alternate" type="application/json+oembed" href="https://steveescoffery.com/wp-json/oembed/1.0/embed?url=https%3A%2F%2Fsteveescoffery.com%2Fabout%2F" />
72<link rel="alternate" type="text/xml+oembed" href="https://steveescoffery.com/wp-json/oembed/1.0/embed?url=https%3A%2F%2Fsteveescoffery.com%2Fabout%2F&#038;format=xml" />
73<style type="text/css"> .enews .screenread {
74	height: 1px;
75    left: -1000em;
76    overflow: hidden;
77    position: absolute;
78    top: -1000em;
79    width: 1px; } </style>
vendor: 21,002 bytes, lines 79-810
79<script type="text/javascript">
80jQuery(document).ready(function($) {
81
82/*! jQuery UI - v1.12.1 - 2016-10-29
83* http://jqueryui.com
84* Includes: widget.js, position.js, data.js, disable-selection.js, focusable.js, form-reset-mixin.js, jquery-1-7.js, keycode.js, labels.js, scroll-parent.js, tabbable.js, unique-id.js, widgets/draggable.js, widgets/resizable.js, widgets/accordion.js, widgets/autocomplete.js, widgets/button.js, widgets/checkboxradio.js, widgets/controlgroup.js, widgets/datepicker.js, widgets/dialog.js, widgets/menu.js, widgets/mouse.js, widgets/progressbar.js, widgets/selectmenu.js, widgets/slider.js, widgets/spinner.js, widgets/tabs.js, widgets/tooltip.js
85* Copyright jQuery Foundation and other contributors; Licensed MIT */
86
87(function( factory ) {
88	if ( typeof define === "function" && define.amd ) {
89
90		// AMD. Register as an anonymous module.
91		define([ "jquery" ], factory );
92	} else {
93
94		// Browser globals
95		factory( jQuery );
96	}
97}(function( $ ) {
98
99$.ui = $.ui || {};
100
101var version = $.ui.version = "1.12.1";
102
103
104/*!
105 * jQuery UI Widget 1.12.1
106 * http://jqueryui.com
107 *
108 * Copyright jQuery Foundation and other contributors
109 * Released under the MIT license.
110 * http://jquery.org/license
111 */
112
113//>>label: Widget
114//>>group: Core
115//>>description: Provides a factory for creating stateful widgets with a common API.
116//>>docs: http://api.jqueryui.com/jQuery.widget/
117//>>demos: http://jqueryui.com/widget/
118
119
120
121var widgetUuid = 0;
122var widgetSlice = Array.prototype.slice;
123
124$.cleanData = ( function( orig ) {
125	return function( elems ) {
126		var events, elem, i;
127		for ( i = 0; ( elem = elems[ i ] ) != null; i++ ) {
128			try {
129
130				// Only trigger remove when necessary to save time
131				events = $._data( elem, "events" );
132				if ( events && events.remove ) {
133					$( elem ).triggerHandler( "remove" );
134				}
135
136			// Http://bugs.jquery.com/ticket/8235
137			} catch ( e ) {}
138		}
139		orig( elems );
140	};
141} )( $.cleanData );
142
143$.widget = function( name, base, prototype ) {
144	var existingConstructor, constructor, basePrototype;
145
146	// ProxiedPrototype allows the provided prototype to remain unmodified
147	// so that it can be used as a mixin for multiple widgets (#8876)
148	var proxiedPrototype = {};
149
150	var namespace = name.split( "." )[ 0 ];
151	name = name.split( "." )[ 1 ];
152	var fullName = namespace + "-" + name;
153
154	if ( !prototype ) {
155		prototype = base;
156		base = $.Widget;
157	}
158
159	if ( $.isArray( prototype ) ) {
160		prototype = $.extend.apply( null, [ {} ].concat( prototype ) );
161	}
162
163	// Create selector for plugin
164	$.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
165		return !!$.data( elem, fullName );
166	};
167
168	$[ namespace ] = $[ namespace ] || {};
169	existingConstructor = $[ namespace ][ name ];
170	constructor = $[ namespace ][ name ] = function( options, element ) {
171
172		// Allow instantiation without "new" keyword
173		if ( !this._createWidget ) {
174			return new constructor( options, element );
175		}
176
177		// Allow instantiation without initializing for simple inheritance
178		// must use "new" keyword (the code above always passes args)
179		if ( arguments.length ) {
180			this._createWidget( options, element );
181		}
182	};
183
184	// Extend with the existing constructor to carry over any static properties
185	$.extend( constructor, existingConstructor, {
186		version: prototype.version,
187
188		// Copy the object used to create the prototype in case we need to
189		// redefine the widget later
190		_proto: $.extend( {}, prototype ),
191
192		// Track widgets that inherit from this widget in case this widget is
193		// redefined after a widget inherits from it
194		_childConstructors: []
195	} );
196
197	basePrototype = new base();
198
199	// We need to make the options hash a property directly on the new instance
200	// otherwise we'll modify the options hash on the prototype that we're
201	// inheriting from
202	basePrototype.options = $.widget.extend( {}, basePrototype.options );
203	$.each( prototype, function( prop, value ) {
204		if ( !$.isFunction( value ) ) {
205			proxiedPrototype[ prop ] = value;
206			return;
207		}
208		proxiedPrototype[ prop ] = ( function() {
209			function _super() {
210				return base.prototype[ prop ].apply( this, arguments );
211			}
212
213			function _superApply( args ) {
214				return base.prototype[ prop ].apply( this, args );
215			}
216
217			return function() {
218				var __super = this._super;
219				var __superApply = this._superApply;
220				var returnValue;
221
222				this._super = _super;
223				this._superApply = _superApply;
224
225				returnValue = value.apply( this, arguments );
226
227				this._super = __super;
228				this._superApply = __superApply;
229
230				return returnValue;
231			};
232		} )();
233	} );
234	constructor.prototype = $.widget.extend( basePrototype, {
235
236		// TODO: remove support for widgetEventPrefix
237		// always use the name + a colon as the prefix, e.g., draggable:start
238		// don't prefix for widgets that aren't DOM-based
239		widgetEventPrefix: existingConstructor ? ( basePrototype.widgetEventPrefix || name ) : name
240	}, proxiedPrototype, {
241		constructor: constructor,
242		namespace: namespace,
243		widgetName: name,
244		widgetFullName: fullName
245	} );
246
247	// If this widget is being redefined then we need to find all widgets that
248	// are inheriting from it and redefine all of them so that they inherit from
249	// the new version of this widget. We're essentially trying to replace one
250	// level in the prototype chain.
251	if ( existingConstructor ) {
252		$.each( existingConstructor._childConstructors, function( i, child ) {
253			var childPrototype = child.prototype;
254
255			// Redefine the child widget using the same prototype that was
256			// originally used, but inherit from the new version of the base
257			$.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor,
258				child._proto );
259		} );
260
261		// Remove the list of existing child constructors from the old constructor
262		// so the old child constructors can be garbage collected
263		delete existingConstructor._childConstructors;
264	} else {
265		base._childConstructors.push( constructor );
266	}
267
268	$.widget.bridge( name, constructor );
269
270	return constructor;
271};
272
273$.widget.extend = function( target ) {
274	var input = widgetSlice.call( arguments, 1 );
275	var inputIndex = 0;
276	var inputLength = input.length;
277	var key;
278	var value;
279
280	for ( ; inputIndex < inputLength; inputIndex++ ) {
281		for ( key in input[ inputIndex ] ) {
282			value = input[ inputIndex ][ key ];
283			if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
284
285				// Clone objects
286				if ( $.isPlainObject( value ) ) {
287					target[ key ] = $.isPlainObject( target[ key ] ) ?
288						$.widget.extend( {}, target[ key ], value ) :
289
290						// Don't extend strings, arrays, etc. with objects
291						$.widget.extend( {}, value );
292
293				// Copy everything else by reference
294				} else {
295					target[ key ] = value;
296				}
297			}
298		}
299	}
300	return target;
301};
302
303$.widget.bridge = function( name, object ) {
304	var fullName = object.prototype.widgetFullName || name;
305	$.fn[ name ] = function( options ) {
306		var isMethodCall = typeof options === "string";
307		var args = widgetSlice.call( arguments, 1 );
308		var returnValue = this;
309
310		if ( isMethodCall ) {
311
312			// If this is an empty collection, we need to have the instance method
313			// return undefined instead of the jQuery instance
314			if ( !this.length && options === "instance" ) {
315				returnValue = undefined;
316			} else {
317				this.each( function() {
318					var methodValue;
319					var instance = $.data( this, fullName );
320
321					if ( options === "instance" ) {
322						returnValue = instance;
323						return false;
324					}
325
326					if ( !instance ) {
327						return $.error( "cannot call methods on " + name +
328							" prior to initialization; " +
329							"attempted to call method '" + options + "'" );
330					}
331
332					if ( !$.isFunction( instance[ options ] ) || options.charAt( 0 ) === "_" ) {
333						return $.error( "no such method '" + options + "' for " + name +
334							" widget instance" );
335					}
336
337					methodValue = instance[ options ].apply( instance, args );
338
339					if ( methodValue !== instance && methodValue !== undefined ) {
340						returnValue = methodValue && methodValue.jquery ?
341							returnValue.pushStack( methodValue.get() ) :
342							methodValue;
343						return false;
344					}
345				} );
346			}
347		} else {
348
349			// Allow multiple hashes to be passed on init
350			if ( args.length ) {
351				options = $.widget.extend.apply( null, [ options ].concat( args ) );
352			}
353
354			this.each( function() {
355				var instance = $.data( this, fullName );
356				if ( instance ) {
357					instance.option( options || {} );
358					if ( instance._init ) {
359						instance._init();
360					}
361				} else {
362					$.data( this, fullName, new object( options, this ) );
363				}
364			} );
365		}
366
367		return returnValue;
368	};
369};
370
371$.Widget = function( /* options, element */ ) {};
372$.Widget._childConstructors = [];
373
374$.Widget.prototype = {
375	widgetName: "widget",
376	widgetEventPrefix: "",
377	defaultElement: "<div>",
378
379	options: {
380		classes: {},
381		disabled: false,
382
383		// Callbacks
384		create: null
385	},
386
387	_createWidget: function( options, element ) {
388		element = $( element || this.defaultElement || this )[ 0 ];
389		this.element = $( element );
390		this.uuid = widgetUuid++;
391		this.eventNamespace = "." + this.widgetName + this.uuid;
392
393		this.bindings = $();
394		this.hoverable = $();
395		this.focusable = $();
396		this.classesElementLookup = {};
397
398		if ( element !== this ) {
399			$.data( element, this.widgetFullName, this );
400			this._on( true, this.element, {
401				remove: function( event ) {
402					if ( event.target === element ) {
403						this.destroy();
404					}
405				}
406			} );
407			this.document = $( element.style ?
408
409				// Element within the document
410				element.ownerDocument :
411
412				// Element is window or document
413				element.document || element );
414			this.window = $( this.document[ 0 ].defaultView || this.document[ 0 ].parentWindow );
415		}
416
417		this.options = $.widget.extend( {},
418			this.options,
419			this._getCreateOptions(),
420			options );
421
422		this._create();
423
424		if ( this.options.disabled ) {
425			this._setOptionDisabled( this.options.disabled );
426		}
427
428		this._trigger( "create", null, this._getCreateEventData() );
429		this._init();
430	},
431
432	_getCreateOptions: function() {
433		return {};
434	},
435
436	_getCreateEventData: $.noop,
437
438	_create: $.noop,
439
440	_init: $.noop,
441
442	destroy: function() {
443		var that = this;
444
445		this._destroy();
446		$.each( this.classesElementLookup, function( key, value ) {
447			that._removeClass( value, key );
448		} );
449
450		// We can probably remove the unbind calls in 2.0
451		// all event bindings should go through this._on()
452		this.element
453			.off( this.eventNamespace )
454			.removeData( this.widgetFullName );
455		this.widget()
456			.off( this.eventNamespace )
457			.removeAttr( "aria-disabled" );
458
459		// Clean up events and states
460		this.bindings.off( this.eventNamespace );
461	},
462
463	_destroy: $.noop,
464
465	widget: function() {
466		return this.element;
467	},
468
469	option: function( key, value ) {
470		var options = key;
471		var parts;
472		var curOption;
473		var i;
474
475		if ( arguments.length === 0 ) {
476
477			// Don't return a reference to the internal hash
478			return $.widget.extend( {}, this.options );
479		}
480
481		if ( typeof key === "string" ) {
482
483			// Handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
484			options = {};
485			parts = key.split( "." );
486			key = parts.shift();
487			if ( parts.length ) {
488				curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
489				for ( i = 0; i < parts.length - 1; i++ ) {
490					curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
491					curOption = curOption[ parts[ i ] ];
492				}
493				key = parts.pop();
494				if ( arguments.length === 1 ) {
495					return curOption[ key ] === undefined ? null : curOption[ key ];
496				}
497				curOption[ key ] = value;
498			} else {
499				if ( arguments.length === 1 ) {
500					return this.options[ key ] === undefined ? null : this.options[ key ];
501				}
502				options[ key ] = value;
503			}
504		}
505
506		this._setOptions( options );
507
508		return this;
509	},
510
511	_setOptions: function( options ) {
512		var key;
513
514		for ( key in options ) {
515			this._setOption( key, options[ key ] );
516		}
517
518		return this;
519	},
520
521	_setOption: function( key, value ) {
522		if ( key === "classes" ) {
523			this._setOptionClasses( value );
524		}
525
526		this.options[ key ] = value;
527
528		if ( key === "disabled" ) {
529			this._setOptionDisabled( value );
530		}
531
532		return this;
533	},
534
535	_setOptionClasses: function( value ) {
536		var classKey, elements, currentElements;
537
538		for ( classKey in value ) {
539			currentElements = this.classesElementLookup[ classKey ];
540			if ( value[ classKey ] === this.options.classes[ classKey ] ||
541					!currentElements ||
542					!currentElements.length ) {
543				continue;
544			}
545
546			// We are doing this to create a new jQuery object because the _removeClass() call
547			// on the next line is going to destroy the reference to the current elements being
548			// tracked. We need to save a copy of this collection so that we can add the new classes
549			// below.
550			elements = $( currentElements.get() );
551			this._removeClass( currentElements, classKey );
552
553			// We don't use _addClass() here, because that uses this.options.classes
554			// for generating the string of classes. We want to use the value passed in from
555			// _setOption(), this is the new value of the classes option which was passed to
556			// _setOption(). We pass this value directly to _classes().
557			elements.addClass( this._classes( {
558				element: elements,
559				keys: classKey,
560				classes: value,
561				add: true
562			} ) );
563		}
564	},
565
566	_setOptionDisabled: function( value ) {
567		this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null, !!value );
568
569		// If the widget is becoming disabled, then nothing is interactive
570		if ( value ) {
571			this._removeClass( this.hoverable, null, "ui-state-hover" );
572			this._removeClass( this.focusable, null, "ui-state-focus" );
573		}
574	},
575
576	enable: function() {
577		return this._setOptions( { disabled: false } );
578	},
579
580	disable: function() {
581		return this._setOptions( { disabled: true } );
582	},
583
584	_classes: function( options ) {
585		var full = [];
586		var that = this;
587
588		options = $.extend( {
589			element: this.element,
590			classes: this.options.classes || {}
591		}, options );
592
593		function processClassString( classes, checkOption ) {
594			var current, i;
595			for ( i = 0; i < classes.length; i++ ) {
596				current = that.classesElementLookup[ classes[ i ] ] || $();
597				if ( options.add ) {
598					current = $( $.unique( current.get().concat( options.element.get() ) ) );
599				} else {
600					current = $( current.not( options.element ).get() );
601				}
602				that.classesElementLookup[ classes[ i ] ] = current;
603				full.push( classes[ i ] );
604				if ( checkOption && options.classes[ classes[ i ] ] ) {
605					full.push( options.classes[ classes[ i ] ] );
606				}
607			}
608		}
609
610		this._on( options.element, {
611			"remove": "_untrackClassesElement"
612		} );
613
614		if ( options.keys ) {
615			processClassString( options.keys.match( /\S+/g ) || [], true );
616		}
617		if ( options.extra ) {
618			processClassString( options.extra.match( /\S+/g ) || [] );
619		}
620
621		return full.join( " " );
622	},
623
624	_untrackClassesElement: function( event ) {
625		var that = this;
626		$.each( that.classesElementLookup, function( key, value ) {
627			if ( $.inArray( event.target, value ) !== -1 ) {
628				that.classesElementLookup[ key ] = $( value.not( event.target ).get() );
629			}
630		} );
631	},
632
633	_removeClass: function( element, keys, extra ) {
634		return this._toggleClass( element, keys, extra, false );
635	},
636
637	_addClass: function( element, keys, extra ) {
638		return this._toggleClass( element, keys, extra, true );
639	},
640
641	_toggleClass: function( element, keys, extra, add ) {
642		add = ( typeof add === "boolean" ) ? add : extra;
643		var shift = ( typeof element === "string" || element === null ),
644			options = {
645				extra: shift ? keys : extra,
646				keys: shift ? element : keys,
647				element: shift ? this.element : element,
648				add: add
649			};
650		options.element.toggleClass( this._classes( options ), add );
651		return this;
652	},
653
654	_on: function( suppressDisabledCheck, element, handlers ) {
655		var delegateElement;
656		var instance = this;
657
658		// No suppressDisabledCheck flag, shuffle arguments
659		if ( typeof suppressDisabledCheck !== "boolean" ) {
660			handlers = element;
661			element = suppressDisabledCheck;
662			suppressDisabledCheck = false;
663		}
664
665		// No element argument, shuffle and use this.element
666		if ( !handlers ) {
667			handlers = element;
668			element = this.element;
669			delegateElement = this.widget();
670		} else {
671			element = delegateElement = $( element );
672			this.bindings = this.bindings.add( element );
673		}
674
675		$.each( handlers, function( event, handler ) {
676			function handlerProxy() {
677
678				// Allow widgets to customize the disabled handling
679				// - disabled as an array instead of boolean
680				// - disabled class as method for disabling individual parts
681				if ( !suppressDisabledCheck &&
682						( instance.options.disabled === true ||
683						$( this ).hasClass( "ui-state-disabled" ) ) ) {
684					return;
685				}
686				return ( typeof handler === "string" ? instance[ handler ] : handler )
687					.apply( instance, arguments );
688			}
689
690			// Copy the guid so direct unbinding works
691			if ( typeof handler !== "string" ) {
692				handlerProxy.guid = handler.guid =
693					handler.guid || handlerProxy.guid || $.guid++;
694			}
695
696			var match = event.match( /^([\w:-]*)\s*(.*)$/ );
697			var eventName = match[ 1 ] + instance.eventNamespace;
698			var selector = match[ 2 ];
699
700			if ( selector ) {
701				delegateElement.on( eventName, selector, handlerProxy );
702			} else {
703				element.on( eventName, handlerProxy );
704			}
705		} );
706	},
707
708	_off: function( element, eventName ) {
709		eventName = ( eventName || "" ).split( " " ).join( this.eventNamespace + " " ) +
710			this.eventNamespace;
711		element.off( eventName ).off( eventName );
712
713		// Clear the stack to avoid memory leaks (#10056)
714		this.bindings = $( this.bindings.not( element ).get() );
715		this.focusable = $( this.focusable.not( element ).get() );
716		this.hoverable = $( this.hoverable.not( element ).get() );
717	},
718
719	_delay: function( handler, delay ) {
720		function handlerProxy() {
721			return ( typeof handler === "string" ? instance[ handler ] : handler )
722				.apply( instance, arguments );
723		}
724		var instance = this;
725		return setTimeout( handlerProxy, delay || 0 );
726	},
727
728	_hoverable: function( element ) {
729		this.hoverable = this.hoverable.add( element );
730		this._on( element, {
731			mouseenter: function( event ) {
732				this._addClass( $( event.currentTarget ), null, "ui-state-hover" );
733			},
734			mouseleave: function( event ) {
735				this._removeClass( $( event.currentTarget ), null, "ui-state-hover" );
736			}
737		} );
738	},
739
740	_focusable: function( element ) {
741		this.focusable = this.focusable.add( element );
742		this._on( element, {
743			focusin: function( event ) {
744				this._addClass( $( event.currentTarget ), null, "ui-state-focus" );
745			},
746			focusout: function( event ) {
747				this._removeClass( $( event.currentTarget ), null, "ui-state-focus" );
748			}
749		} );
750	},
751
752	_trigger: function( type, event, data ) {
753		var prop, orig;
754		var callback = this.options[ type ];
755
756		data = data || {};
757		event = $.Event( event );
758		event.type = ( type === this.widgetEventPrefix ?
759			type :
760			this.widgetEventPrefix + type ).toLowerCase();
761
762		// The original event may come from any element
763		// so we need to reset the target on the new event
764		event.target = this.element[ 0 ];
765
766		// Copy original event properties over to the new event
767		orig = event.originalEvent;
768		if ( orig ) {
769			for ( prop in orig ) {
770				if ( !( prop in event ) ) {
771					event[ prop ] = orig[ prop ];
772				}
773			}
774		}
775
776		this.element.trigger( event, data );
777		return !( $.isFunction( callback ) &&
778			callback.apply( this.element[ 0 ], [ event ].concat( data ) ) === false ||
779			event.isDefaultPrevented() );
780	}
781};
782
783$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
784	$.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
785		if ( typeof options === "string" ) {
786			options = { effect: options };
787		}
788
789		var hasOptions;
790		var effectName = !options ?
791			method :
792			options === true || typeof options === "number" ?
793				defaultEffect :
794				options.effect || defaultEffect;
795
796		options = options || {};
797		if ( typeof options === "number" ) {
798			options = { duration: options };
799		}
800
801		hasOptions = !$.isEmptyObject( options );
802		options.complete = callback;
803
804		if ( options.delay ) {
805			element.delay( options.delay );
806		}
807
808		if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
809			element[ method ]( options );
810		} else if ( effectName !== method && element[ effectName ] ) {
vendor: 4,982 bytes, lines 811-990
811			element[ effectName ]( options.duration, options.easing, callback );
812		} else {
813			element.queue( function( next ) {
814				$( this )[ method ]();
815				if ( callback ) {
816					callback.call( element[ 0 ] );
817				}
818				next();
819			} );
820		}
821	};
822} );
823
824var widget = $.widget;
825
826
827/*!
828 * jQuery UI Position 1.12.1
829 * http://jqueryui.com
830 *
831 * Copyright jQuery Foundation and other contributors
832 * Released under the MIT license.
833 * http://jquery.org/license
834 *
835 * http://api.jqueryui.com/position/
836 */
837
838//>>label: Position
839//>>group: Core
840//>>description: Positions elements relative to other elements.
841//>>docs: http://api.jqueryui.com/position/
842//>>demos: http://jqueryui.com/position/
843
844
845( function() {
846var cachedScrollbarWidth,
847	max = Math.max,
848	abs = Math.abs,
849	rhorizontal = /left|center|right/,
850	rvertical = /top|center|bottom/,
851	roffset = /[\+\-]\d+(\.[\d]+)?%?/,
852	rposition = /^\w+/,
853	rpercent = /%$/,
854	_position = $.fn.position;
855
856function getOffsets( offsets, width, height ) {
857	return [
858		parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),
859		parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )
860	];
861}
862
863function parseCss( element, property ) {
864	return parseInt( $.css( element, property ), 10 ) || 0;
865}
866
867function getDimensions( elem ) {
868	var raw = elem[ 0 ];
869	if ( raw.nodeType === 9 ) {
870		return {
871			width: elem.width(),
872			height: elem.height(),
873			offset: { top: 0, left: 0 }
874		};
875	}
876	if ( $.isWindow( raw ) ) {
877		return {
878			width: elem.width(),
879			height: elem.height(),
880			offset: { top: elem.scrollTop(), left: elem.scrollLeft() }
881		};
882	}
883	if ( raw.preventDefault ) {
884		return {
885			width: 0,
886			height: 0,
887			offset: { top: raw.pageY, left: raw.pageX }
888		};
889	}
890	return {
891		width: elem.outerWidth(),
892		height: elem.outerHeight(),
893		offset: elem.offset()
894	};
895}
896
897$.position = {
898	scrollbarWidth: function() {
899		if ( cachedScrollbarWidth !== undefined ) {
900			return cachedScrollbarWidth;
901		}
902		var w1, w2,
903			div = $( "<div " +
904				"style='display:block;position:absolute;width:50px;height:50px;overflow:hidden;'>" +
905				"<div style='height:100px;width:auto;'></div></div>" ),
906			innerDiv = div.children()[ 0 ];
907
908		$( "body" ).append( div );
909		w1 = innerDiv.offsetWidth;
910		div.css( "overflow", "scroll" );
911
912		w2 = innerDiv.offsetWidth;
913
914		if ( w1 === w2 ) {
915			w2 = div[ 0 ].clientWidth;
916		}
917
918		div.remove();
919
920		return ( cachedScrollbarWidth = w1 - w2 );
921	},
922	getScrollInfo: function( within ) {
923		var overflowX = within.isWindow || within.isDocument ? "" :
924				within.element.css( "overflow-x" ),
925			overflowY = within.isWindow || within.isDocument ? "" :
926				within.element.css( "overflow-y" ),
927			hasOverflowX = overflowX === "scroll" ||
928				( overflowX === "auto" && within.width < within.element[ 0 ].scrollWidth ),
929			hasOverflowY = overflowY === "scroll" ||
930				( overflowY === "auto" && within.height < within.element[ 0 ].scrollHeight );
931		return {
932			width: hasOverflowY ? $.position.scrollbarWidth() : 0,
933			height: hasOverflowX ? $.position.scrollbarWidth() : 0
934		};
935	},
936	getWithinInfo: function( element ) {
937		var withinElement = $( element || window ),
938			isWindow = $.isWindow( withinElement[ 0 ] ),
939			isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9,
940			hasOffset = !isWindow && !isDocument;
941		return {
942			element: withinElement,
943			isWindow: isWindow,
944			isDocument: isDocument,
945			offset: hasOffset ? $( element ).offset() : { left: 0, top: 0 },
946			scrollLeft: withinElement.scrollLeft(),
947			scrollTop: withinElement.scrollTop(),
948			width: withinElement.outerWidth(),
949			height: withinElement.outerHeight()
950		};
951	}
952};
953
954$.fn.position = function( options ) {
955	if ( !options || !options.of ) {
956		return _position.apply( this, arguments );
957	}
958
959	// Make a copy, we don't want to modify arguments
960	options = $.extend( {}, options );
961
962	var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,
963		target = $( options.of ),
964		within = $.position.getWithinInfo( options.within ),
965		scrollInfo = $.position.getScrollInfo( within ),
966		collision = ( options.collision || "flip" ).split( " " ),
967		offsets = {};
968
969	dimensions = getDimensions( target );
970	if ( target[ 0 ].preventDefault ) {
971
972		// Force left top to allow flipping
973		options.at = "left top";
974	}
975	targetWidth = dimensions.width;
976	targetHeight = dimensions.height;
977	targetOffset = dimensions.offset;
978
979	// Clone to reuse original targetOffset later
980	basePosition = $.extend( {}, targetOffset );
981
982	// Force my and at to have valid horizontal and vertical positions
983	// if a value is missing or invalid, it will be converted to center
984	$.each( [ "my", "at" ], function() {
985		var pos = ( options[ this ] || "" ).split( " " ),
986			horizontalOffset,
987			verticalOffset;
988
989		if ( pos.length === 1 ) {
990			pos = rhorizontal.test( pos[ 0 ] ) ?
vendor: 10,483 bytes, lines 991-1317
991				pos.concat( [ "center" ] ) :
992				rvertical.test( pos[ 0 ] ) ?
993					[ "center" ].concat( pos ) :
994					[ "center", "center" ];
995		}
996		pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center";
997		pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";
998
999		// Calculate offsets
1000		horizontalOffset = roffset.exec( pos[ 0 ] );
1001		verticalOffset = roffset.exec( pos[ 1 ] );
1002		offsets[ this ] = [
1003			horizontalOffset ? horizontalOffset[ 0 ] : 0,
1004			verticalOffset ? verticalOffset[ 0 ] : 0
1005		];
1006
1007		// Reduce to just the positions without the offsets
1008		options[ this ] = [
1009			rposition.exec( pos[ 0 ] )[ 0 ],
1010			rposition.exec( pos[ 1 ] )[ 0 ]
1011		];
1012	} );
1013
1014	// Normalize collision option
1015	if ( collision.length === 1 ) {
1016		collision[ 1 ] = collision[ 0 ];
1017	}
1018
1019	if ( options.at[ 0 ] === "right" ) {
1020		basePosition.left += targetWidth;
1021	} else if ( options.at[ 0 ] === "center" ) {
1022		basePosition.left += targetWidth / 2;
1023	}
1024
1025	if ( options.at[ 1 ] === "bottom" ) {
1026		basePosition.top += targetHeight;
1027	} else if ( options.at[ 1 ] === "center" ) {
1028		basePosition.top += targetHeight / 2;
1029	}
1030
1031	atOffset = getOffsets( offsets.at, targetWidth, targetHeight );
1032	basePosition.left += atOffset[ 0 ];
1033	basePosition.top += atOffset[ 1 ];
1034
1035	return this.each( function() {
1036		var collisionPosition, using,
1037			elem = $( this ),
1038			elemWidth = elem.outerWidth(),
1039			elemHeight = elem.outerHeight(),
1040			marginLeft = parseCss( this, "marginLeft" ),
1041			marginTop = parseCss( this, "marginTop" ),
1042			collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) +
1043				scrollInfo.width,
1044			collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) +
1045				scrollInfo.height,
1046			position = $.extend( {}, basePosition ),
1047			myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );
1048
1049		if ( options.my[ 0 ] === "right" ) {
1050			position.left -= elemWidth;
1051		} else if ( options.my[ 0 ] === "center" ) {
1052			position.left -= elemWidth / 2;
1053		}
1054
1055		if ( options.my[ 1 ] === "bottom" ) {
1056			position.top -= elemHeight;
1057		} else if ( options.my[ 1 ] === "center" ) {
1058			position.top -= elemHeight / 2;
1059		}
1060
1061		position.left += myOffset[ 0 ];
1062		position.top += myOffset[ 1 ];
1063
1064		collisionPosition = {
1065			marginLeft: marginLeft,
1066			marginTop: marginTop
1067		};
1068
1069		$.each( [ "left", "top" ], function( i, dir ) {
1070			if ( $.ui.position[ collision[ i ] ] ) {
1071				$.ui.position[ collision[ i ] ][ dir ]( position, {
1072					targetWidth: targetWidth,
1073					targetHeight: targetHeight,
1074					elemWidth: elemWidth,
1075					elemHeight: elemHeight,
1076					collisionPosition: collisionPosition,
1077					collisionWidth: collisionWidth,
1078					collisionHeight: collisionHeight,
1079					offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],
1080					my: options.my,
1081					at: options.at,
1082					within: within,
1083					elem: elem
1084				} );
1085			}
1086		} );
1087
1088		if ( options.using ) {
1089
1090			// Adds feedback as second argument to using callback, if present
1091			using = function( props ) {
1092				var left = targetOffset.left - position.left,
1093					right = left + targetWidth - elemWidth,
1094					top = targetOffset.top - position.top,
1095					bottom = top + targetHeight - elemHeight,
1096					feedback = {
1097						target: {
1098							element: target,
1099							left: targetOffset.left,
1100							top: targetOffset.top,
1101							width: targetWidth,
1102							height: targetHeight
1103						},
1104						element: {
1105							element: elem,
1106							left: position.left,
1107							top: position.top,
1108							width: elemWidth,
1109							height: elemHeight
1110						},
1111						horizontal: right < 0 ? "left" : left > 0 ? "right" : "center",
1112						vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle"
1113					};
1114				if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {
1115					feedback.horizontal = "center";
1116				}
1117				if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {
1118					feedback.vertical = "middle";
1119				}
1120				if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {
1121					feedback.important = "horizontal";
1122				} else {
1123					feedback.important = "vertical";
1124				}
1125				options.using.call( this, props, feedback );
1126			};
1127		}
1128
1129		elem.offset( $.extend( position, { using: using } ) );
1130	} );
1131};
1132
1133$.ui.position = {
1134	fit: {
1135		left: function( position, data ) {
1136			var within = data.within,
1137				withinOffset = within.isWindow ? within.scrollLeft : within.offset.left,
1138				outerWidth = within.width,
1139				collisionPosLeft = position.left - data.collisionPosition.marginLeft,
1140				overLeft = withinOffset - collisionPosLeft,
1141				overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
1142				newOverRight;
1143
1144			// Element is wider than within
1145			if ( data.collisionWidth > outerWidth ) {
1146
1147				// Element is initially over the left side of within
1148				if ( overLeft > 0 && overRight <= 0 ) {
1149					newOverRight = position.left + overLeft + data.collisionWidth - outerWidth -
1150						withinOffset;
1151					position.left += overLeft - newOverRight;
1152
1153				// Element is initially over right side of within
1154				} else if ( overRight > 0 && overLeft <= 0 ) {
1155					position.left = withinOffset;
1156
1157				// Element is initially over both left and right sides of within
1158				} else {
1159					if ( overLeft > overRight ) {
1160						position.left = withinOffset + outerWidth - data.collisionWidth;
1161					} else {
1162						position.left = withinOffset;
1163					}
1164				}
1165
1166			// Too far left -> align with left edge
1167			} else if ( overLeft > 0 ) {
1168				position.left += overLeft;
1169
1170			// Too far right -> align with right edge
1171			} else if ( overRight > 0 ) {
1172				position.left -= overRight;
1173
1174			// Adjust based on position and margin
1175			} else {
1176				position.left = max( position.left - collisionPosLeft, position.left );
1177			}
1178		},
1179		top: function( position, data ) {
1180			var within = data.within,
1181				withinOffset = within.isWindow ? within.scrollTop : within.offset.top,
1182				outerHeight = data.within.height,
1183				collisionPosTop = position.top - data.collisionPosition.marginTop,
1184				overTop = withinOffset - collisionPosTop,
1185				overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
1186				newOverBottom;
1187
1188			// Element is taller than within
1189			if ( data.collisionHeight > outerHeight ) {
1190
1191				// Element is initially over the top of within
1192				if ( overTop > 0 && overBottom <= 0 ) {
1193					newOverBottom = position.top + overTop + data.collisionHeight - outerHeight -
1194						withinOffset;
1195					position.top += overTop - newOverBottom;
1196
1197				// Element is initially over bottom of within
1198				} else if ( overBottom > 0 && overTop <= 0 ) {
1199					position.top = withinOffset;
1200
1201				// Element is initially over both top and bottom of within
1202				} else {
1203					if ( overTop > overBottom ) {
1204						position.top = withinOffset + outerHeight - data.collisionHeight;
1205					} else {
1206						position.top = withinOffset;
1207					}
1208				}
1209
1210			// Too far up -> align with top
1211			} else if ( overTop > 0 ) {
1212				position.top += overTop;
1213
1214			// Too far down -> align with bottom edge
1215			} else if ( overBottom > 0 ) {
1216				position.top -= overBottom;
1217
1218			// Adjust based on position and margin
1219			} else {
1220				position.top = max( position.top - collisionPosTop, position.top );
1221			}
1222		}
1223	},
1224	flip: {
1225		left: function( position, data ) {
1226			var within = data.within,
1227				withinOffset = within.offset.left + within.scrollLeft,
1228				outerWidth = within.width,
1229				offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,
1230				collisionPosLeft = position.left - data.collisionPosition.marginLeft,
1231				overLeft = collisionPosLeft - offsetLeft,
1232				overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,
1233				myOffset = data.my[ 0 ] === "left" ?
1234					-data.elemWidth :
1235					data.my[ 0 ] === "right" ?
1236						data.elemWidth :
1237						0,
1238				atOffset = data.at[ 0 ] === "left" ?
1239					data.targetWidth :
1240					data.at[ 0 ] === "right" ?
1241						-data.targetWidth :
1242						0,
1243				offset = -2 * data.offset[ 0 ],
1244				newOverRight,
1245				newOverLeft;
1246
1247			if ( overLeft < 0 ) {
1248				newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth -
1249					outerWidth - withinOffset;
1250				if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {
1251					position.left += myOffset + atOffset + offset;
1252				}
1253			} else if ( overRight > 0 ) {
1254				newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset +
1255					atOffset + offset - offsetLeft;
1256				if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {
1257					position.left += myOffset + atOffset + offset;
1258				}
1259			}
1260		},
1261		top: function( position, data ) {
1262			var within = data.within,
1263				withinOffset = within.offset.top + within.scrollTop,
1264				outerHeight = within.height,
1265				offsetTop = within.isWindow ? within.scrollTop : within.offset.top,
1266				collisionPosTop = position.top - data.collisionPosition.marginTop,
1267				overTop = collisionPosTop - offsetTop,
1268				overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,
1269				top = data.my[ 1 ] === "top",
1270				myOffset = top ?
1271					-data.elemHeight :
1272					data.my[ 1 ] === "bottom" ?
1273						data.elemHeight :
1274						0,
1275				atOffset = data.at[ 1 ] === "top" ?
1276					data.targetHeight :
1277					data.at[ 1 ] === "bottom" ?
1278						-data.targetHeight :
1279						0,
1280				offset = -2 * data.offset[ 1 ],
1281				newOverTop,
1282				newOverBottom;
1283			if ( overTop < 0 ) {
1284				newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight -
1285					outerHeight - withinOffset;
1286				if ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) {
1287					position.top += myOffset + atOffset + offset;
1288				}
1289			} else if ( overBottom > 0 ) {
1290				newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset +
1291					offset - offsetTop;
1292				if ( newOverTop > 0 || abs( newOverTop ) < overBottom ) {
1293					position.top += myOffset + atOffset + offset;
1294				}
1295			}
1296		}
1297	},
1298	flipfit: {
1299		left: function() {
1300			$.ui.position.flip.left.apply( this, arguments );
1301			$.ui.position.fit.left.apply( this, arguments );
1302		},
1303		top: function() {
1304			$.ui.position.flip.top.apply( this, arguments );
1305			$.ui.position.fit.top.apply( this, arguments );
1306		}
1307	}
1308};
1309
1310} )();
1311
1312var position = $.ui.position;
1313
1314
1315/*!
1316 * jQuery UI :data 1.12.1
1317 * http://jqueryui.com
vendor: 4,582 bytes, lines 1318-1488
1318 *
1319 * Copyright jQuery Foundation and other contributors
1320 * Released under the MIT license.
1321 * http://jquery.org/license
1322 */
1323
1324//>>label: :data Selector
1325//>>group: Core
1326//>>description: Selects elements which have data stored under the specified key.
1327//>>docs: http://api.jqueryui.com/data-selector/
1328
1329
1330var data = $.extend( $.expr[ ":" ], {
1331	data: $.expr.createPseudo ?
1332		$.expr.createPseudo( function( dataName ) {
1333			return function( elem ) {
1334				return !!$.data( elem, dataName );
1335			};
1336		} ) :
1337
1338		// Support: jQuery <1.8
1339		function( elem, i, match ) {
1340			return !!$.data( elem, match[ 3 ] );
1341		}
1342} );
1343
1344/*!
1345 * jQuery UI Disable Selection 1.12.1
1346 * http://jqueryui.com
1347 *
1348 * Copyright jQuery Foundation and other contributors
1349 * Released under the MIT license.
1350 * http://jquery.org/license
1351 */
1352
1353//>>label: disableSelection
1354//>>group: Core
1355//>>description: Disable selection of text content within the set of matched elements.
1356//>>docs: http://api.jqueryui.com/disableSelection/
1357
1358// This file is deprecated
1359
1360
1361var disableSelection = $.fn.extend( {
1362	disableSelection: ( function() {
1363		var eventType = "onselectstart" in document.createElement( "div" ) ?
1364			"selectstart" :
1365			"mousedown";
1366
1367		return function() {
1368			return this.on( eventType + ".ui-disableSelection", function( event ) {
1369				event.preventDefault();
1370			} );
1371		};
1372	} )(),
1373
1374	enableSelection: function() {
1375		return this.off( ".ui-disableSelection" );
1376	}
1377} );
1378
1379
1380/*!
1381 * jQuery UI Focusable 1.12.1
1382 * http://jqueryui.com
1383 *
1384 * Copyright jQuery Foundation and other contributors
1385 * Released under the MIT license.
1386 * http://jquery.org/license
1387 */
1388
1389//>>label: :focusable Selector
1390//>>group: Core
1391//>>description: Selects elements which can be focused.
1392//>>docs: http://api.jqueryui.com/focusable-selector/
1393
1394
1395
1396// Selectors
1397$.ui.focusable = function( element, hasTabindex ) {
1398	var map, mapName, img, focusableIfVisible, fieldset,
1399		nodeName = element.nodeName.toLowerCase();
1400
1401	if ( "area" === nodeName ) {
1402		map = element.parentNode;
1403		mapName = map.name;
1404		if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
1405			return false;
1406		}
1407		img = $( "img[usemap='#" + mapName + "']" );
1408		return img.length > 0 && img.is( ":visible" );
1409	}
1410
1411	if ( /^(input|select|textarea|button|object)$/.test( nodeName ) ) {
1412		focusableIfVisible = !element.disabled;
1413
1414		if ( focusableIfVisible ) {
1415
1416			// Form controls within a disabled fieldset are disabled.
1417			// However, controls within the fieldset's legend do not get disabled.
1418			// Since controls generally aren't placed inside legends, we skip
1419			// this portion of the check.
1420			fieldset = $( element ).closest( "fieldset" )[ 0 ];
1421			if ( fieldset ) {
1422				focusableIfVisible = !fieldset.disabled;
1423			}
1424		}
1425	} else if ( "a" === nodeName ) {
1426		focusableIfVisible = element.href || hasTabindex;
1427	} else {
1428		focusableIfVisible = hasTabindex;
1429	}
1430
1431	return focusableIfVisible && $( element ).is( ":visible" ) && visible( $( element ) );
1432};
1433
1434// Support: IE 8 only
1435// IE 8 doesn't resolve inherit to visible/hidden for computed values
1436function visible( element ) {
1437	var visibility = element.css( "visibility" );
1438	while ( visibility === "inherit" ) {
1439		element = element.parent();
1440		visibility = element.css( "visibility" );
1441	}
1442	return visibility !== "hidden";
1443}
1444
1445$.extend( $.expr[ ":" ], {
1446	focusable: function( element ) {
1447		return $.ui.focusable( element, $.attr( element, "tabindex" ) != null );
1448	}
1449} );
1450
1451var focusable = $.ui.focusable;
1452
1453
1454
1455
1456// Support: IE8 Only
1457// IE8 does not support the form attribute and when it is supplied. It overwrites the form prop
1458// with a string, so we need to find the proper form.
1459var form = $.fn.form = function() {
1460	return typeof this[ 0 ].form === "string" ? this.closest( "form" ) : $( this[ 0 ].form );
1461};
1462
1463
1464/*!
1465 * jQuery UI Form Reset Mixin 1.12.1
1466 * http://jqueryui.com
1467 *
1468 * Copyright jQuery Foundation and other contributors
1469 * Released under the MIT license.
1470 * http://jquery.org/license
1471 */
1472
1473//>>label: Form Reset Mixin
1474//>>group: Core
1475//>>description: Refresh input widgets when their form is reset
1476//>>docs: http://api.jqueryui.com/form-reset-mixin/
1477
1478
1479
1480var formResetMixin = $.ui.formResetMixin = {
1481	_formResetHandler: function() {
1482		var form = $( this );
1483
1484		// Wait for the form reset to actually happen before refreshing
1485		setTimeout( function() {
1486			var instances = form.data( "ui-form-reset-instances" );
1487			$.each( instances, function() {
1488				this.refresh();
vendor: 4,158 bytes, lines 1489-1654
1489			} );
1490		} );
1491	},
1492
1493	_bindFormResetHandler: function() {
1494		this.form = this.element.form();
1495		if ( !this.form.length ) {
1496			return;
1497		}
1498
1499		var instances = this.form.data( "ui-form-reset-instances" ) || [];
1500		if ( !instances.length ) {
1501
1502			// We don't use _on() here because we use a single event handler per form
1503			this.form.on( "reset.ui-form-reset", this._formResetHandler );
1504		}
1505		instances.push( this );
1506		this.form.data( "ui-form-reset-instances", instances );
1507	},
1508
1509	_unbindFormResetHandler: function() {
1510		if ( !this.form.length ) {
1511			return;
1512		}
1513
1514		var instances = this.form.data( "ui-form-reset-instances" );
1515		instances.splice( $.inArray( this, instances ), 1 );
1516		if ( instances.length ) {
1517			this.form.data( "ui-form-reset-instances", instances );
1518		} else {
1519			this.form
1520				.removeData( "ui-form-reset-instances" )
1521				.off( "reset.ui-form-reset" );
1522		}
1523	}
1524};
1525
1526
1527/*!
1528 * jQuery UI Support for jQuery core 1.7.x 1.12.1
1529 * http://jqueryui.com
1530 *
1531 * Copyright jQuery Foundation and other contributors
1532 * Released under the MIT license.
1533 * http://jquery.org/license
1534 *
1535 */
1536
1537//>>label: jQuery 1.7 Support
1538//>>group: Core
1539//>>description: Support version 1.7.x of jQuery core
1540
1541
1542
1543// Support: jQuery 1.7 only
1544// Not a great way to check versions, but since we only support 1.7+ and only
1545// need to detect <1.8, this is a simple check that should suffice. Checking
1546// for "1.7." would be a bit safer, but the version string is 1.7, not 1.7.0
1547// and we'll never reach 1.70.0 (if we do, we certainly won't be supporting
1548// 1.7 anymore). See #11197 for why we're not using feature detection.
1549if ( $.fn.jquery.substring( 0, 3 ) === "1.7" ) {
1550
1551	// Setters for .innerWidth(), .innerHeight(), .outerWidth(), .outerHeight()
1552	// Unlike jQuery Core 1.8+, these only support numeric values to set the
1553	// dimensions in pixels
1554	$.each( [ "Width", "Height" ], function( i, name ) {
1555		var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
1556			type = name.toLowerCase(),
1557			orig = {
1558				innerWidth: $.fn.innerWidth,
1559				innerHeight: $.fn.innerHeight,
1560				outerWidth: $.fn.outerWidth,
1561				outerHeight: $.fn.outerHeight
1562			};
1563
1564		function reduce( elem, size, border, margin ) {
1565			$.each( side, function() {
1566				size -= parseFloat( $.css( elem, "padding" + this ) ) || 0;
1567				if ( border ) {
1568					size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0;
1569				}
1570				if ( margin ) {
1571					size -= parseFloat( $.css( elem, "margin" + this ) ) || 0;
1572				}
1573			} );
1574			return size;
1575		}
1576
1577		$.fn[ "inner" + name ] = function( size ) {
1578			if ( size === undefined ) {
1579				return orig[ "inner" + name ].call( this );
1580			}
1581
1582			return this.each( function() {
1583				$( this ).css( type, reduce( this, size ) + "px" );
1584			} );
1585		};
1586
1587		$.fn[ "outer" + name ] = function( size, margin ) {
1588			if ( typeof size !== "number" ) {
1589				return orig[ "outer" + name ].call( this, size );
1590			}
1591
1592			return this.each( function() {
1593				$( this ).css( type, reduce( this, size, true, margin ) + "px" );
1594			} );
1595		};
1596	} );
1597
1598	$.fn.addBack = function( selector ) {
1599		return this.add( selector == null ?
1600			this.prevObject : this.prevObject.filter( selector )
1601		);
1602	};
1603}
1604
1605;
1606/*!
1607 * jQuery UI Keycode 1.12.1
1608 * http://jqueryui.com
1609 *
1610 * Copyright jQuery Foundation and other contributors
1611 * Released under the MIT license.
1612 * http://jquery.org/license
1613 */
1614
1615//>>label: Keycode
1616//>>group: Core
1617//>>description: Provide keycodes as keynames
1618//>>docs: http://api.jqueryui.com/jQuery.ui.keyCode/
1619
1620
1621var keycode = $.ui.keyCode = {
1622	BACKSPACE: 8,
1623	COMMA: 188,
1624	DELETE: 46,
1625	DOWN: 40,
1626	END: 35,
1627	ENTER: 13,
1628	ESCAPE: 27,
1629	HOME: 36,
1630	LEFT: 37,
1631	PAGE_DOWN: 34,
1632	PAGE_UP: 33,
1633	PERIOD: 190,
1634	RIGHT: 39,
1635	SPACE: 32,
1636	TAB: 9,
1637	UP: 38
1638};
1639
1640
1641
1642
1643// Internal use only
1644var escapeSelector = $.ui.escapeSelector = ( function() {
1645	var selectorEscape = /([!"#$%&'()*+,./:;<=>?@[\]^`{|}~])/g;
1646	return function( selector ) {
1647		return selector.replace( selectorEscape, "\\$1" );
1648	};
1649} )();
1650
1651
1652/*!
1653 * jQuery UI Labels 1.12.1
1654 * http://jqueryui.com
vendor: 4,601 bytes, lines 1655-1835
1655 *
1656 * Copyright jQuery Foundation and other contributors
1657 * Released under the MIT license.
1658 * http://jquery.org/license
1659 */
1660
1661//>>label: labels
1662//>>group: Core
1663//>>description: Find all the labels associated with a given input
1664//>>docs: http://api.jqueryui.com/labels/
1665
1666
1667
1668var labels = $.fn.labels = function() {
1669	var ancestor, selector, id, labels, ancestors;
1670
1671	// Check control.labels first
1672	if ( this[ 0 ].labels && this[ 0 ].labels.length ) {
1673		return this.pushStack( this[ 0 ].labels );
1674	}
1675
1676	// Support: IE <= 11, FF <= 37, Android <= 2.3 only
1677	// Above browsers do not support control.labels. Everything below is to support them
1678	// as well as document fragments. control.labels does not work on document fragments
1679	labels = this.eq( 0 ).parents( "label" );
1680
1681	// Look for the label based on the id
1682	id = this.attr( "id" );
1683	if ( id ) {
1684
1685		// We don't search against the document in case the element
1686		// is disconnected from the DOM
1687		ancestor = this.eq( 0 ).parents().last();
1688
1689		// Get a full set of top level ancestors
1690		ancestors = ancestor.add( ancestor.length ? ancestor.siblings() : this.siblings() );
1691
1692		// Create a selector for the label based on the id
1693		selector = "label[for='" + $.ui.escapeSelector( id ) + "']";
1694
1695		labels = labels.add( ancestors.find( selector ).addBack( selector ) );
1696
1697	}
1698
1699	// Return whatever we have found for labels
1700	return this.pushStack( labels );
1701};
1702
1703
1704/*!
1705 * jQuery UI Scroll Parent 1.12.1
1706 * http://jqueryui.com
1707 *
1708 * Copyright jQuery Foundation and other contributors
1709 * Released under the MIT license.
1710 * http://jquery.org/license
1711 */
1712
1713//>>label: scrollParent
1714//>>group: Core
1715//>>description: Get the closest ancestor element that is scrollable.
1716//>>docs: http://api.jqueryui.com/scrollParent/
1717
1718
1719
1720var scrollParent = $.fn.scrollParent = function( includeHidden ) {
1721	var position = this.css( "position" ),
1722		excludeStaticParent = position === "absolute",
1723		overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/,
1724		scrollParent = this.parents().filter( function() {
1725			var parent = $( this );
1726			if ( excludeStaticParent && parent.css( "position" ) === "static" ) {
1727				return false;
1728			}
1729			return overflowRegex.test( parent.css( "overflow" ) + parent.css( "overflow-y" ) +
1730				parent.css( "overflow-x" ) );
1731		} ).eq( 0 );
1732
1733	return position === "fixed" || !scrollParent.length ?
1734		$( this[ 0 ].ownerDocument || document ) :
1735		scrollParent;
1736};
1737
1738
1739/*!
1740 * jQuery UI Tabbable 1.12.1
1741 * http://jqueryui.com
1742 *
1743 * Copyright jQuery Foundation and other contributors
1744 * Released under the MIT license.
1745 * http://jquery.org/license
1746 */
1747
1748//>>label: :tabbable Selector
1749//>>group: Core
1750//>>description: Selects elements which can be tabbed to.
1751//>>docs: http://api.jqueryui.com/tabbable-selector/
1752
1753
1754
1755var tabbable = $.extend( $.expr[ ":" ], {
1756	tabbable: function( element ) {
1757		var tabIndex = $.attr( element, "tabindex" ),
1758			hasTabindex = tabIndex != null;
1759		return ( !hasTabindex || tabIndex >= 0 ) && $.ui.focusable( element, hasTabindex );
1760	}
1761} );
1762
1763
1764/*!
1765 * jQuery UI Unique ID 1.12.1
1766 * http://jqueryui.com
1767 *
1768 * Copyright jQuery Foundation and other contributors
1769 * Released under the MIT license.
1770 * http://jquery.org/license
1771 */
1772
1773//>>label: uniqueId
1774//>>group: Core
1775//>>description: Functions to generate and remove uniqueId's
1776//>>docs: http://api.jqueryui.com/uniqueId/
1777
1778
1779
1780var uniqueId = $.fn.extend( {
1781	uniqueId: ( function() {
1782		var uuid = 0;
1783
1784		return function() {
1785			return this.each( function() {
1786				if ( !this.id ) {
1787					this.id = "ui-id-" + ( ++uuid );
1788				}
1789			} );
1790		};
1791	} )(),
1792
1793	removeUniqueId: function() {
1794		return this.each( function() {
1795			if ( /^ui-id-\d+$/.test( this.id ) ) {
1796				$( this ).removeAttr( "id" );
1797			}
1798		} );
1799	}
1800} );
1801
1802
1803
1804
1805// This file is deprecated
1806var ie = $.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() );
1807
1808/*!
1809 * jQuery UI Mouse 1.12.1
1810 * http://jqueryui.com
1811 *
1812 * Copyright jQuery Foundation and other contributors
1813 * Released under the MIT license.
1814 * http://jquery.org/license
1815 */
1816
1817//>>label: Mouse
1818//>>group: Widgets
1819//>>description: Abstracts mouse-based interactions to assist in creating certain widgets.
1820//>>docs: http://api.jqueryui.com/mouse/
1821
1822
1823
1824var mouseHandled = false;
1825$( document ).on( "mouseup", function() {
1826	mouseHandled = false;
1827} );
1828
1829var widgetsMouse = $.widget( "ui.mouse", {
1830	version: "1.12.1",
1831	options: {
1832		cancel: "input, textarea, button, select, option",
1833		distance: 1,
1834		delay: 0
1835	},
vendor: 2,991 bytes, lines 1836-1932
1836	_mouseInit: function() {
1837		var that = this;
1838
1839		this.element
1840			.on( "mousedown." + this.widgetName, function( event ) {
1841				return that._mouseDown( event );
1842			} )
1843			.on( "click." + this.widgetName, function( event ) {
1844				if ( true === $.data( event.target, that.widgetName + ".preventClickEvent" ) ) {
1845					$.removeData( event.target, that.widgetName + ".preventClickEvent" );
1846					event.stopImmediatePropagation();
1847					return false;
1848				}
1849			} );
1850
1851		this.started = false;
1852	},
1853
1854	// TODO: make sure destroying one instance of mouse doesn't mess with
1855	// other instances of mouse
1856	_mouseDestroy: function() {
1857		this.element.off( "." + this.widgetName );
1858		if ( this._mouseMoveDelegate ) {
1859			this.document
1860				.off( "mousemove." + this.widgetName, this._mouseMoveDelegate )
1861				.off( "mouseup." + this.widgetName, this._mouseUpDelegate );
1862		}
1863	},
1864
1865	_mouseDown: function( event ) {
1866
1867		// don't let more than one widget handle mouseStart
1868		if ( mouseHandled ) {
1869			return;
1870		}
1871
1872		this._mouseMoved = false;
1873
1874		// We may have missed mouseup (out of window)
1875		( this._mouseStarted && this._mouseUp( event ) );
1876
1877		this._mouseDownEvent = event;
1878
1879		var that = this,
1880			btnIsLeft = ( event.which === 1 ),
1881
1882			// event.target.nodeName works around a bug in IE 8 with
1883			// disabled inputs (#7620)
1884			elIsCancel = ( typeof this.options.cancel === "string" && event.target.nodeName ?
1885				$( event.target ).closest( this.options.cancel ).length : false );
1886		if ( !btnIsLeft || elIsCancel || !this._mouseCapture( event ) ) {
1887			return true;
1888		}
1889
1890		this.mouseDelayMet = !this.options.delay;
1891		if ( !this.mouseDelayMet ) {
1892			this._mouseDelayTimer = setTimeout( function() {
1893				that.mouseDelayMet = true;
1894			}, this.options.delay );
1895		}
1896
1897		if ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) {
1898			this._mouseStarted = ( this._mouseStart( event ) !== false );
1899			if ( !this._mouseStarted ) {
1900				event.preventDefault();
1901				return true;
1902			}
1903		}
1904
1905		// Click event may never have fired (Gecko & Opera)
1906		if ( true === $.data( event.target, this.widgetName + ".preventClickEvent" ) ) {
1907			$.removeData( event.target, this.widgetName + ".preventClickEvent" );
1908		}
1909
1910		// These delegates are required to keep context
1911		this._mouseMoveDelegate = function( event ) {
1912			return that._mouseMove( event );
1913		};
1914		this._mouseUpDelegate = function( event ) {
1915			return that._mouseUp( event );
1916		};
1917
1918		this.document
1919			.on( "mousemove." + this.widgetName, this._mouseMoveDelegate )
1920			.on( "mouseup." + this.widgetName, this._mouseUpDelegate );
1921
1922		event.preventDefault();
1923
1924		mouseHandled = true;
1925		return true;
1926	},
1927
1928	_mouseMove: function( event ) {
1929
1930		// Only check for mouseups outside the document if you've moved inside the document
1931		// at least once. This prevents the firing of mouseup in the case of IE<9, which will
1932		// fire a mousemove event if content is placed under the cursor. See #7778
vendor: 4,365 bytes, lines 1933-2096
1933		// Support: IE <9
1934		if ( this._mouseMoved ) {
1935
1936			// IE mouseup check - mouseup happened when mouse was out of window
1937			if ( $.ui.ie && ( !document.documentMode || document.documentMode < 9 ) &&
1938					!event.button ) {
1939				return this._mouseUp( event );
1940
1941			// Iframe mouseup check - mouseup occurred in another document
1942			} else if ( !event.which ) {
1943
1944				// Support: Safari <=8 - 9
1945				// Safari sets which to 0 if you press any of the following keys
1946				// during a drag (#14461)
1947				if ( event.originalEvent.altKey || event.originalEvent.ctrlKey ||
1948						event.originalEvent.metaKey || event.originalEvent.shiftKey ) {
1949					this.ignoreMissingWhich = true;
1950				} else if ( !this.ignoreMissingWhich ) {
1951					return this._mouseUp( event );
1952				}
1953			}
1954		}
1955
1956		if ( event.which || event.button ) {
1957			this._mouseMoved = true;
1958		}
1959
1960		if ( this._mouseStarted ) {
1961			this._mouseDrag( event );
1962			return event.preventDefault();
1963		}
1964
1965		if ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) {
1966			this._mouseStarted =
1967				( this._mouseStart( this._mouseDownEvent, event ) !== false );
1968			( this._mouseStarted ? this._mouseDrag( event ) : this._mouseUp( event ) );
1969		}
1970
1971		return !this._mouseStarted;
1972	},
1973
1974	_mouseUp: function( event ) {
1975		this.document
1976			.off( "mousemove." + this.widgetName, this._mouseMoveDelegate )
1977			.off( "mouseup." + this.widgetName, this._mouseUpDelegate );
1978
1979		if ( this._mouseStarted ) {
1980			this._mouseStarted = false;
1981
1982			if ( event.target === this._mouseDownEvent.target ) {
1983				$.data( event.target, this.widgetName + ".preventClickEvent", true );
1984			}
1985
1986			this._mouseStop( event );
1987		}
1988
1989		if ( this._mouseDelayTimer ) {
1990			clearTimeout( this._mouseDelayTimer );
1991			delete this._mouseDelayTimer;
1992		}
1993
1994		this.ignoreMissingWhich = false;
1995		mouseHandled = false;
1996		event.preventDefault();
1997	},
1998
1999	_mouseDistanceMet: function( event ) {
2000		return ( Math.max(
2001				Math.abs( this._mouseDownEvent.pageX - event.pageX ),
2002				Math.abs( this._mouseDownEvent.pageY - event.pageY )
2003			) >= this.options.distance
2004		);
2005	},
2006
2007	_mouseDelayMet: function( /* event */ ) {
2008		return this.mouseDelayMet;
2009	},
2010
2011	// These are placeholder methods, to be overriden by extending plugin
2012	_mouseStart: function( /* event */ ) {},
2013	_mouseDrag: function( /* event */ ) {},
2014	_mouseStop: function( /* event */ ) {},
2015	_mouseCapture: function( /* event */ ) { return true; }
2016} );
2017
2018
2019
2020
2021// $.ui.plugin is deprecated. Use $.widget() extensions instead.
2022var plugin = $.ui.plugin = {
2023	add: function( module, option, set ) {
2024		var i,
2025			proto = $.ui[ module ].prototype;
2026		for ( i in set ) {
2027			proto.plugins[ i ] = proto.plugins[ i ] || [];
2028			proto.plugins[ i ].push( [ option, set[ i ] ] );
2029		}
2030	},
2031	call: function( instance, name, args, allowDisconnected ) {
2032		var i,
2033			set = instance.plugins[ name ];
2034
2035		if ( !set ) {
2036			return;
2037		}
2038
2039		if ( !allowDisconnected && ( !instance.element[ 0 ].parentNode ||
2040				instance.element[ 0 ].parentNode.nodeType === 11 ) ) {
2041			return;
2042		}
2043
2044		for ( i = 0; i < set.length; i++ ) {
2045			if ( instance.options[ set[ i ][ 0 ] ] ) {
2046				set[ i ][ 1 ].apply( instance.element, args );
2047			}
2048		}
2049	}
2050};
2051
2052
2053
2054var safeActiveElement = $.ui.safeActiveElement = function( document ) {
2055	var activeElement;
2056
2057	// Support: IE 9 only
2058	// IE9 throws an "Unspecified error" accessing document.activeElement from an <iframe>
2059	try {
2060		activeElement = document.activeElement;
2061	} catch ( error ) {
2062		activeElement = document.body;
2063	}
2064
2065	// Support: IE 9 - 11 only
2066	// IE may return null instead of an element
2067	// Interestingly, this only seems to occur when NOT in an iframe
2068	if ( !activeElement ) {
2069		activeElement = document.body;
2070	}
2071
2072	// Support: IE 11 only
2073	// IE11 returns a seemingly empty object in some cases when accessing
2074	// document.activeElement from an <iframe>
2075	if ( !activeElement.nodeName ) {
2076		activeElement = document.body;
2077	}
2078
2079	return activeElement;
2080};
2081
2082
2083
2084var safeBlur = $.ui.safeBlur = function( element ) {
2085
2086	// Support: IE9 - 10 only
2087	// If the <body data-rsssl=1> is blurred, IE will switch windows, see #9420
2088	if ( element && element.nodeName.toLowerCase() !== "body" ) {
2089		$( element ).trigger( "blur" );
2090	}
2091};
2092
2093
2094/*!
2095 * jQuery UI Draggable 1.12.1
2096 * http://jqueryui.com
vendor: 4,141 bytes, lines 2097-2265
2097 *
2098 * Copyright jQuery Foundation and other contributors
2099 * Released under the MIT license.
2100 * http://jquery.org/license
2101 */
2102
2103//>>label: Draggable
2104//>>group: Interactions
2105//>>description: Enables dragging functionality for any element.
2106//>>docs: http://api.jqueryui.com/draggable/
2107//>>demos: http://jqueryui.com/draggable/
2108//>>css.structure: ../../themes/base/draggable.css
2109
2110
2111
2112$.widget( "ui.draggable", $.ui.mouse, {
2113	version: "1.12.1",
2114	widgetEventPrefix: "drag",
2115	options: {
2116		addClasses: true,
2117		appendTo: "parent",
2118		axis: false,
2119		connectToSortable: false,
2120		containment: false,
2121		cursor: "auto",
2122		cursorAt: false,
2123		grid: false,
2124		handle: false,
2125		helper: "original",
2126		iframeFix: false,
2127		opacity: false,
2128		refreshPositions: false,
2129		revert: false,
2130		revertDuration: 500,
2131		scope: "default",
2132		scroll: true,
2133		scrollSensitivity: 20,
2134		scrollSpeed: 20,
2135		snap: false,
2136		snapMode: "both",
2137		snapTolerance: 20,
2138		stack: false,
2139		zIndex: false,
2140
2141		// Callbacks
2142		drag: null,
2143		start: null,
2144		stop: null
2145	},
2146	_create: function() {
2147
2148		if ( this.options.helper === "original" ) {
2149			this._setPositionRelative();
2150		}
2151		if ( this.options.addClasses ) {
2152			this._addClass( "ui-draggable" );
2153		}
2154		this._setHandleClassName();
2155
2156		this._mouseInit();
2157	},
2158
2159	_setOption: function( key, value ) {
2160		this._super( key, value );
2161		if ( key === "handle" ) {
2162			this._removeHandleClassName();
2163			this._setHandleClassName();
2164		}
2165	},
2166
2167	_destroy: function() {
2168		if ( ( this.helper || this.element ).is( ".ui-draggable-dragging" ) ) {
2169			this.destroyOnClear = true;
2170			return;
2171		}
2172		this._removeHandleClassName();
2173		this._mouseDestroy();
2174	},
2175
2176	_mouseCapture: function( event ) {
2177		var o = this.options;
2178
2179		// Among others, prevent a drag on a resizable-handle
2180		if ( this.helper || o.disabled ||
2181				$( event.target ).closest( ".ui-resizable-handle" ).length > 0 ) {
2182			return false;
2183		}
2184
2185		//Quit if we're not on a valid handle
2186		this.handle = this._getHandle( event );
2187		if ( !this.handle ) {
2188			return false;
2189		}
2190
2191		this._blurActiveElement( event );
2192
2193		this._blockFrames( o.iframeFix === true ? "iframe" : o.iframeFix );
2194
2195		return true;
2196
2197	},
2198
2199	_blockFrames: function( selector ) {
2200		this.iframeBlocks = this.document.find( selector ).map( function() {
2201			var iframe = $( this );
2202
2203			return $( "<div>" )
2204				.css( "position", "absolute" )
2205				.appendTo( iframe.parent() )
2206				.outerWidth( iframe.outerWidth() )
2207				.outerHeight( iframe.outerHeight() )
2208				.offset( iframe.offset() )[ 0 ];
2209		} );
2210	},
2211
2212	_unblockFrames: function() {
2213		if ( this.iframeBlocks ) {
2214			this.iframeBlocks.remove();
2215			delete this.iframeBlocks;
2216		}
2217	},
2218
2219	_blurActiveElement: function( event ) {
2220		var activeElement = $.ui.safeActiveElement( this.document[ 0 ] ),
2221			target = $( event.target );
2222
2223		// Don't blur if the event occurred on an element that is within
2224		// the currently focused element
2225		// See #10527, #12472
2226		if ( target.closest( activeElement ).length ) {
2227			return;
2228		}
2229
2230		// Blur any element that currently has focus, see #4261
2231		$.ui.safeBlur( activeElement );
2232	},
2233
2234	_mouseStart: function( event ) {
2235
2236		var o = this.options;
2237
2238		//Create and append the visible helper
2239		this.helper = this._createHelper( event );
2240
2241		this._addClass( this.helper, "ui-draggable-dragging" );
2242
2243		//Cache the helper size
2244		this._cacheHelperProportions();
2245
2246		//If ddmanager is used for droppables, set the global draggable
2247		if ( $.ui.ddmanager ) {
2248			$.ui.ddmanager.current = this;
2249		}
2250
2251		/*
2252		 * - Position generation -
2253		 * This block generates everything position related - it's the core of draggables.
2254		 */
2255
2256		//Cache the margins of the original element
2257		this._cacheMargins();
2258
2259		//Store the helper's css position
2260		this.cssPosition = this.helper.css( "position" );
2261		this.scrollParent = this.helper.scrollParent( true );
2262		this.offsetParent = this.helper.offsetParent();
2263		this.hasFixedAncestor = this.helper.parents().filter( function() {
2264				return $( this ).css( "position" ) === "fixed";
2265			} ).length > 0;
vendor: 5,410 bytes, lines 2266-2458
2266
2267		//The element's absolute position on the page minus margins
2268		this.positionAbs = this.element.offset();
2269		this._refreshOffsets( event );
2270
2271		//Generate the original position
2272		this.originalPosition = this.position = this._generatePosition( event, false );
2273		this.originalPageX = event.pageX;
2274		this.originalPageY = event.pageY;
2275
2276		//Adjust the mouse offset relative to the helper if "cursorAt" is supplied
2277		( o.cursorAt && this._adjustOffsetFromHelper( o.cursorAt ) );
2278
2279		//Set a containment if given in the options
2280		this._setContainment();
2281
2282		//Trigger event + callbacks
2283		if ( this._trigger( "start", event ) === false ) {
2284			this._clear();
2285			return false;
2286		}
2287
2288		//Recache the helper size
2289		this._cacheHelperProportions();
2290
2291		//Prepare the droppable offsets
2292		if ( $.ui.ddmanager && !o.dropBehaviour ) {
2293			$.ui.ddmanager.prepareOffsets( this, event );
2294		}
2295
2296		// Execute the drag once - this causes the helper not to be visible before getting its
2297		// correct position
2298		this._mouseDrag( event, true );
2299
2300		// If the ddmanager is used for droppables, inform the manager that dragging has started
2301		// (see #5003)
2302		if ( $.ui.ddmanager ) {
2303			$.ui.ddmanager.dragStart( this, event );
2304		}
2305
2306		return true;
2307	},
2308
2309	_refreshOffsets: function( event ) {
2310		this.offset = {
2311			top: this.positionAbs.top - this.margins.top,
2312			left: this.positionAbs.left - this.margins.left,
2313			scroll: false,
2314			parent: this._getParentOffset(),
2315			relative: this._getRelativeOffset()
2316		};
2317
2318		this.offset.click = {
2319			left: event.pageX - this.offset.left,
2320			top: event.pageY - this.offset.top
2321		};
2322	},
2323
2324	_mouseDrag: function( event, noPropagation ) {
2325
2326		// reset any necessary cached properties (see #5009)
2327		if ( this.hasFixedAncestor ) {
2328			this.offset.parent = this._getParentOffset();
2329		}
2330
2331		//Compute the helpers position
2332		this.position = this._generatePosition( event, true );
2333		this.positionAbs = this._convertPositionTo( "absolute" );
2334
2335		//Call plugins and callbacks and use the resulting position if something is returned
2336		if ( !noPropagation ) {
2337			var ui = this._uiHash();
2338			if ( this._trigger( "drag", event, ui ) === false ) {
2339				this._mouseUp( new $.Event( "mouseup", event ) );
2340				return false;
2341			}
2342			this.position = ui.position;
2343		}
2344
2345		this.helper[ 0 ].style.left = this.position.left + "px";
2346		this.helper[ 0 ].style.top = this.position.top + "px";
2347
2348		if ( $.ui.ddmanager ) {
2349			$.ui.ddmanager.drag( this, event );
2350		}
2351
2352		return false;
2353	},
2354
2355	_mouseStop: function( event ) {
2356
2357		//If we are using droppables, inform the manager about the drop
2358		var that = this,
2359			dropped = false;
2360		if ( $.ui.ddmanager && !this.options.dropBehaviour ) {
2361			dropped = $.ui.ddmanager.drop( this, event );
2362		}
2363
2364		//if a drop comes from outside (a sortable)
2365		if ( this.dropped ) {
2366			dropped = this.dropped;
2367			this.dropped = false;
2368		}
2369
2370		if ( ( this.options.revert === "invalid" && !dropped ) ||
2371				( this.options.revert === "valid" && dropped ) ||
2372				this.options.revert === true || ( $.isFunction( this.options.revert ) &&
2373				this.options.revert.call( this.element, dropped ) )
2374		) {
2375			$( this.helper ).animate(
2376				this.originalPosition,
2377				parseInt( this.options.revertDuration, 10 ),
2378				function() {
2379					if ( that._trigger( "stop", event ) !== false ) {
2380						that._clear();
2381					}
2382				}
2383			);
2384		} else {
2385			if ( this._trigger( "stop", event ) !== false ) {
2386				this._clear();
2387			}
2388		}
2389
2390		return false;
2391	},
2392
2393	_mouseUp: function( event ) {
2394		this._unblockFrames();
2395
2396		// If the ddmanager is used for droppables, inform the manager that dragging has stopped
2397		// (see #5003)
2398		if ( $.ui.ddmanager ) {
2399			$.ui.ddmanager.dragStop( this, event );
2400		}
2401
2402		// Only need to focus if the event occurred on the draggable itself, see #10527
2403		if ( this.handleElement.is( event.target ) ) {
2404
2405			// The interaction is over; whether or not the click resulted in a drag,
2406			// focus the element
2407			this.element.trigger( "focus" );
2408		}
2409
2410		return $.ui.mouse.prototype._mouseUp.call( this, event );
2411	},
2412
2413	cancel: function() {
2414
2415		if ( this.helper.is( ".ui-draggable-dragging" ) ) {
2416			this._mouseUp( new $.Event( "mouseup", { target: this.element[ 0 ] } ) );
2417		} else {
2418			this._clear();
2419		}
2420
2421		return this;
2422
2423	},
2424
2425	_getHandle: function( event ) {
2426		return this.options.handle ?
2427			!!$( event.target ).closest( this.element.find( this.options.handle ) ).length :
2428			true;
2429	},
2430
2431	_setHandleClassName: function() {
2432		this.handleElement = this.options.handle ?
2433			this.element.find( this.options.handle ) : this.element;
2434		this._addClass( this.handleElement, "ui-draggable-handle" );
2435	},
2436
2437	_removeHandleClassName: function() {
2438		this._removeClass( this.handleElement, "ui-draggable-handle" );
2439	},
2440
2441	_createHelper: function( event ) {
2442
2443		var o = this.options,
2444			helperIsFunction = $.isFunction( o.helper ),
2445			helper = helperIsFunction ?
2446				$( o.helper.apply( this.element[ 0 ], [ event ] ) ) :
2447				( o.helper === "clone" ?
2448					this.element.clone().removeAttr( "id" ) :
2449					this.element );
2450
2451		if ( !helper.parents( "body" ).length ) {
2452			helper.appendTo( ( o.appendTo === "parent" ?
2453				this.element[ 0 ].parentNode :
2454				o.appendTo ) );
2455		}
2456
2457		// Http://bugs.jqueryui.com/ticket/9446
2458		// a helper function can return the original element
vendor: 15,341 bytes, lines 2459-2951
2459		// which wouldn't have been set to relative in _create
2460		if ( helperIsFunction && helper[ 0 ] === this.element[ 0 ] ) {
2461			this._setPositionRelative();
2462		}
2463
2464		if ( helper[ 0 ] !== this.element[ 0 ] &&
2465				!( /(fixed|absolute)/ ).test( helper.css( "position" ) ) ) {
2466			helper.css( "position", "absolute" );
2467		}
2468
2469		return helper;
2470
2471	},
2472
2473	_setPositionRelative: function() {
2474		if ( !( /^(?:r|a|f)/ ).test( this.element.css( "position" ) ) ) {
2475			this.element[ 0 ].style.position = "relative";
2476		}
2477	},
2478
2479	_adjustOffsetFromHelper: function( obj ) {
2480		if ( typeof obj === "string" ) {
2481			obj = obj.split( " " );
2482		}
2483		if ( $.isArray( obj ) ) {
2484			obj = { left: +obj[ 0 ], top: +obj[ 1 ] || 0 };
2485		}
2486		if ( "left" in obj ) {
2487			this.offset.click.left = obj.left + this.margins.left;
2488		}
2489		if ( "right" in obj ) {
2490			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
2491		}
2492		if ( "top" in obj ) {
2493			this.offset.click.top = obj.top + this.margins.top;
2494		}
2495		if ( "bottom" in obj ) {
2496			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
2497		}
2498	},
2499
2500	_isRootNode: function( element ) {
2501		return ( /(html|body)/i ).test( element.tagName ) || element === this.document[ 0 ];
2502	},
2503
2504	_getParentOffset: function() {
2505
2506		//Get the offsetParent and cache its position
2507		var po = this.offsetParent.offset(),
2508			document = this.document[ 0 ];
2509
2510		// This is a special case where we need to modify a offset calculated on start, since the
2511		// following happened:
2512		// 1. The position of the helper is absolute, so it's position is calculated based on the
2513		// next positioned parent
2514		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't
2515		// the document, which means that the scroll is included in the initial calculation of the
2516		// offset of the parent, and never recalculated upon drag
2517		if ( this.cssPosition === "absolute" && this.scrollParent[ 0 ] !== document &&
2518				$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) {
2519			po.left += this.scrollParent.scrollLeft();
2520			po.top += this.scrollParent.scrollTop();
2521		}
2522
2523		if ( this._isRootNode( this.offsetParent[ 0 ] ) ) {
2524			po = { top: 0, left: 0 };
2525		}
2526
2527		return {
2528			top: po.top + ( parseInt( this.offsetParent.css( "borderTopWidth" ), 10 ) || 0 ),
2529			left: po.left + ( parseInt( this.offsetParent.css( "borderLeftWidth" ), 10 ) || 0 )
2530		};
2531
2532	},
2533
2534	_getRelativeOffset: function() {
2535		if ( this.cssPosition !== "relative" ) {
2536			return { top: 0, left: 0 };
2537		}
2538
2539		var p = this.element.position(),
2540			scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );
2541
2542		return {
2543			top: p.top - ( parseInt( this.helper.css( "top" ), 10 ) || 0 ) +
2544				( !scrollIsRootNode ? this.scrollParent.scrollTop() : 0 ),
2545			left: p.left - ( parseInt( this.helper.css( "left" ), 10 ) || 0 ) +
2546				( !scrollIsRootNode ? this.scrollParent.scrollLeft() : 0 )
2547		};
2548
2549	},
2550
2551	_cacheMargins: function() {
2552		this.margins = {
2553			left: ( parseInt( this.element.css( "marginLeft" ), 10 ) || 0 ),
2554			top: ( parseInt( this.element.css( "marginTop" ), 10 ) || 0 ),
2555			right: ( parseInt( this.element.css( "marginRight" ), 10 ) || 0 ),
2556			bottom: ( parseInt( this.element.css( "marginBottom" ), 10 ) || 0 )
2557		};
2558	},
2559
2560	_cacheHelperProportions: function() {
2561		this.helperProportions = {
2562			width: this.helper.outerWidth(),
2563			height: this.helper.outerHeight()
2564		};
2565	},
2566
2567	_setContainment: function() {
2568
2569		var isUserScrollable, c, ce,
2570			o = this.options,
2571			document = this.document[ 0 ];
2572
2573		this.relativeContainer = null;
2574
2575		if ( !o.containment ) {
2576			this.containment = null;
2577			return;
2578		}
2579
2580		if ( o.containment === "window" ) {
2581			this.containment = [
2582				$( window ).scrollLeft() - this.offset.relative.left - this.offset.parent.left,
2583				$( window ).scrollTop() - this.offset.relative.top - this.offset.parent.top,
2584				$( window ).scrollLeft() + $( window ).width() -
2585					this.helperProportions.width - this.margins.left,
2586				$( window ).scrollTop() +
2587					( $( window ).height() || document.body.parentNode.scrollHeight ) -
2588					this.helperProportions.height - this.margins.top
2589			];
2590			return;
2591		}
2592
2593		if ( o.containment === "document" ) {
2594			this.containment = [
2595				0,
2596				0,
2597				$( document ).width() - this.helperProportions.width - this.margins.left,
2598				( $( document ).height() || document.body.parentNode.scrollHeight ) -
2599					this.helperProportions.height - this.margins.top
2600			];
2601			return;
2602		}
2603
2604		if ( o.containment.constructor === Array ) {
2605			this.containment = o.containment;
2606			return;
2607		}
2608
2609		if ( o.containment === "parent" ) {
2610			o.containment = this.helper[ 0 ].parentNode;
2611		}
2612
2613		c = $( o.containment );
2614		ce = c[ 0 ];
2615
2616		if ( !ce ) {
2617			return;
2618		}
2619
2620		isUserScrollable = /(scroll|auto)/.test( c.css( "overflow" ) );
2621
2622		this.containment = [
2623			( parseInt( c.css( "borderLeftWidth" ), 10 ) || 0 ) +
2624				( parseInt( c.css( "paddingLeft" ), 10 ) || 0 ),
2625			( parseInt( c.css( "borderTopWidth" ), 10 ) || 0 ) +
2626				( parseInt( c.css( "paddingTop" ), 10 ) || 0 ),
2627			( isUserScrollable ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) -
2628				( parseInt( c.css( "borderRightWidth" ), 10 ) || 0 ) -
2629				( parseInt( c.css( "paddingRight" ), 10 ) || 0 ) -
2630				this.helperProportions.width -
2631				this.margins.left -
2632				this.margins.right,
2633			( isUserScrollable ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) -
2634				( parseInt( c.css( "borderBottomWidth" ), 10 ) || 0 ) -
2635				( parseInt( c.css( "paddingBottom" ), 10 ) || 0 ) -
2636				this.helperProportions.height -
2637				this.margins.top -
2638				this.margins.bottom
2639		];
2640		this.relativeContainer = c;
2641	},
2642
2643	_convertPositionTo: function( d, pos ) {
2644
2645		if ( !pos ) {
2646			pos = this.position;
2647		}
2648
2649		var mod = d === "absolute" ? 1 : -1,
2650			scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );
2651
2652		return {
2653			top: (
2654
2655				// The absolute mouse position
2656				pos.top	+
2657
2658				// Only for relative positioned nodes: Relative offset from element to offset parent
2659				this.offset.relative.top * mod +
2660
2661				// The offsetParent's offset without borders (offset + border)
2662				this.offset.parent.top * mod -
2663				( ( this.cssPosition === "fixed" ?
2664					-this.offset.scroll.top :
2665					( scrollIsRootNode ? 0 : this.offset.scroll.top ) ) * mod )
2666			),
2667			left: (
2668
2669				// The absolute mouse position
2670				pos.left +
2671
2672				// Only for relative positioned nodes: Relative offset from element to offset parent
2673				this.offset.relative.left * mod +
2674
2675				// The offsetParent's offset without borders (offset + border)
2676				this.offset.parent.left * mod	-
2677				( ( this.cssPosition === "fixed" ?
2678					-this.offset.scroll.left :
2679					( scrollIsRootNode ? 0 : this.offset.scroll.left ) ) * mod )
2680			)
2681		};
2682
2683	},
2684
2685	_generatePosition: function( event, constrainPosition ) {
2686
2687		var containment, co, top, left,
2688			o = this.options,
2689			scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ),
2690			pageX = event.pageX,
2691			pageY = event.pageY;
2692
2693		// Cache the scroll
2694		if ( !scrollIsRootNode || !this.offset.scroll ) {
2695			this.offset.scroll = {
2696				top: this.scrollParent.scrollTop(),
2697				left: this.scrollParent.scrollLeft()
2698			};
2699		}
2700
2701		/*
2702		 * - Position constraining -
2703		 * Constrain the position to a mix of grid, containment.
2704		 */
2705
2706		// If we are not dragging yet, we won't check for options
2707		if ( constrainPosition ) {
2708			if ( this.containment ) {
2709				if ( this.relativeContainer ) {
2710					co = this.relativeContainer.offset();
2711					containment = [
2712						this.containment[ 0 ] + co.left,
2713						this.containment[ 1 ] + co.top,
2714						this.containment[ 2 ] + co.left,
2715						this.containment[ 3 ] + co.top
2716					];
2717				} else {
2718					containment = this.containment;
2719				}
2720
2721				if ( event.pageX - this.offset.click.left < containment[ 0 ] ) {
2722					pageX = containment[ 0 ] + this.offset.click.left;
2723				}
2724				if ( event.pageY - this.offset.click.top < containment[ 1 ] ) {
2725					pageY = containment[ 1 ] + this.offset.click.top;
2726				}
2727				if ( event.pageX - this.offset.click.left > containment[ 2 ] ) {
2728					pageX = containment[ 2 ] + this.offset.click.left;
2729				}
2730				if ( event.pageY - this.offset.click.top > containment[ 3 ] ) {
2731					pageY = containment[ 3 ] + this.offset.click.top;
2732				}
2733			}
2734
2735			if ( o.grid ) {
2736
2737				//Check for grid elements set to 0 to prevent divide by 0 error causing invalid
2738				// argument errors in IE (see ticket #6950)
2739				top = o.grid[ 1 ] ? this.originalPageY + Math.round( ( pageY -
2740					this.originalPageY ) / o.grid[ 1 ] ) * o.grid[ 1 ] : this.originalPageY;
2741				pageY = containment ? ( ( top - this.offset.click.top >= containment[ 1 ] ||
2742					top - this.offset.click.top > containment[ 3 ] ) ?
2743						top :
2744						( ( top - this.offset.click.top >= containment[ 1 ] ) ?
2745							top - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) : top;
2746
2747				left = o.grid[ 0 ] ? this.originalPageX +
2748					Math.round( ( pageX - this.originalPageX ) / o.grid[ 0 ] ) * o.grid[ 0 ] :
2749					this.originalPageX;
2750				pageX = containment ? ( ( left - this.offset.click.left >= containment[ 0 ] ||
2751					left - this.offset.click.left > containment[ 2 ] ) ?
2752						left :
2753						( ( left - this.offset.click.left >= containment[ 0 ] ) ?
2754							left - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) : left;
2755			}
2756
2757			if ( o.axis === "y" ) {
2758				pageX = this.originalPageX;
2759			}
2760
2761			if ( o.axis === "x" ) {
2762				pageY = this.originalPageY;
2763			}
2764		}
2765
2766		return {
2767			top: (
2768
2769				// The absolute mouse position
2770				pageY -
2771
2772				// Click offset (relative to the element)
2773				this.offset.click.top -
2774
2775				// Only for relative positioned nodes: Relative offset from element to offset parent
2776				this.offset.relative.top -
2777
2778				// The offsetParent's offset without borders (offset + border)
2779				this.offset.parent.top +
2780				( this.cssPosition === "fixed" ?
2781					-this.offset.scroll.top :
2782					( scrollIsRootNode ? 0 : this.offset.scroll.top ) )
2783			),
2784			left: (
2785
2786				// The absolute mouse position
2787				pageX -
2788
2789				// Click offset (relative to the element)
2790				this.offset.click.left -
2791
2792				// Only for relative positioned nodes: Relative offset from element to offset parent
2793				this.offset.relative.left -
2794
2795				// The offsetParent's offset without borders (offset + border)
2796				this.offset.parent.left +
2797				( this.cssPosition === "fixed" ?
2798					-this.offset.scroll.left :
2799					( scrollIsRootNode ? 0 : this.offset.scroll.left ) )
2800			)
2801		};
2802
2803	},
2804
2805	_clear: function() {
2806		this._removeClass( this.helper, "ui-draggable-dragging" );
2807		if ( this.helper[ 0 ] !== this.element[ 0 ] && !this.cancelHelperRemoval ) {
2808			this.helper.remove();
2809		}
2810		this.helper = null;
2811		this.cancelHelperRemoval = false;
2812		if ( this.destroyOnClear ) {
2813			this.destroy();
2814		}
2815	},
2816
2817	// From now on bulk stuff - mainly helpers
2818
2819	_trigger: function( type, event, ui ) {
2820		ui = ui || this._uiHash();
2821		$.ui.plugin.call( this, type, [ event, ui, this ], true );
2822
2823		// Absolute position and offset (see #6884 ) have to be recalculated after plugins
2824		if ( /^(drag|start|stop)/.test( type ) ) {
2825			this.positionAbs = this._convertPositionTo( "absolute" );
2826			ui.offset = this.positionAbs;
2827		}
2828		return $.Widget.prototype._trigger.call( this, type, event, ui );
2829	},
2830
2831	plugins: {},
2832
2833	_uiHash: function() {
2834		return {
2835			helper: this.helper,
2836			position: this.position,
2837			originalPosition: this.originalPosition,
2838			offset: this.positionAbs
2839		};
2840	}
2841
2842} );
2843
2844$.ui.plugin.add( "draggable", "connectToSortable", {
2845	start: function( event, ui, draggable ) {
2846		var uiSortable = $.extend( {}, ui, {
2847			item: draggable.element
2848		} );
2849
2850		draggable.sortables = [];
2851		$( draggable.options.connectToSortable ).each( function() {
2852			var sortable = $( this ).sortable( "instance" );
2853
2854			if ( sortable && !sortable.options.disabled ) {
2855				draggable.sortables.push( sortable );
2856
2857				// RefreshPositions is called at drag start to refresh the containerCache
2858				// which is used in drag. This ensures it's initialized and synchronized
2859				// with any changes that might have happened on the page since initialization.
2860				sortable.refreshPositions();
2861				sortable._trigger( "activate", event, uiSortable );
2862			}
2863		} );
2864	},
2865	stop: function( event, ui, draggable ) {
2866		var uiSortable = $.extend( {}, ui, {
2867			item: draggable.element
2868		} );
2869
2870		draggable.cancelHelperRemoval = false;
2871
2872		$.each( draggable.sortables, function() {
2873			var sortable = this;
2874
2875			if ( sortable.isOver ) {
2876				sortable.isOver = 0;
2877
2878				// Allow this sortable to handle removing the helper
2879				draggable.cancelHelperRemoval = true;
2880				sortable.cancelHelperRemoval = false;
2881
2882				// Use _storedCSS To restore properties in the sortable,
2883				// as this also handles revert (#9675) since the draggable
2884				// may have modified them in unexpected ways (#8809)
2885				sortable._storedCSS = {
2886					position: sortable.placeholder.css( "position" ),
2887					top: sortable.placeholder.css( "top" ),
2888					left: sortable.placeholder.css( "left" )
2889				};
2890
2891				sortable._mouseStop( event );
2892
2893				// Once drag has ended, the sortable should return to using
2894				// its original helper, not the shared helper from draggable
2895				sortable.options.helper = sortable.options._helper;
2896			} else {
2897
2898				// Prevent this Sortable from removing the helper.
2899				// However, don't set the draggable to remove the helper
2900				// either as another connected Sortable may yet handle the removal.
2901				sortable.cancelHelperRemoval = true;
2902
2903				sortable._trigger( "deactivate", event, uiSortable );
2904			}
2905		} );
2906	},
2907	drag: function( event, ui, draggable ) {
2908		$.each( draggable.sortables, function() {
2909			var innermostIntersecting = false,
2910				sortable = this;
2911
2912			// Copy over variables that sortable's _intersectsWith uses
2913			sortable.positionAbs = draggable.positionAbs;
2914			sortable.helperProportions = draggable.helperProportions;
2915			sortable.offset.click = draggable.offset.click;
2916
2917			if ( sortable._intersectsWith( sortable.containerCache ) ) {
2918				innermostIntersecting = true;
2919
2920				$.each( draggable.sortables, function() {
2921
2922					// Copy over variables that sortable's _intersectsWith uses
2923					this.positionAbs = draggable.positionAbs;
2924					this.helperProportions = draggable.helperProportions;
2925					this.offset.click = draggable.offset.click;
2926
2927					if ( this !== sortable &&
2928							this._intersectsWith( this.containerCache ) &&
2929							$.contains( sortable.element[ 0 ], this.element[ 0 ] ) ) {
2930						innermostIntersecting = false;
2931					}
2932
2933					return innermostIntersecting;
2934				} );
2935			}
2936
2937			if ( innermostIntersecting ) {
2938
2939				// If it intersects, we use a little isOver variable and set it once,
2940				// so that the move-in stuff gets fired only once.
2941				if ( !sortable.isOver ) {
2942					sortable.isOver = 1;
2943
2944					// Store draggable's parent in case we need to reappend to it later.
2945					draggable._parent = ui.helper.parent();
2946
2947					sortable.currentItem = ui.helper
2948						.appendTo( sortable.element )
2949						.data( "ui-sortable-item", true );
2950
2951					// Store helper option to later restore it
vendor: 11,429 bytes, lines 2952-3326
2952					sortable.options._helper = sortable.options.helper;
2953
2954					sortable.options.helper = function() {
2955						return ui.helper[ 0 ];
2956					};
2957
2958					// Fire the start events of the sortable with our passed browser event,
2959					// and our own helper (so it doesn't create a new one)
2960					event.target = sortable.currentItem[ 0 ];
2961					sortable._mouseCapture( event, true );
2962					sortable._mouseStart( event, true, true );
2963
2964					// Because the browser event is way off the new appended portlet,
2965					// modify necessary variables to reflect the changes
2966					sortable.offset.click.top = draggable.offset.click.top;
2967					sortable.offset.click.left = draggable.offset.click.left;
2968					sortable.offset.parent.left -= draggable.offset.parent.left -
2969						sortable.offset.parent.left;
2970					sortable.offset.parent.top -= draggable.offset.parent.top -
2971						sortable.offset.parent.top;
2972
2973					draggable._trigger( "toSortable", event );
2974
2975					// Inform draggable that the helper is in a valid drop zone,
2976					// used solely in the revert option to handle "valid/invalid".
2977					draggable.dropped = sortable.element;
2978
2979					// Need to refreshPositions of all sortables in the case that
2980					// adding to one sortable changes the location of the other sortables (#9675)
2981					$.each( draggable.sortables, function() {
2982						this.refreshPositions();
2983					} );
2984
2985					// Hack so receive/update callbacks work (mostly)
2986					draggable.currentItem = draggable.element;
2987					sortable.fromOutside = draggable;
2988				}
2989
2990				if ( sortable.currentItem ) {
2991					sortable._mouseDrag( event );
2992
2993					// Copy the sortable's position because the draggable's can potentially reflect
2994					// a relative position, while sortable is always absolute, which the dragged
2995					// element has now become. (#8809)
2996					ui.position = sortable.position;
2997				}
2998			} else {
2999
3000				// If it doesn't intersect with the sortable, and it intersected before,
3001				// we fake the drag stop of the sortable, but make sure it doesn't remove
3002				// the helper by using cancelHelperRemoval.
3003				if ( sortable.isOver ) {
3004
3005					sortable.isOver = 0;
3006					sortable.cancelHelperRemoval = true;
3007
3008					// Calling sortable's mouseStop would trigger a revert,
3009					// so revert must be temporarily false until after mouseStop is called.
3010					sortable.options._revert = sortable.options.revert;
3011					sortable.options.revert = false;
3012
3013					sortable._trigger( "out", event, sortable._uiHash( sortable ) );
3014					sortable._mouseStop( event, true );
3015
3016					// Restore sortable behaviors that were modfied
3017					// when the draggable entered the sortable area (#9481)
3018					sortable.options.revert = sortable.options._revert;
3019					sortable.options.helper = sortable.options._helper;
3020
3021					if ( sortable.placeholder ) {
3022						sortable.placeholder.remove();
3023					}
3024
3025					// Restore and recalculate the draggable's offset considering the sortable
3026					// may have modified them in unexpected ways. (#8809, #10669)
3027					ui.helper.appendTo( draggable._parent );
3028					draggable._refreshOffsets( event );
3029					ui.position = draggable._generatePosition( event, true );
3030
3031					draggable._trigger( "fromSortable", event );
3032
3033					// Inform draggable that the helper is no longer in a valid drop zone
3034					draggable.dropped = false;
3035
3036					// Need to refreshPositions of all sortables just in case removing
3037					// from one sortable changes the location of other sortables (#9675)
3038					$.each( draggable.sortables, function() {
3039						this.refreshPositions();
3040					} );
3041				}
3042			}
3043		} );
3044	}
3045} );
3046
3047$.ui.plugin.add( "draggable", "cursor", {
3048	start: function( event, ui, instance ) {
3049		var t = $( "body" ),
3050			o = instance.options;
3051
3052		if ( t.css( "cursor" ) ) {
3053			o._cursor = t.css( "cursor" );
3054		}
3055		t.css( "cursor", o.cursor );
3056	},
3057	stop: function( event, ui, instance ) {
3058		var o = instance.options;
3059		if ( o._cursor ) {
3060			$( "body" ).css( "cursor", o._cursor );
3061		}
3062	}
3063} );
3064
3065$.ui.plugin.add( "draggable", "opacity", {
3066	start: function( event, ui, instance ) {
3067		var t = $( ui.helper ),
3068			o = instance.options;
3069		if ( t.css( "opacity" ) ) {
3070			o._opacity = t.css( "opacity" );
3071		}
3072		t.css( "opacity", o.opacity );
3073	},
3074	stop: function( event, ui, instance ) {
3075		var o = instance.options;
3076		if ( o._opacity ) {
3077			$( ui.helper ).css( "opacity", o._opacity );
3078		}
3079	}
3080} );
3081
3082$.ui.plugin.add( "draggable", "scroll", {
3083	start: function( event, ui, i ) {
3084		if ( !i.scrollParentNotHidden ) {
3085			i.scrollParentNotHidden = i.helper.scrollParent( false );
3086		}
3087
3088		if ( i.scrollParentNotHidden[ 0 ] !== i.document[ 0 ] &&
3089				i.scrollParentNotHidden[ 0 ].tagName !== "HTML" ) {
3090			i.overflowOffset = i.scrollParentNotHidden.offset();
3091		}
3092	},
3093	drag: function( event, ui, i  ) {
3094
3095		var o = i.options,
3096			scrolled = false,
3097			scrollParent = i.scrollParentNotHidden[ 0 ],
3098			document = i.document[ 0 ];
3099
3100		if ( scrollParent !== document && scrollParent.tagName !== "HTML" ) {
3101			if ( !o.axis || o.axis !== "x" ) {
3102				if ( ( i.overflowOffset.top + scrollParent.offsetHeight ) - event.pageY <
3103						o.scrollSensitivity ) {
3104					scrollParent.scrollTop = scrolled = scrollParent.scrollTop + o.scrollSpeed;
3105				} else if ( event.pageY - i.overflowOffset.top < o.scrollSensitivity ) {
3106					scrollParent.scrollTop = scrolled = scrollParent.scrollTop - o.scrollSpeed;
3107				}
3108			}
3109
3110			if ( !o.axis || o.axis !== "y" ) {
3111				if ( ( i.overflowOffset.left + scrollParent.offsetWidth ) - event.pageX <
3112						o.scrollSensitivity ) {
3113					scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft + o.scrollSpeed;
3114				} else if ( event.pageX - i.overflowOffset.left < o.scrollSensitivity ) {
3115					scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft - o.scrollSpeed;
3116				}
3117			}
3118
3119		} else {
3120
3121			if ( !o.axis || o.axis !== "x" ) {
3122				if ( event.pageY - $( document ).scrollTop() < o.scrollSensitivity ) {
3123					scrolled = $( document ).scrollTop( $( document ).scrollTop() - o.scrollSpeed );
3124				} else if ( $( window ).height() - ( event.pageY - $( document ).scrollTop() ) <
3125						o.scrollSensitivity ) {
3126					scrolled = $( document ).scrollTop( $( document ).scrollTop() + o.scrollSpeed );
3127				}
3128			}
3129
3130			if ( !o.axis || o.axis !== "y" ) {
3131				if ( event.pageX - $( document ).scrollLeft() < o.scrollSensitivity ) {
3132					scrolled = $( document ).scrollLeft(
3133						$( document ).scrollLeft() - o.scrollSpeed
3134					);
3135				} else if ( $( window ).width() - ( event.pageX - $( document ).scrollLeft() ) <
3136						o.scrollSensitivity ) {
3137					scrolled = $( document ).scrollLeft(
3138						$( document ).scrollLeft() + o.scrollSpeed
3139					);
3140				}
3141			}
3142
3143		}
3144
3145		if ( scrolled !== false && $.ui.ddmanager && !o.dropBehaviour ) {
3146			$.ui.ddmanager.prepareOffsets( i, event );
3147		}
3148
3149	}
3150} );
3151
3152$.ui.plugin.add( "draggable", "snap", {
3153	start: function( event, ui, i ) {
3154
3155		var o = i.options;
3156
3157		i.snapElements = [];
3158
3159		$( o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap )
3160			.each( function() {
3161				var $t = $( this ),
3162					$o = $t.offset();
3163				if ( this !== i.element[ 0 ] ) {
3164					i.snapElements.push( {
3165						item: this,
3166						width: $t.outerWidth(), height: $t.outerHeight(),
3167						top: $o.top, left: $o.left
3168					} );
3169				}
3170			} );
3171
3172	},
3173	drag: function( event, ui, inst ) {
3174
3175		var ts, bs, ls, rs, l, r, t, b, i, first,
3176			o = inst.options,
3177			d = o.snapTolerance,
3178			x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
3179			y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
3180
3181		for ( i = inst.snapElements.length - 1; i >= 0; i-- ) {
3182
3183			l = inst.snapElements[ i ].left - inst.margins.left;
3184			r = l + inst.snapElements[ i ].width;
3185			t = inst.snapElements[ i ].top - inst.margins.top;
3186			b = t + inst.snapElements[ i ].height;
3187
3188			if ( x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d ||
3189					!$.contains( inst.snapElements[ i ].item.ownerDocument,
3190					inst.snapElements[ i ].item ) ) {
3191				if ( inst.snapElements[ i ].snapping ) {
3192					( inst.options.snap.release &&
3193						inst.options.snap.release.call(
3194							inst.element,
3195							event,
3196							$.extend( inst._uiHash(), { snapItem: inst.snapElements[ i ].item } )
3197						) );
3198				}
3199				inst.snapElements[ i ].snapping = false;
3200				continue;
3201			}
3202
3203			if ( o.snapMode !== "inner" ) {
3204				ts = Math.abs( t - y2 ) <= d;
3205				bs = Math.abs( b - y1 ) <= d;
3206				ls = Math.abs( l - x2 ) <= d;
3207				rs = Math.abs( r - x1 ) <= d;
3208				if ( ts ) {
3209					ui.position.top = inst._convertPositionTo( "relative", {
3210						top: t - inst.helperProportions.height,
3211						left: 0
3212					} ).top;
3213				}
3214				if ( bs ) {
3215					ui.position.top = inst._convertPositionTo( "relative", {
3216						top: b,
3217						left: 0
3218					} ).top;
3219				}
3220				if ( ls ) {
3221					ui.position.left = inst._convertPositionTo( "relative", {
3222						top: 0,
3223						left: l - inst.helperProportions.width
3224					} ).left;
3225				}
3226				if ( rs ) {
3227					ui.position.left = inst._convertPositionTo( "relative", {
3228						top: 0,
3229						left: r
3230					} ).left;
3231				}
3232			}
3233
3234			first = ( ts || bs || ls || rs );
3235
3236			if ( o.snapMode !== "outer" ) {
3237				ts = Math.abs( t - y1 ) <= d;
3238				bs = Math.abs( b - y2 ) <= d;
3239				ls = Math.abs( l - x1 ) <= d;
3240				rs = Math.abs( r - x2 ) <= d;
3241				if ( ts ) {
3242					ui.position.top = inst._convertPositionTo( "relative", {
3243						top: t,
3244						left: 0
3245					} ).top;
3246				}
3247				if ( bs ) {
3248					ui.position.top = inst._convertPositionTo( "relative", {
3249						top: b - inst.helperProportions.height,
3250						left: 0
3251					} ).top;
3252				}
3253				if ( ls ) {
3254					ui.position.left = inst._convertPositionTo( "relative", {
3255						top: 0,
3256						left: l
3257					} ).left;
3258				}
3259				if ( rs ) {
3260					ui.position.left = inst._convertPositionTo( "relative", {
3261						top: 0,
3262						left: r - inst.helperProportions.width
3263					} ).left;
3264				}
3265			}
3266
3267			if ( !inst.snapElements[ i ].snapping && ( ts || bs || ls || rs || first ) ) {
3268				( inst.options.snap.snap &&
3269					inst.options.snap.snap.call(
3270						inst.element,
3271						event,
3272						$.extend( inst._uiHash(), {
3273							snapItem: inst.snapElements[ i ].item
3274						} ) ) );
3275			}
3276			inst.snapElements[ i ].snapping = ( ts || bs || ls || rs || first );
3277
3278		}
3279
3280	}
3281} );
3282
3283$.ui.plugin.add( "draggable", "stack", {
3284	start: function( event, ui, instance ) {
3285		var min,
3286			o = instance.options,
3287			group = $.makeArray( $( o.stack ) ).sort( function( a, b ) {
3288				return ( parseInt( $( a ).css( "zIndex" ), 10 ) || 0 ) -
3289					( parseInt( $( b ).css( "zIndex" ), 10 ) || 0 );
3290			} );
3291
3292		if ( !group.length ) { return; }
3293
3294		min = parseInt( $( group[ 0 ] ).css( "zIndex" ), 10 ) || 0;
3295		$( group ).each( function( i ) {
3296			$( this ).css( "zIndex", min + i );
3297		} );
3298		this.css( "zIndex", ( min + group.length ) );
3299	}
3300} );
3301
3302$.ui.plugin.add( "draggable", "zIndex", {
3303	start: function( event, ui, instance ) {
3304		var t = $( ui.helper ),
3305			o = instance.options;
3306
3307		if ( t.css( "zIndex" ) ) {
3308			o._zIndex = t.css( "zIndex" );
3309		}
3310		t.css( "zIndex", o.zIndex );
3311	},
3312	stop: function( event, ui, instance ) {
3313		var o = instance.options;
3314
3315		if ( o._zIndex ) {
3316			$( ui.helper ).css( "zIndex", o._zIndex );
3317		}
3318	}
3319} );
3320
3321var widgetsDraggable = $.ui.draggable;
3322
3323
3324/*!
3325 * jQuery UI Resizable 1.12.1
3326 * http://jqueryui.com
vendor: 6,932 bytes, lines 3327-3605
3327 *
3328 * Copyright jQuery Foundation and other contributors
3329 * Released under the MIT license.
3330 * http://jquery.org/license
3331 */
3332
3333//>>label: Resizable
3334//>>group: Interactions
3335//>>description: Enables resize functionality for any element.
3336//>>docs: http://api.jqueryui.com/resizable/
3337//>>demos: http://jqueryui.com/resizable/
3338//>>css.structure: ../../themes/base/core.css
3339//>>css.structure: ../../themes/base/resizable.css
3340//>>css.theme: ../../themes/base/theme.css
3341
3342
3343
3344$.widget( "ui.resizable", $.ui.mouse, {
3345	version: "1.12.1",
3346	widgetEventPrefix: "resize",
3347	options: {
3348		alsoResize: false,
3349		animate: false,
3350		animateDuration: "slow",
3351		animateEasing: "swing",
3352		aspectRatio: false,
3353		autoHide: false,
3354		classes: {
3355			"ui-resizable-se": "ui-icon ui-icon-gripsmall-diagonal-se"
3356		},
3357		containment: false,
3358		ghost: false,
3359		grid: false,
3360		handles: "e,s,se",
3361		helper: false,
3362		maxHeight: null,
3363		maxWidth: null,
3364		minHeight: 10,
3365		minWidth: 10,
3366
3367		// See #7960
3368		zIndex: 90,
3369
3370		// Callbacks
3371		resize: null,
3372		start: null,
3373		stop: null
3374	},
3375
3376	_num: function( value ) {
3377		return parseFloat( value ) || 0;
3378	},
3379
3380	_isNumber: function( value ) {
3381		return !isNaN( parseFloat( value ) );
3382	},
3383
3384	_hasScroll: function( el, a ) {
3385
3386		if ( $( el ).css( "overflow" ) === "hidden" ) {
3387			return false;
3388		}
3389
3390		var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
3391			has = false;
3392
3393		if ( el[ scroll ] > 0 ) {
3394			return true;
3395		}
3396
3397		// TODO: determine which cases actually cause this to happen
3398		// if the element doesn't have the scroll set, see if it's possible to
3399		// set the scroll
3400		el[ scroll ] = 1;
3401		has = ( el[ scroll ] > 0 );
3402		el[ scroll ] = 0;
3403		return has;
3404	},
3405
3406	_create: function() {
3407
3408		var margins,
3409			o = this.options,
3410			that = this;
3411		this._addClass( "ui-resizable" );
3412
3413		$.extend( this, {
3414			_aspectRatio: !!( o.aspectRatio ),
3415			aspectRatio: o.aspectRatio,
3416			originalElement: this.element,
3417			_proportionallyResizeElements: [],
3418			_helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null
3419		} );
3420
3421		// Wrap the element if it cannot hold child nodes
3422		if ( this.element[ 0 ].nodeName.match( /^(canvas|textarea|input|select|button|img)$/i ) ) {
3423
3424			this.element.wrap(
3425				$( "<div class='ui-wrapper' style='overflow: hidden;'></div>" ).css( {
3426					position: this.element.css( "position" ),
3427					width: this.element.outerWidth(),
3428					height: this.element.outerHeight(),
3429					top: this.element.css( "top" ),
3430					left: this.element.css( "left" )
3431				} )
3432			);
3433
3434			this.element = this.element.parent().data(
3435				"ui-resizable", this.element.resizable( "instance" )
3436			);
3437
3438			this.elementIsWrapper = true;
3439
3440			margins = {
3441				marginTop: this.originalElement.css( "marginTop" ),
3442				marginRight: this.originalElement.css( "marginRight" ),
3443				marginBottom: this.originalElement.css( "marginBottom" ),
3444				marginLeft: this.originalElement.css( "marginLeft" )
3445			};
3446
3447			this.element.css( margins );
3448			this.originalElement.css( "margin", 0 );
3449
3450			// support: Safari
3451			// Prevent Safari textarea resize
3452			this.originalResizeStyle = this.originalElement.css( "resize" );
3453			this.originalElement.css( "resize", "none" );
3454
3455			this._proportionallyResizeElements.push( this.originalElement.css( {
3456				position: "static",
3457				zoom: 1,
3458				display: "block"
3459			} ) );
3460
3461			// Support: IE9
3462			// avoid IE jump (hard set the margin)
3463			this.originalElement.css( margins );
3464
3465			this._proportionallyResize();
3466		}
3467
3468		this._setupHandles();
3469
3470		if ( o.autoHide ) {
3471			$( this.element )
3472				.on( "mouseenter", function() {
3473					if ( o.disabled ) {
3474						return;
3475					}
3476					that._removeClass( "ui-resizable-autohide" );
3477					that._handles.show();
3478				} )
3479				.on( "mouseleave", function() {
3480					if ( o.disabled ) {
3481						return;
3482					}
3483					if ( !that.resizing ) {
3484						that._addClass( "ui-resizable-autohide" );
3485						that._handles.hide();
3486					}
3487				} );
3488		}
3489
3490		this._mouseInit();
3491	},
3492
3493	_destroy: function() {
3494
3495		this._mouseDestroy();
3496
3497		var wrapper,
3498			_destroy = function( exp ) {
3499				$( exp )
3500					.removeData( "resizable" )
3501					.removeData( "ui-resizable" )
3502					.off( ".resizable" )
3503					.find( ".ui-resizable-handle" )
3504						.remove();
3505			};
3506
3507		// TODO: Unwrap at same DOM position
3508		if ( this.elementIsWrapper ) {
3509			_destroy( this.element );
3510			wrapper = this.element;
3511			this.originalElement.css( {
3512				position: wrapper.css( "position" ),
3513				width: wrapper.outerWidth(),
3514				height: wrapper.outerHeight(),
3515				top: wrapper.css( "top" ),
3516				left: wrapper.css( "left" )
3517			} ).insertAfter( wrapper );
3518			wrapper.remove();
3519		}
3520
3521		this.originalElement.css( "resize", this.originalResizeStyle );
3522		_destroy( this.originalElement );
3523
3524		return this;
3525	},
3526
3527	_setOption: function( key, value ) {
3528		this._super( key, value );
3529
3530		switch ( key ) {
3531		case "handles":
3532			this._removeHandles();
3533			this._setupHandles();
3534			break;
3535		default:
3536			break;
3537		}
3538	},
3539
3540	_setupHandles: function() {
3541		var o = this.options, handle, i, n, hname, axis, that = this;
3542		this.handles = o.handles ||
3543			( !$( ".ui-resizable-handle", this.element ).length ?
3544				"e,s,se" : {
3545					n: ".ui-resizable-n",
3546					e: ".ui-resizable-e",
3547					s: ".ui-resizable-s",
3548					w: ".ui-resizable-w",
3549					se: ".ui-resizable-se",
3550					sw: ".ui-resizable-sw",
3551					ne: ".ui-resizable-ne",
3552					nw: ".ui-resizable-nw"
3553				} );
3554
3555		this._handles = $();
3556		if ( this.handles.constructor === String ) {
3557
3558			if ( this.handles === "all" ) {
3559				this.handles = "n,e,s,w,se,sw,ne,nw";
3560			}
3561
3562			n = this.handles.split( "," );
3563			this.handles = {};
3564
3565			for ( i = 0; i < n.length; i++ ) {
3566
3567				handle = $.trim( n[ i ] );
3568				hname = "ui-resizable-" + handle;
3569				axis = $( "<div>" );
3570				this._addClass( axis, "ui-resizable-handle " + hname );
3571
3572				axis.css( { zIndex: o.zIndex } );
3573
3574				this.handles[ handle ] = ".ui-resizable-" + handle;
3575				this.element.append( axis );
3576			}
3577
3578		}
3579
3580		this._renderAxis = function( target ) {
3581
3582			var i, axis, padPos, padWrapper;
3583
3584			target = target || this.element;
3585
3586			for ( i in this.handles ) {
3587
3588				if ( this.handles[ i ].constructor === String ) {
3589					this.handles[ i ] = this.element.children( this.handles[ i ] ).first().show();
3590				} else if ( this.handles[ i ].jquery || this.handles[ i ].nodeType ) {
3591					this.handles[ i ] = $( this.handles[ i ] );
3592					this._on( this.handles[ i ], { "mousedown": that._mouseDown } );
3593				}
3594
3595				if ( this.elementIsWrapper &&
3596						this.originalElement[ 0 ]
3597							.nodeName
3598							.match( /^(textarea|input|select|button)$/i ) ) {
3599					axis = $( this.handles[ i ], this.element );
3600
3601					padWrapper = /sw|ne|nw|se|n|s/.test( i ) ?
3602						axis.outerHeight() :
3603						axis.outerWidth();
3604
3605					padPos = [ "padding",
vendor: 4,678 bytes, lines 3606-3786
3606						/ne|nw|n/.test( i ) ? "Top" :
3607						/se|sw|s/.test( i ) ? "Bottom" :
3608						/^e$/.test( i ) ? "Right" : "Left" ].join( "" );
3609
3610					target.css( padPos, padWrapper );
3611
3612					this._proportionallyResize();
3613				}
3614
3615				this._handles = this._handles.add( this.handles[ i ] );
3616			}
3617		};
3618
3619		// TODO: make renderAxis a prototype function
3620		this._renderAxis( this.element );
3621
3622		this._handles = this._handles.add( this.element.find( ".ui-resizable-handle" ) );
3623		this._handles.disableSelection();
3624
3625		this._handles.on( "mouseover", function() {
3626			if ( !that.resizing ) {
3627				if ( this.className ) {
3628					axis = this.className.match( /ui-resizable-(se|sw|ne|nw|n|e|s|w)/i );
3629				}
3630				that.axis = axis && axis[ 1 ] ? axis[ 1 ] : "se";
3631			}
3632		} );
3633
3634		if ( o.autoHide ) {
3635			this._handles.hide();
3636			this._addClass( "ui-resizable-autohide" );
3637		}
3638	},
3639
3640	_removeHandles: function() {
3641		this._handles.remove();
3642	},
3643
3644	_mouseCapture: function( event ) {
3645		var i, handle,
3646			capture = false;
3647
3648		for ( i in this.handles ) {
3649			handle = $( this.handles[ i ] )[ 0 ];
3650			if ( handle === event.target || $.contains( handle, event.target ) ) {
3651				capture = true;
3652			}
3653		}
3654
3655		return !this.options.disabled && capture;
3656	},
3657
3658	_mouseStart: function( event ) {
3659
3660		var curleft, curtop, cursor,
3661			o = this.options,
3662			el = this.element;
3663
3664		this.resizing = true;
3665
3666		this._renderProxy();
3667
3668		curleft = this._num( this.helper.css( "left" ) );
3669		curtop = this._num( this.helper.css( "top" ) );
3670
3671		if ( o.containment ) {
3672			curleft += $( o.containment ).scrollLeft() || 0;
3673			curtop += $( o.containment ).scrollTop() || 0;
3674		}
3675
3676		this.offset = this.helper.offset();
3677		this.position = { left: curleft, top: curtop };
3678
3679		this.size = this._helper ? {
3680				width: this.helper.width(),
3681				height: this.helper.height()
3682			} : {
3683				width: el.width(),
3684				height: el.height()
3685			};
3686
3687		this.originalSize = this._helper ? {
3688				width: el.outerWidth(),
3689				height: el.outerHeight()
3690			} : {
3691				width: el.width(),
3692				height: el.height()
3693			};
3694
3695		this.sizeDiff = {
3696			width: el.outerWidth() - el.width(),
3697			height: el.outerHeight() - el.height()
3698		};
3699
3700		this.originalPosition = { left: curleft, top: curtop };
3701		this.originalMousePosition = { left: event.pageX, top: event.pageY };
3702
3703		this.aspectRatio = ( typeof o.aspectRatio === "number" ) ?
3704			o.aspectRatio :
3705			( ( this.originalSize.width / this.originalSize.height ) || 1 );
3706
3707		cursor = $( ".ui-resizable-" + this.axis ).css( "cursor" );
3708		$( "body" ).css( "cursor", cursor === "auto" ? this.axis + "-resize" : cursor );
3709
3710		this._addClass( "ui-resizable-resizing" );
3711		this._propagate( "start", event );
3712		return true;
3713	},
3714
3715	_mouseDrag: function( event ) {
3716
3717		var data, props,
3718			smp = this.originalMousePosition,
3719			a = this.axis,
3720			dx = ( event.pageX - smp.left ) || 0,
3721			dy = ( event.pageY - smp.top ) || 0,
3722			trigger = this._change[ a ];
3723
3724		this._updatePrevProperties();
3725
3726		if ( !trigger ) {
3727			return false;
3728		}
3729
3730		data = trigger.apply( this, [ event, dx, dy ] );
3731
3732		this._updateVirtualBoundaries( event.shiftKey );
3733		if ( this._aspectRatio || event.shiftKey ) {
3734			data = this._updateRatio( data, event );
3735		}
3736
3737		data = this._respectSize( data, event );
3738
3739		this._updateCache( data );
3740
3741		this._propagate( "resize", event );
3742
3743		props = this._applyChanges();
3744
3745		if ( !this._helper && this._proportionallyResizeElements.length ) {
3746			this._proportionallyResize();
3747		}
3748
3749		if ( !$.isEmptyObject( props ) ) {
3750			this._updatePrevProperties();
3751			this._trigger( "resize", event, this.ui() );
3752			this._applyChanges();
3753		}
3754
3755		return false;
3756	},
3757
3758	_mouseStop: function( event ) {
3759
3760		this.resizing = false;
3761		var pr, ista, soffseth, soffsetw, s, left, top,
3762			o = this.options, that = this;
3763
3764		if ( this._helper ) {
3765
3766			pr = this._proportionallyResizeElements;
3767			ista = pr.length && ( /textarea/i ).test( pr[ 0 ].nodeName );
3768			soffseth = ista && this._hasScroll( pr[ 0 ], "left" ) ? 0 : that.sizeDiff.height;
3769			soffsetw = ista ? 0 : that.sizeDiff.width;
3770
3771			s = {
3772				width: ( that.helper.width()  - soffsetw ),
3773				height: ( that.helper.height() - soffseth )
3774			};
3775			left = ( parseFloat( that.element.css( "left" ) ) +
3776				( that.position.left - that.originalPosition.left ) ) || null;
3777			top = ( parseFloat( that.element.css( "top" ) ) +
3778				( that.position.top - that.originalPosition.top ) ) || null;
3779
3780			if ( !o.animate ) {
3781				this.element.css( $.extend( s, { top: top, left: left } ) );
3782			}
3783
3784			that.helper.height( that.size.height );
3785			that.helper.width( that.size.width );
3786
vendor: 6,168 bytes, lines 3787-4027
3787			if ( this._helper && !o.animate ) {
3788				this._proportionallyResize();
3789			}
3790		}
3791
3792		$( "body" ).css( "cursor", "auto" );
3793
3794		this._removeClass( "ui-resizable-resizing" );
3795
3796		this._propagate( "stop", event );
3797
3798		if ( this._helper ) {
3799			this.helper.remove();
3800		}
3801
3802		return false;
3803
3804	},
3805
3806	_updatePrevProperties: function() {
3807		this.prevPosition = {
3808			top: this.position.top,
3809			left: this.position.left
3810		};
3811		this.prevSize = {
3812			width: this.size.width,
3813			height: this.size.height
3814		};
3815	},
3816
3817	_applyChanges: function() {
3818		var props = {};
3819
3820		if ( this.position.top !== this.prevPosition.top ) {
3821			props.top = this.position.top + "px";
3822		}
3823		if ( this.position.left !== this.prevPosition.left ) {
3824			props.left = this.position.left + "px";
3825		}
3826		if ( this.size.width !== this.prevSize.width ) {
3827			props.width = this.size.width + "px";
3828		}
3829		if ( this.size.height !== this.prevSize.height ) {
3830			props.height = this.size.height + "px";
3831		}
3832
3833		this.helper.css( props );
3834
3835		return props;
3836	},
3837
3838	_updateVirtualBoundaries: function( forceAspectRatio ) {
3839		var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b,
3840			o = this.options;
3841
3842		b = {
3843			minWidth: this._isNumber( o.minWidth ) ? o.minWidth : 0,
3844			maxWidth: this._isNumber( o.maxWidth ) ? o.maxWidth : Infinity,
3845			minHeight: this._isNumber( o.minHeight ) ? o.minHeight : 0,
3846			maxHeight: this._isNumber( o.maxHeight ) ? o.maxHeight : Infinity
3847		};
3848
3849		if ( this._aspectRatio || forceAspectRatio ) {
3850			pMinWidth = b.minHeight * this.aspectRatio;
3851			pMinHeight = b.minWidth / this.aspectRatio;
3852			pMaxWidth = b.maxHeight * this.aspectRatio;
3853			pMaxHeight = b.maxWidth / this.aspectRatio;
3854
3855			if ( pMinWidth > b.minWidth ) {
3856				b.minWidth = pMinWidth;
3857			}
3858			if ( pMinHeight > b.minHeight ) {
3859				b.minHeight = pMinHeight;
3860			}
3861			if ( pMaxWidth < b.maxWidth ) {
3862				b.maxWidth = pMaxWidth;
3863			}
3864			if ( pMaxHeight < b.maxHeight ) {
3865				b.maxHeight = pMaxHeight;
3866			}
3867		}
3868		this._vBoundaries = b;
3869	},
3870
3871	_updateCache: function( data ) {
3872		this.offset = this.helper.offset();
3873		if ( this._isNumber( data.left ) ) {
3874			this.position.left = data.left;
3875		}
3876		if ( this._isNumber( data.top ) ) {
3877			this.position.top = data.top;
3878		}
3879		if ( this._isNumber( data.height ) ) {
3880			this.size.height = data.height;
3881		}
3882		if ( this._isNumber( data.width ) ) {
3883			this.size.width = data.width;
3884		}
3885	},
3886
3887	_updateRatio: function( data ) {
3888
3889		var cpos = this.position,
3890			csize = this.size,
3891			a = this.axis;
3892
3893		if ( this._isNumber( data.height ) ) {
3894			data.width = ( data.height * this.aspectRatio );
3895		} else if ( this._isNumber( data.width ) ) {
3896			data.height = ( data.width / this.aspectRatio );
3897		}
3898
3899		if ( a === "sw" ) {
3900			data.left = cpos.left + ( csize.width - data.width );
3901			data.top = null;
3902		}
3903		if ( a === "nw" ) {
3904			data.top = cpos.top + ( csize.height - data.height );
3905			data.left = cpos.left + ( csize.width - data.width );
3906		}
3907
3908		return data;
3909	},
3910
3911	_respectSize: function( data ) {
3912
3913		var o = this._vBoundaries,
3914			a = this.axis,
3915			ismaxw = this._isNumber( data.width ) && o.maxWidth && ( o.maxWidth < data.width ),
3916			ismaxh = this._isNumber( data.height ) && o.maxHeight && ( o.maxHeight < data.height ),
3917			isminw = this._isNumber( data.width ) && o.minWidth && ( o.minWidth > data.width ),
3918			isminh = this._isNumber( data.height ) && o.minHeight && ( o.minHeight > data.height ),
3919			dw = this.originalPosition.left + this.originalSize.width,
3920			dh = this.originalPosition.top + this.originalSize.height,
3921			cw = /sw|nw|w/.test( a ), ch = /nw|ne|n/.test( a );
3922		if ( isminw ) {
3923			data.width = o.minWidth;
3924		}
3925		if ( isminh ) {
3926			data.height = o.minHeight;
3927		}
3928		if ( ismaxw ) {
3929			data.width = o.maxWidth;
3930		}
3931		if ( ismaxh ) {
3932			data.height = o.maxHeight;
3933		}
3934
3935		if ( isminw && cw ) {
3936			data.left = dw - o.minWidth;
3937		}
3938		if ( ismaxw && cw ) {
3939			data.left = dw - o.maxWidth;
3940		}
3941		if ( isminh && ch ) {
3942			data.top = dh - o.minHeight;
3943		}
3944		if ( ismaxh && ch ) {
3945			data.top = dh - o.maxHeight;
3946		}
3947
3948		// Fixing jump error on top/left - bug #2330
3949		if ( !data.width && !data.height && !data.left && data.top ) {
3950			data.top = null;
3951		} else if ( !data.width && !data.height && !data.top && data.left ) {
3952			data.left = null;
3953		}
3954
3955		return data;
3956	},
3957
3958	_getPaddingPlusBorderDimensions: function( element ) {
3959		var i = 0,
3960			widths = [],
3961			borders = [
3962				element.css( "borderTopWidth" ),
3963				element.css( "borderRightWidth" ),
3964				element.css( "borderBottomWidth" ),
3965				element.css( "borderLeftWidth" )
3966			],
3967			paddings = [
3968				element.css( "paddingTop" ),
3969				element.css( "paddingRight" ),
3970				element.css( "paddingBottom" ),
3971				element.css( "paddingLeft" )
3972			];
3973
3974		for ( ; i < 4; i++ ) {
3975			widths[ i ] = ( parseFloat( borders[ i ] ) || 0 );
3976			widths[ i ] += ( parseFloat( paddings[ i ] ) || 0 );
3977		}
3978
3979		return {
3980			height: widths[ 0 ] + widths[ 2 ],
3981			width: widths[ 1 ] + widths[ 3 ]
3982		};
3983	},
3984
3985	_proportionallyResize: function() {
3986
3987		if ( !this._proportionallyResizeElements.length ) {
3988			return;
3989		}
3990
3991		var prel,
3992			i = 0,
3993			element = this.helper || this.element;
3994
3995		for ( ; i < this._proportionallyResizeElements.length; i++ ) {
3996
3997			prel = this._proportionallyResizeElements[ i ];
3998
3999			// TODO: Seems like a bug to cache this.outerDimensions
4000			// considering that we are in a loop.
4001			if ( !this.outerDimensions ) {
4002				this.outerDimensions = this._getPaddingPlusBorderDimensions( prel );
4003			}
4004
4005			prel.css( {
4006				height: ( element.height() - this.outerDimensions.height ) || 0,
4007				width: ( element.width() - this.outerDimensions.width ) || 0
4008			} );
4009
4010		}
4011
4012	},
4013
4014	_renderProxy: function() {
4015
4016		var el = this.element, o = this.options;
4017		this.elementOffset = el.offset();
4018
4019		if ( this._helper ) {
4020
4021			this.helper = this.helper || $( "<div style='overflow:hidden;'></div>" );
4022
4023			this._addClass( this.helper, this._helper );
4024			this.helper.css( {
4025				width: this.element.outerWidth(),
4026				height: this.element.outerHeight(),
4027				position: "absolute",
vendor: 1,421 bytes, lines 4028-4075
4028				left: this.elementOffset.left + "px",
4029				top: this.elementOffset.top + "px",
4030				zIndex: ++o.zIndex //TODO: Don't modify option
4031			} );
4032
4033			this.helper
4034				.appendTo( "body" )
4035				.disableSelection();
4036
4037		} else {
4038			this.helper = this.element;
4039		}
4040
4041	},
4042
4043	_change: {
4044		e: function( event, dx ) {
4045			return { width: this.originalSize.width + dx };
4046		},
4047		w: function( event, dx ) {
4048			var cs = this.originalSize, sp = this.originalPosition;
4049			return { left: sp.left + dx, width: cs.width - dx };
4050		},
4051		n: function( event, dx, dy ) {
4052			var cs = this.originalSize, sp = this.originalPosition;
4053			return { top: sp.top + dy, height: cs.height - dy };
4054		},
4055		s: function( event, dx, dy ) {
4056			return { height: this.originalSize.height + dy };
4057		},
4058		se: function( event, dx, dy ) {
4059			return $.extend( this._change.s.apply( this, arguments ),
4060				this._change.e.apply( this, [ event, dx, dy ] ) );
4061		},
4062		sw: function( event, dx, dy ) {
4063			return $.extend( this._change.s.apply( this, arguments ),
4064				this._change.w.apply( this, [ event, dx, dy ] ) );
4065		},
4066		ne: function( event, dx, dy ) {
4067			return $.extend( this._change.n.apply( this, arguments ),
4068				this._change.e.apply( this, [ event, dx, dy ] ) );
4069		},
4070		nw: function( event, dx, dy ) {
4071			return $.extend( this._change.n.apply( this, arguments ),
4072				this._change.w.apply( this, [ event, dx, dy ] ) );
4073		}
4074	},
4075
vendor: 9,740 bytes, lines 4076-4441
4076	_propagate: function( n, event ) {
4077		$.ui.plugin.call( this, n, [ event, this.ui() ] );
4078		( n !== "resize" && this._trigger( n, event, this.ui() ) );
4079	},
4080
4081	plugins: {},
4082
4083	ui: function() {
4084		return {
4085			originalElement: this.originalElement,
4086			element: this.element,
4087			helper: this.helper,
4088			position: this.position,
4089			size: this.size,
4090			originalSize: this.originalSize,
4091			originalPosition: this.originalPosition
4092		};
4093	}
4094
4095} );
4096
4097/*
4098 * Resizable Extensions
4099 */
4100
4101$.ui.plugin.add( "resizable", "animate", {
4102
4103	stop: function( event ) {
4104		var that = $( this ).resizable( "instance" ),
4105			o = that.options,
4106			pr = that._proportionallyResizeElements,
4107			ista = pr.length && ( /textarea/i ).test( pr[ 0 ].nodeName ),
4108			soffseth = ista && that._hasScroll( pr[ 0 ], "left" ) ? 0 : that.sizeDiff.height,
4109			soffsetw = ista ? 0 : that.sizeDiff.width,
4110			style = {
4111				width: ( that.size.width - soffsetw ),
4112				height: ( that.size.height - soffseth )
4113			},
4114			left = ( parseFloat( that.element.css( "left" ) ) +
4115				( that.position.left - that.originalPosition.left ) ) || null,
4116			top = ( parseFloat( that.element.css( "top" ) ) +
4117				( that.position.top - that.originalPosition.top ) ) || null;
4118
4119		that.element.animate(
4120			$.extend( style, top && left ? { top: top, left: left } : {} ), {
4121				duration: o.animateDuration,
4122				easing: o.animateEasing,
4123				step: function() {
4124
4125					var data = {
4126						width: parseFloat( that.element.css( "width" ) ),
4127						height: parseFloat( that.element.css( "height" ) ),
4128						top: parseFloat( that.element.css( "top" ) ),
4129						left: parseFloat( that.element.css( "left" ) )
4130					};
4131
4132					if ( pr && pr.length ) {
4133						$( pr[ 0 ] ).css( { width: data.width, height: data.height } );
4134					}
4135
4136					// Propagating resize, and updating values for each animation step
4137					that._updateCache( data );
4138					that._propagate( "resize", event );
4139
4140				}
4141			}
4142		);
4143	}
4144
4145} );
4146
4147$.ui.plugin.add( "resizable", "containment", {
4148
4149	start: function() {
4150		var element, p, co, ch, cw, width, height,
4151			that = $( this ).resizable( "instance" ),
4152			o = that.options,
4153			el = that.element,
4154			oc = o.containment,
4155			ce = ( oc instanceof $ ) ?
4156				oc.get( 0 ) :
4157				( /parent/.test( oc ) ) ? el.parent().get( 0 ) : oc;
4158
4159		if ( !ce ) {
4160			return;
4161		}
4162
4163		that.containerElement = $( ce );
4164
4165		if ( /document/.test( oc ) || oc === document ) {
4166			that.containerOffset = {
4167				left: 0,
4168				top: 0
4169			};
4170			that.containerPosition = {
4171				left: 0,
4172				top: 0
4173			};
4174
4175			that.parentData = {
4176				element: $( document ),
4177				left: 0,
4178				top: 0,
4179				width: $( document ).width(),
4180				height: $( document ).height() || document.body.parentNode.scrollHeight
4181			};
4182		} else {
4183			element = $( ce );
4184			p = [];
4185			$( [ "Top", "Right", "Left", "Bottom" ] ).each( function( i, name ) {
4186				p[ i ] = that._num( element.css( "padding" + name ) );
4187			} );
4188
4189			that.containerOffset = element.offset();
4190			that.containerPosition = element.position();
4191			that.containerSize = {
4192				height: ( element.innerHeight() - p[ 3 ] ),
4193				width: ( element.innerWidth() - p[ 1 ] )
4194			};
4195
4196			co = that.containerOffset;
4197			ch = that.containerSize.height;
4198			cw = that.containerSize.width;
4199			width = ( that._hasScroll ( ce, "left" ) ? ce.scrollWidth : cw );
4200			height = ( that._hasScroll ( ce ) ? ce.scrollHeight : ch ) ;
4201
4202			that.parentData = {
4203				element: ce,
4204				left: co.left,
4205				top: co.top,
4206				width: width,
4207				height: height
4208			};
4209		}
4210	},
4211
4212	resize: function( event ) {
4213		var woset, hoset, isParent, isOffsetRelative,
4214			that = $( this ).resizable( "instance" ),
4215			o = that.options,
4216			co = that.containerOffset,
4217			cp = that.position,
4218			pRatio = that._aspectRatio || event.shiftKey,
4219			cop = {
4220				top: 0,
4221				left: 0
4222			},
4223			ce = that.containerElement,
4224			continueResize = true;
4225
4226		if ( ce[ 0 ] !== document && ( /static/ ).test( ce.css( "position" ) ) ) {
4227			cop = co;
4228		}
4229
4230		if ( cp.left < ( that._helper ? co.left : 0 ) ) {
4231			that.size.width = that.size.width +
4232				( that._helper ?
4233					( that.position.left - co.left ) :
4234					( that.position.left - cop.left ) );
4235
4236			if ( pRatio ) {
4237				that.size.height = that.size.width / that.aspectRatio;
4238				continueResize = false;
4239			}
4240			that.position.left = o.helper ? co.left : 0;
4241		}
4242
4243		if ( cp.top < ( that._helper ? co.top : 0 ) ) {
4244			that.size.height = that.size.height +
4245				( that._helper ?
4246					( that.position.top - co.top ) :
4247					that.position.top );
4248
4249			if ( pRatio ) {
4250				that.size.width = that.size.height * that.aspectRatio;
4251				continueResize = false;
4252			}
4253			that.position.top = that._helper ? co.top : 0;
4254		}
4255
4256		isParent = that.containerElement.get( 0 ) === that.element.parent().get( 0 );
4257		isOffsetRelative = /relative|absolute/.test( that.containerElement.css( "position" ) );
4258
4259		if ( isParent && isOffsetRelative ) {
4260			that.offset.left = that.parentData.left + that.position.left;
4261			that.offset.top = that.parentData.top + that.position.top;
4262		} else {
4263			that.offset.left = that.element.offset().left;
4264			that.offset.top = that.element.offset().top;
4265		}
4266
4267		woset = Math.abs( that.sizeDiff.width +
4268			( that._helper ?
4269				that.offset.left - cop.left :
4270				( that.offset.left - co.left ) ) );
4271
4272		hoset = Math.abs( that.sizeDiff.height +
4273			( that._helper ?
4274				that.offset.top - cop.top :
4275				( that.offset.top - co.top ) ) );
4276
4277		if ( woset + that.size.width >= that.parentData.width ) {
4278			that.size.width = that.parentData.width - woset;
4279			if ( pRatio ) {
4280				that.size.height = that.size.width / that.aspectRatio;
4281				continueResize = false;
4282			}
4283		}
4284
4285		if ( hoset + that.size.height >= that.parentData.height ) {
4286			that.size.height = that.parentData.height - hoset;
4287			if ( pRatio ) {
4288				that.size.width = that.size.height * that.aspectRatio;
4289				continueResize = false;
4290			}
4291		}
4292
4293		if ( !continueResize ) {
4294			that.position.left = that.prevPosition.left;
4295			that.position.top = that.prevPosition.top;
4296			that.size.width = that.prevSize.width;
4297			that.size.height = that.prevSize.height;
4298		}
4299	},
4300
4301	stop: function() {
4302		var that = $( this ).resizable( "instance" ),
4303			o = that.options,
4304			co = that.containerOffset,
4305			cop = that.containerPosition,
4306			ce = that.containerElement,
4307			helper = $( that.helper ),
4308			ho = helper.offset(),
4309			w = helper.outerWidth() - that.sizeDiff.width,
4310			h = helper.outerHeight() - that.sizeDiff.height;
4311
4312		if ( that._helper && !o.animate && ( /relative/ ).test( ce.css( "position" ) ) ) {
4313			$( this ).css( {
4314				left: ho.left - cop.left - co.left,
4315				width: w,
4316				height: h
4317			} );
4318		}
4319
4320		if ( that._helper && !o.animate && ( /static/ ).test( ce.css( "position" ) ) ) {
4321			$( this ).css( {
4322				left: ho.left - cop.left - co.left,
4323				width: w,
4324				height: h
4325			} );
4326		}
4327	}
4328} );
4329
4330$.ui.plugin.add( "resizable", "alsoResize", {
4331
4332	start: function() {
4333		var that = $( this ).resizable( "instance" ),
4334			o = that.options;
4335
4336		$( o.alsoResize ).each( function() {
4337			var el = $( this );
4338			el.data( "ui-resizable-alsoresize", {
4339				width: parseFloat( el.width() ), height: parseFloat( el.height() ),
4340				left: parseFloat( el.css( "left" ) ), top: parseFloat( el.css( "top" ) )
4341			} );
4342		} );
4343	},
4344
4345	resize: function( event, ui ) {
4346		var that = $( this ).resizable( "instance" ),
4347			o = that.options,
4348			os = that.originalSize,
4349			op = that.originalPosition,
4350			delta = {
4351				height: ( that.size.height - os.height ) || 0,
4352				width: ( that.size.width - os.width ) || 0,
4353				top: ( that.position.top - op.top ) || 0,
4354				left: ( that.position.left - op.left ) || 0
4355			};
4356
4357			$( o.alsoResize ).each( function() {
4358				var el = $( this ), start = $( this ).data( "ui-resizable-alsoresize" ), style = {},
4359					css = el.parents( ui.originalElement[ 0 ] ).length ?
4360							[ "width", "height" ] :
4361							[ "width", "height", "top", "left" ];
4362
4363				$.each( css, function( i, prop ) {
4364					var sum = ( start[ prop ] || 0 ) + ( delta[ prop ] || 0 );
4365					if ( sum && sum >= 0 ) {
4366						style[ prop ] = sum || null;
4367					}
4368				} );
4369
4370				el.css( style );
4371			} );
4372	},
4373
4374	stop: function() {
4375		$( this ).removeData( "ui-resizable-alsoresize" );
4376	}
4377} );
4378
4379$.ui.plugin.add( "resizable", "ghost", {
4380
4381	start: function() {
4382
4383		var that = $( this ).resizable( "instance" ), cs = that.size;
4384
4385		that.ghost = that.originalElement.clone();
4386		that.ghost.css( {
4387			opacity: 0.25,
4388			display: "block",
4389			position: "relative",
4390			height: cs.height,
4391			width: cs.width,
4392			margin: 0,
4393			left: 0,
4394			top: 0
4395		} );
4396
4397		that._addClass( that.ghost, "ui-resizable-ghost" );
4398
4399		// DEPRECATED
4400		// TODO: remove after 1.12
4401		if ( $.uiBackCompat !== false && typeof that.options.ghost === "string" ) {
4402
4403			// Ghost option
4404			that.ghost.addClass( this.options.ghost );
4405		}
4406
4407		that.ghost.appendTo( that.helper );
4408
4409	},
4410
4411	resize: function() {
4412		var that = $( this ).resizable( "instance" );
4413		if ( that.ghost ) {
4414			that.ghost.css( {
4415				position: "relative",
4416				height: that.size.height,
4417				width: that.size.width
4418			} );
4419		}
4420	},
4421
4422	stop: function() {
4423		var that = $( this ).resizable( "instance" );
4424		if ( that.ghost && that.helper ) {
4425			that.helper.get( 0 ).removeChild( that.ghost.get( 0 ) );
4426		}
4427	}
4428
4429} );
4430
4431$.ui.plugin.add( "resizable", "grid", {
4432
4433	resize: function() {
4434		var outerDimensions,
4435			that = $( this ).resizable( "instance" ),
4436			o = that.options,
4437			cs = that.size,
4438			os = that.originalSize,
4439			op = that.originalPosition,
4440			a = that.axis,
4441			grid = typeof o.grid === "number" ? [ o.grid, o.grid ] : o.grid,
vendor: 6,045 bytes, lines 4442-4676
4442			gridX = ( grid[ 0 ] || 1 ),
4443			gridY = ( grid[ 1 ] || 1 ),
4444			ox = Math.round( ( cs.width - os.width ) / gridX ) * gridX,
4445			oy = Math.round( ( cs.height - os.height ) / gridY ) * gridY,
4446			newWidth = os.width + ox,
4447			newHeight = os.height + oy,
4448			isMaxWidth = o.maxWidth && ( o.maxWidth < newWidth ),
4449			isMaxHeight = o.maxHeight && ( o.maxHeight < newHeight ),
4450			isMinWidth = o.minWidth && ( o.minWidth > newWidth ),
4451			isMinHeight = o.minHeight && ( o.minHeight > newHeight );
4452
4453		o.grid = grid;
4454
4455		if ( isMinWidth ) {
4456			newWidth += gridX;
4457		}
4458		if ( isMinHeight ) {
4459			newHeight += gridY;
4460		}
4461		if ( isMaxWidth ) {
4462			newWidth -= gridX;
4463		}
4464		if ( isMaxHeight ) {
4465			newHeight -= gridY;
4466		}
4467
4468		if ( /^(se|s|e)$/.test( a ) ) {
4469			that.size.width = newWidth;
4470			that.size.height = newHeight;
4471		} else if ( /^(ne)$/.test( a ) ) {
4472			that.size.width = newWidth;
4473			that.size.height = newHeight;
4474			that.position.top = op.top - oy;
4475		} else if ( /^(sw)$/.test( a ) ) {
4476			that.size.width = newWidth;
4477			that.size.height = newHeight;
4478			that.position.left = op.left - ox;
4479		} else {
4480			if ( newHeight - gridY <= 0 || newWidth - gridX <= 0 ) {
4481				outerDimensions = that._getPaddingPlusBorderDimensions( this );
4482			}
4483
4484			if ( newHeight - gridY > 0 ) {
4485				that.size.height = newHeight;
4486				that.position.top = op.top - oy;
4487			} else {
4488				newHeight = gridY - outerDimensions.height;
4489				that.size.height = newHeight;
4490				that.position.top = op.top + os.height - newHeight;
4491			}
4492			if ( newWidth - gridX > 0 ) {
4493				that.size.width = newWidth;
4494				that.position.left = op.left - ox;
4495			} else {
4496				newWidth = gridX - outerDimensions.width;
4497				that.size.width = newWidth;
4498				that.position.left = op.left + os.width - newWidth;
4499			}
4500		}
4501	}
4502
4503} );
4504
4505var widgetsResizable = $.ui.resizable;
4506
4507
4508/*!
4509 * jQuery UI Accordion 1.12.1
4510 * http://jqueryui.com
4511 *
4512 * Copyright jQuery Foundation and other contributors
4513 * Released under the MIT license.
4514 * http://jquery.org/license
4515 */
4516
4517//>>label: Accordion
4518//>>group: Widgets
4519// jscs:disable maximumLineLength
4520//>>description: Displays collapsible content panels for presenting information in a limited amount of space.
4521// jscs:enable maximumLineLength
4522//>>docs: http://api.jqueryui.com/accordion/
4523//>>demos: http://jqueryui.com/accordion/
4524//>>css.structure: ../../themes/base/core.css
4525//>>css.structure: ../../themes/base/accordion.css
4526//>>css.theme: ../../themes/base/theme.css
4527
4528
4529
4530var widgetsAccordion = $.widget( "ui.accordion", {
4531	version: "1.12.1",
4532	options: {
4533		active: 0,
4534		animate: {},
4535		classes: {
4536			"ui-accordion-header": "ui-corner-top",
4537			"ui-accordion-header-collapsed": "ui-corner-all",
4538			"ui-accordion-content": "ui-corner-bottom"
4539		},
4540		collapsible: false,
4541		event: "click",
4542		header: "> li > :first-child, > :not(li):even",
4543		heightStyle: "auto",
4544		icons: {
4545			activeHeader: "ui-icon-triangle-1-s",
4546			header: "ui-icon-triangle-1-e"
4547		},
4548
4549		// Callbacks
4550		activate: null,
4551		beforeActivate: null
4552	},
4553
4554	hideProps: {
4555		borderTopWidth: "hide",
4556		borderBottomWidth: "hide",
4557		paddingTop: "hide",
4558		paddingBottom: "hide",
4559		height: "hide"
4560	},
4561
4562	showProps: {
4563		borderTopWidth: "show",
4564		borderBottomWidth: "show",
4565		paddingTop: "show",
4566		paddingBottom: "show",
4567		height: "show"
4568	},
4569
4570	_create: function() {
4571		var options = this.options;
4572
4573		this.prevShow = this.prevHide = $();
4574		this._addClass( "ui-accordion", "ui-widget ui-helper-reset" );
4575		this.element.attr( "role", "tablist" );
4576
4577		// Don't allow collapsible: false and active: false / null
4578		if ( !options.collapsible && ( options.active === false || options.active == null ) ) {
4579			options.active = 0;
4580		}
4581
4582		this._processPanels();
4583
4584		// handle negative values
4585		if ( options.active < 0 ) {
4586			options.active += this.headers.length;
4587		}
4588		this._refresh();
4589	},
4590
4591	_getCreateEventData: function() {
4592		return {
4593			header: this.active,
4594			panel: !this.active.length ? $() : this.active.next()
4595		};
4596	},
4597
4598	_createIcons: function() {
4599		var icon, children,
4600			icons = this.options.icons;
4601
4602		if ( icons ) {
4603			icon = $( "<span>" );
4604			this._addClass( icon, "ui-accordion-header-icon", "ui-icon " + icons.header );
4605			icon.prependTo( this.headers );
4606			children = this.active.children( ".ui-accordion-header-icon" );
4607			this._removeClass( children, icons.header )
4608				._addClass( children, null, icons.activeHeader )
4609				._addClass( this.headers, "ui-accordion-icons" );
4610		}
4611	},
4612
4613	_destroyIcons: function() {
4614		this._removeClass( this.headers, "ui-accordion-icons" );
4615		this.headers.children( ".ui-accordion-header-icon" ).remove();
4616	},
4617
4618	_destroy: function() {
4619		var contents;
4620
4621		// Clean up main element
4622		this.element.removeAttr( "role" );
4623
4624		// Clean up headers
4625		this.headers
4626			.removeAttr( "role aria-expanded aria-selected aria-controls tabIndex" )
4627			.removeUniqueId();
4628
4629		this._destroyIcons();
4630
4631		// Clean up content panels
4632		contents = this.headers.next()
4633			.css( "display", "" )
4634			.removeAttr( "role aria-hidden aria-labelledby" )
4635			.removeUniqueId();
4636
4637		if ( this.options.heightStyle !== "content" ) {
4638			contents.css( "height", "" );
4639		}
4640	},
4641
4642	_setOption: function( key, value ) {
4643		if ( key === "active" ) {
4644
4645			// _activate() will handle invalid values and update this.options
4646			this._activate( value );
4647			return;
4648		}
4649
4650		if ( key === "event" ) {
4651			if ( this.options.event ) {
4652				this._off( this.headers, this.options.event );
4653			}
4654			this._setupEvents( value );
4655		}
4656
4657		this._super( key, value );
4658
4659		// Setting collapsible: false while collapsed; open first panel
4660		if ( key === "collapsible" && !value && this.options.active === false ) {
4661			this._activate( 0 );
4662		}
4663
4664		if ( key === "icons" ) {
4665			this._destroyIcons();
4666			if ( value ) {
4667				this._createIcons();
4668			}
4669		}
4670	},
4671
4672	_setOptionDisabled: function( value ) {
4673		this._super( value );
4674
4675		this.element.attr( "aria-disabled", value );
4676
vendor: 20,452 bytes, lines 4677-5409
4677		// Support: IE8 Only
4678		// #5332 / #6059 - opacity doesn't cascade to positioned elements in IE
4679		// so we need to add the disabled class to the headers and panels
4680		this._toggleClass( null, "ui-state-disabled", !!value );
4681		this._toggleClass( this.headers.add( this.headers.next() ), null, "ui-state-disabled",
4682			!!value );
4683	},
4684
4685	_keydown: function( event ) {
4686		if ( event.altKey || event.ctrlKey ) {
4687			return;
4688		}
4689
4690		var keyCode = $.ui.keyCode,
4691			length = this.headers.length,
4692			currentIndex = this.headers.index( event.target ),
4693			toFocus = false;
4694
4695		switch ( event.keyCode ) {
4696		case keyCode.RIGHT:
4697		case keyCode.DOWN:
4698			toFocus = this.headers[ ( currentIndex + 1 ) % length ];
4699			break;
4700		case keyCode.LEFT:
4701		case keyCode.UP:
4702			toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
4703			break;
4704		case keyCode.SPACE:
4705		case keyCode.ENTER:
4706			this._eventHandler( event );
4707			break;
4708		case keyCode.HOME:
4709			toFocus = this.headers[ 0 ];
4710			break;
4711		case keyCode.END:
4712			toFocus = this.headers[ length - 1 ];
4713			break;
4714		}
4715
4716		if ( toFocus ) {
4717			$( event.target ).attr( "tabIndex", -1 );
4718			$( toFocus ).attr( "tabIndex", 0 );
4719			$( toFocus ).trigger( "focus" );
4720			event.preventDefault();
4721		}
4722	},
4723
4724	_panelKeyDown: function( event ) {
4725		if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) {
4726			$( event.currentTarget ).prev().trigger( "focus" );
4727		}
4728	},
4729
4730	refresh: function() {
4731		var options = this.options;
4732		this._processPanels();
4733
4734		// Was collapsed or no panel
4735		if ( ( options.active === false && options.collapsible === true ) ||
4736				!this.headers.length ) {
4737			options.active = false;
4738			this.active = $();
4739
4740		// active false only when collapsible is true
4741		} else if ( options.active === false ) {
4742			this._activate( 0 );
4743
4744		// was active, but active panel is gone
4745		} else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
4746
4747			// all remaining panel are disabled
4748			if ( this.headers.length === this.headers.find( ".ui-state-disabled" ).length ) {
4749				options.active = false;
4750				this.active = $();
4751
4752			// activate previous panel
4753			} else {
4754				this._activate( Math.max( 0, options.active - 1 ) );
4755			}
4756
4757		// was active, active panel still exists
4758		} else {
4759
4760			// make sure active index is correct
4761			options.active = this.headers.index( this.active );
4762		}
4763
4764		this._destroyIcons();
4765
4766		this._refresh();
4767	},
4768
4769	_processPanels: function() {
4770		var prevHeaders = this.headers,
4771			prevPanels = this.panels;
4772
4773		this.headers = this.element.find( this.options.header );
4774		this._addClass( this.headers, "ui-accordion-header ui-accordion-header-collapsed",
4775			"ui-state-default" );
4776
4777		this.panels = this.headers.next().filter( ":not(.ui-accordion-content-active)" ).hide();
4778		this._addClass( this.panels, "ui-accordion-content", "ui-helper-reset ui-widget-content" );
4779
4780		// Avoid memory leaks (#10056)
4781		if ( prevPanels ) {
4782			this._off( prevHeaders.not( this.headers ) );
4783			this._off( prevPanels.not( this.panels ) );
4784		}
4785	},
4786
4787	_refresh: function() {
4788		var maxHeight,
4789			options = this.options,
4790			heightStyle = options.heightStyle,
4791			parent = this.element.parent();
4792
4793		this.active = this._findActive( options.active );
4794		this._addClass( this.active, "ui-accordion-header-active", "ui-state-active" )
4795			._removeClass( this.active, "ui-accordion-header-collapsed" );
4796		this._addClass( this.active.next(), "ui-accordion-content-active" );
4797		this.active.next().show();
4798
4799		this.headers
4800			.attr( "role", "tab" )
4801			.each( function() {
4802				var header = $( this ),
4803					headerId = header.uniqueId().attr( "id" ),
4804					panel = header.next(),
4805					panelId = panel.uniqueId().attr( "id" );
4806				header.attr( "aria-controls", panelId );
4807				panel.attr( "aria-labelledby", headerId );
4808			} )
4809			.next()
4810				.attr( "role", "tabpanel" );
4811
4812		this.headers
4813			.not( this.active )
4814				.attr( {
4815					"aria-selected": "false",
4816					"aria-expanded": "false",
4817					tabIndex: -1
4818				} )
4819				.next()
4820					.attr( {
4821						"aria-hidden": "true"
4822					} )
4823					.hide();
4824
4825		// Make sure at least one header is in the tab order
4826		if ( !this.active.length ) {
4827			this.headers.eq( 0 ).attr( "tabIndex", 0 );
4828		} else {
4829			this.active.attr( {
4830				"aria-selected": "true",
4831				"aria-expanded": "true",
4832				tabIndex: 0
4833			} )
4834				.next()
4835					.attr( {
4836						"aria-hidden": "false"
4837					} );
4838		}
4839
4840		this._createIcons();
4841
4842		this._setupEvents( options.event );
4843
4844		if ( heightStyle === "fill" ) {
4845			maxHeight = parent.height();
4846			this.element.siblings( ":visible" ).each( function() {
4847				var elem = $( this ),
4848					position = elem.css( "position" );
4849
4850				if ( position === "absolute" || position === "fixed" ) {
4851					return;
4852				}
4853				maxHeight -= elem.outerHeight( true );
4854			} );
4855
4856			this.headers.each( function() {
4857				maxHeight -= $( this ).outerHeight( true );
4858			} );
4859
4860			this.headers.next()
4861				.each( function() {
4862					$( this ).height( Math.max( 0, maxHeight -
4863						$( this ).innerHeight() + $( this ).height() ) );
4864				} )
4865				.css( "overflow", "auto" );
4866		} else if ( heightStyle === "auto" ) {
4867			maxHeight = 0;
4868			this.headers.next()
4869				.each( function() {
4870					var isVisible = $( this ).is( ":visible" );
4871					if ( !isVisible ) {
4872						$( this ).show();
4873					}
4874					maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() );
4875					if ( !isVisible ) {
4876						$( this ).hide();
4877					}
4878				} )
4879				.height( maxHeight );
4880		}
4881	},
4882
4883	_activate: function( index ) {
4884		var active = this._findActive( index )[ 0 ];
4885
4886		// Trying to activate the already active panel
4887		if ( active === this.active[ 0 ] ) {
4888			return;
4889		}
4890
4891		// Trying to collapse, simulate a click on the currently active header
4892		active = active || this.active[ 0 ];
4893
4894		this._eventHandler( {
4895			target: active,
4896			currentTarget: active,
4897			preventDefault: $.noop
4898		} );
4899	},
4900
4901	_findActive: function( selector ) {
4902		return typeof selector === "number" ? this.headers.eq( selector ) : $();
4903	},
4904
4905	_setupEvents: function( event ) {
4906		var events = {
4907			keydown: "_keydown"
4908		};
4909		if ( event ) {
4910			$.each( event.split( " " ), function( index, eventName ) {
4911				events[ eventName ] = "_eventHandler";
4912			} );
4913		}
4914
4915		this._off( this.headers.add( this.headers.next() ) );
4916		this._on( this.headers, events );
4917		this._on( this.headers.next(), { keydown: "_panelKeyDown" } );
4918		this._hoverable( this.headers );
4919		this._focusable( this.headers );
4920	},
4921
4922	_eventHandler: function( event ) {
4923		var activeChildren, clickedChildren,
4924			options = this.options,
4925			active = this.active,
4926			clicked = $( event.currentTarget ),
4927			clickedIsActive = clicked[ 0 ] === active[ 0 ],
4928			collapsing = clickedIsActive && options.collapsible,
4929			toShow = collapsing ? $() : clicked.next(),
4930			toHide = active.next(),
4931			eventData = {
4932				oldHeader: active,
4933				oldPanel: toHide,
4934				newHeader: collapsing ? $() : clicked,
4935				newPanel: toShow
4936			};
4937
4938		event.preventDefault();
4939
4940		if (
4941
4942				// click on active header, but not collapsible
4943				( clickedIsActive && !options.collapsible ) ||
4944
4945				// allow canceling activation
4946				( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
4947			return;
4948		}
4949
4950		options.active = collapsing ? false : this.headers.index( clicked );
4951
4952		// When the call to ._toggle() comes after the class changes
4953		// it causes a very odd bug in IE 8 (see #6720)
4954		this.active = clickedIsActive ? $() : clicked;
4955		this._toggle( eventData );
4956
4957		// Switch classes
4958		// corner classes on the previously active header stay after the animation
4959		this._removeClass( active, "ui-accordion-header-active", "ui-state-active" );
4960		if ( options.icons ) {
4961			activeChildren = active.children( ".ui-accordion-header-icon" );
4962			this._removeClass( activeChildren, null, options.icons.activeHeader )
4963				._addClass( activeChildren, null, options.icons.header );
4964		}
4965
4966		if ( !clickedIsActive ) {
4967			this._removeClass( clicked, "ui-accordion-header-collapsed" )
4968				._addClass( clicked, "ui-accordion-header-active", "ui-state-active" );
4969			if ( options.icons ) {
4970				clickedChildren = clicked.children( ".ui-accordion-header-icon" );
4971				this._removeClass( clickedChildren, null, options.icons.header )
4972					._addClass( clickedChildren, null, options.icons.activeHeader );
4973			}
4974
4975			this._addClass( clicked.next(), "ui-accordion-content-active" );
4976		}
4977	},
4978
4979	_toggle: function( data ) {
4980		var toShow = data.newPanel,
4981			toHide = this.prevShow.length ? this.prevShow : data.oldPanel;
4982
4983		// Handle activating a panel during the animation for another activation
4984		this.prevShow.add( this.prevHide ).stop( true, true );
4985		this.prevShow = toShow;
4986		this.prevHide = toHide;
4987
4988		if ( this.options.animate ) {
4989			this._animate( toShow, toHide, data );
4990		} else {
4991			toHide.hide();
4992			toShow.show();
4993			this._toggleComplete( data );
4994		}
4995
4996		toHide.attr( {
4997			"aria-hidden": "true"
4998		} );
4999		toHide.prev().attr( {
5000			"aria-selected": "false",
5001			"aria-expanded": "false"
5002		} );
5003
5004		// if we're switching panels, remove the old header from the tab order
5005		// if we're opening from collapsed state, remove the previous header from the tab order
5006		// if we're collapsing, then keep the collapsing header in the tab order
5007		if ( toShow.length && toHide.length ) {
5008			toHide.prev().attr( {
5009				"tabIndex": -1,
5010				"aria-expanded": "false"
5011			} );
5012		} else if ( toShow.length ) {
5013			this.headers.filter( function() {
5014				return parseInt( $( this ).attr( "tabIndex" ), 10 ) === 0;
5015			} )
5016				.attr( "tabIndex", -1 );
5017		}
5018
5019		toShow
5020			.attr( "aria-hidden", "false" )
5021			.prev()
5022				.attr( {
5023					"aria-selected": "true",
5024					"aria-expanded": "true",
5025					tabIndex: 0
5026				} );
5027	},
5028
5029	_animate: function( toShow, toHide, data ) {
5030		var total, easing, duration,
5031			that = this,
5032			adjust = 0,
5033			boxSizing = toShow.css( "box-sizing" ),
5034			down = toShow.length &&
5035				( !toHide.length || ( toShow.index() < toHide.index() ) ),
5036			animate = this.options.animate || {},
5037			options = down && animate.down || animate,
5038			complete = function() {
5039				that._toggleComplete( data );
5040			};
5041
5042		if ( typeof options === "number" ) {
5043			duration = options;
5044		}
5045		if ( typeof options === "string" ) {
5046			easing = options;
5047		}
5048
5049		// fall back from options to animation in case of partial down settings
5050		easing = easing || options.easing || animate.easing;
5051		duration = duration || options.duration || animate.duration;
5052
5053		if ( !toHide.length ) {
5054			return toShow.animate( this.showProps, duration, easing, complete );
5055		}
5056		if ( !toShow.length ) {
5057			return toHide.animate( this.hideProps, duration, easing, complete );
5058		}
5059
5060		total = toShow.show().outerHeight();
5061		toHide.animate( this.hideProps, {
5062			duration: duration,
5063			easing: easing,
5064			step: function( now, fx ) {
5065				fx.now = Math.round( now );
5066			}
5067		} );
5068		toShow
5069			.hide()
5070			.animate( this.showProps, {
5071				duration: duration,
5072				easing: easing,
5073				complete: complete,
5074				step: function( now, fx ) {
5075					fx.now = Math.round( now );
5076					if ( fx.prop !== "height" ) {
5077						if ( boxSizing === "content-box" ) {
5078							adjust += fx.now;
5079						}
5080					} else if ( that.options.heightStyle !== "content" ) {
5081						fx.now = Math.round( total - toHide.outerHeight() - adjust );
5082						adjust = 0;
5083					}
5084				}
5085			} );
5086	},
5087
5088	_toggleComplete: function( data ) {
5089		var toHide = data.oldPanel,
5090			prev = toHide.prev();
5091
5092		this._removeClass( toHide, "ui-accordion-content-active" );
5093		this._removeClass( prev, "ui-accordion-header-active" )
5094			._addClass( prev, "ui-accordion-header-collapsed" );
5095
5096		// Work around for rendering bug in IE (#5421)
5097		if ( toHide.length ) {
5098			toHide.parent()[ 0 ].className = toHide.parent()[ 0 ].className;
5099		}
5100		this._trigger( "activate", null, data );
5101	}
5102} );
5103
5104
5105/*!
5106 * jQuery UI Menu 1.12.1
5107 * http://jqueryui.com
5108 *
5109 * Copyright jQuery Foundation and other contributors
5110 * Released under the MIT license.
5111 * http://jquery.org/license
5112 */
5113
5114//>>label: Menu
5115//>>group: Widgets
5116//>>description: Creates nestable menus.
5117//>>docs: http://api.jqueryui.com/menu/
5118//>>demos: http://jqueryui.com/menu/
5119//>>css.structure: ../../themes/base/core.css
5120//>>css.structure: ../../themes/base/menu.css
5121//>>css.theme: ../../themes/base/theme.css
5122
5123
5124
5125var widgetsMenu = $.widget( "ui.menu", {
5126	version: "1.12.1",
5127	defaultElement: "<ul>",
5128	delay: 300,
5129	options: {
5130		icons: {
5131			submenu: "ui-icon-caret-1-e"
5132		},
5133		items: "> *",
5134		menus: "ul",
5135		position: {
5136			my: "left top",
5137			at: "right top"
5138		},
5139		role: "menu",
5140
5141		// Callbacks
5142		blur: null,
5143		focus: null,
5144		select: null
5145	},
5146
5147	_create: function() {
5148		this.activeMenu = this.element;
5149
5150		// Flag used to prevent firing of the click handler
5151		// as the event bubbles up through nested menus
5152		this.mouseHandled = false;
5153		this.element
5154			.uniqueId()
5155			.attr( {
5156				role: this.options.role,
5157				tabIndex: 0
5158			} );
5159
5160		this._addClass( "ui-menu", "ui-widget ui-widget-content" );
5161		this._on( {
5162
5163			// Prevent focus from sticking to links inside menu after clicking
5164			// them (focus should always stay on UL during navigation).
5165			"mousedown .ui-menu-item": function( event ) {
5166				event.preventDefault();
5167			},
5168			"click .ui-menu-item": function( event ) {
5169				var target = $( event.target );
5170				var active = $( $.ui.safeActiveElement( this.document[ 0 ] ) );
5171				if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) {
5172					this.select( event );
5173
5174					// Only set the mouseHandled flag if the event will bubble, see #9469.
5175					if ( !event.isPropagationStopped() ) {
5176						this.mouseHandled = true;
5177					}
5178
5179					// Open submenu on click
5180					if ( target.has( ".ui-menu" ).length ) {
5181						this.expand( event );
5182					} else if ( !this.element.is( ":focus" ) &&
5183							active.closest( ".ui-menu" ).length ) {
5184
5185						// Redirect focus to the menu
5186						this.element.trigger( "focus", [ true ] );
5187
5188						// If the active item is on the top level, let it stay active.
5189						// Otherwise, blur the active item since it is no longer visible.
5190						if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) {
5191							clearTimeout( this.timer );
5192						}
5193					}
5194				}
5195			},
5196			"mouseenter .ui-menu-item": function( event ) {
5197
5198				// Ignore mouse events while typeahead is active, see #10458.
5199				// Prevents focusing the wrong item when typeahead causes a scroll while the mouse
5200				// is over an item in the menu
5201				if ( this.previousFilter ) {
5202					return;
5203				}
5204
5205				var actualTarget = $( event.target ).closest( ".ui-menu-item" ),
5206					target = $( event.currentTarget );
5207
5208				// Ignore bubbled events on parent items, see #11641
5209				if ( actualTarget[ 0 ] !== target[ 0 ] ) {
5210					return;
5211				}
5212
5213				// Remove ui-state-active class from siblings of the newly focused menu item
5214				// to avoid a jump caused by adjacent elements both having a class with a border
5215				this._removeClass( target.siblings().children( ".ui-state-active" ),
5216					null, "ui-state-active" );
5217				this.focus( event, target );
5218			},
5219			mouseleave: "collapseAll",
5220			"mouseleave .ui-menu": "collapseAll",
5221			focus: function( event, keepActiveItem ) {
5222
5223				// If there's already an active item, keep it active
5224				// If not, activate the first item
5225				var item = this.active || this.element.find( this.options.items ).eq( 0 );
5226
5227				if ( !keepActiveItem ) {
5228					this.focus( event, item );
5229				}
5230			},
5231			blur: function( event ) {
5232				this._delay( function() {
5233					var notContained = !$.contains(
5234						this.element[ 0 ],
5235						$.ui.safeActiveElement( this.document[ 0 ] )
5236					);
5237					if ( notContained ) {
5238						this.collapseAll( event );
5239					}
5240				} );
5241			},
5242			keydown: "_keydown"
5243		} );
5244
5245		this.refresh();
5246
5247		// Clicks outside of a menu collapse any open menus
5248		this._on( this.document, {
5249			click: function( event ) {
5250				if ( this._closeOnDocumentClick( event ) ) {
5251					this.collapseAll( event );
5252				}
5253
5254				// Reset the mouseHandled flag
5255				this.mouseHandled = false;
5256			}
5257		} );
5258	},
5259
5260	_destroy: function() {
5261		var items = this.element.find( ".ui-menu-item" )
5262				.removeAttr( "role aria-disabled" ),
5263			submenus = items.children( ".ui-menu-item-wrapper" )
5264				.removeUniqueId()
5265				.removeAttr( "tabIndex role aria-haspopup" );
5266
5267		// Destroy (sub)menus
5268		this.element
5269			.removeAttr( "aria-activedescendant" )
5270			.find( ".ui-menu" ).addBack()
5271				.removeAttr( "role aria-labelledby aria-expanded aria-hidden aria-disabled " +
5272					"tabIndex" )
5273				.removeUniqueId()
5274				.show();
5275
5276		submenus.children().each( function() {
5277			var elem = $( this );
5278			if ( elem.data( "ui-menu-submenu-caret" ) ) {
5279				elem.remove();
5280			}
5281		} );
5282	},
5283
5284	_keydown: function( event ) {
5285		var match, prev, character, skip,
5286			preventDefault = true;
5287
5288		switch ( event.keyCode ) {
5289		case $.ui.keyCode.PAGE_UP:
5290			this.previousPage( event );
5291			break;
5292		case $.ui.keyCode.PAGE_DOWN:
5293			this.nextPage( event );
5294			break;
5295		case $.ui.keyCode.HOME:
5296			this._move( "first", "first", event );
5297			break;
5298		case $.ui.keyCode.END:
5299			this._move( "last", "last", event );
5300			break;
5301		case $.ui.keyCode.UP:
5302			this.previous( event );
5303			break;
5304		case $.ui.keyCode.DOWN:
5305			this.next( event );
5306			break;
5307		case $.ui.keyCode.LEFT:
5308			this.collapse( event );
5309			break;
5310		case $.ui.keyCode.RIGHT:
5311			if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
5312				this.expand( event );
5313			}
5314			break;
5315		case $.ui.keyCode.ENTER:
5316		case $.ui.keyCode.SPACE:
5317			this._activate( event );
5318			break;
5319		case $.ui.keyCode.ESCAPE:
5320			this.collapse( event );
5321			break;
5322		default:
5323			preventDefault = false;
5324			prev = this.previousFilter || "";
5325			skip = false;
5326
5327			// Support number pad values
5328			character = event.keyCode >= 96 && event.keyCode <= 105 ?
5329				( event.keyCode - 96 ).toString() : String.fromCharCode( event.keyCode );
5330
5331			clearTimeout( this.filterTimer );
5332
5333			if ( character === prev ) {
5334				skip = true;
5335			} else {
5336				character = prev + character;
5337			}
5338
5339			match = this._filterMenuItems( character );
5340			match = skip && match.index( this.active.next() ) !== -1 ?
5341				this.active.nextAll( ".ui-menu-item" ) :
5342				match;
5343
5344			// If no matches on the current filter, reset to the last character pressed
5345			// to move down the menu to the first item that starts with that character
5346			if ( !match.length ) {
5347				character = String.fromCharCode( event.keyCode );
5348				match = this._filterMenuItems( character );
5349			}
5350
5351			if ( match.length ) {
5352				this.focus( event, match );
5353				this.previousFilter = character;
5354				this.filterTimer = this._delay( function() {
5355					delete this.previousFilter;
5356				}, 1000 );
5357			} else {
5358				delete this.previousFilter;
5359			}
5360		}
5361
5362		if ( preventDefault ) {
5363			event.preventDefault();
5364		}
5365	},
5366
5367	_activate: function( event ) {
5368		if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
5369			if ( this.active.children( "[aria-haspopup='true']" ).length ) {
5370				this.expand( event );
5371			} else {
5372				this.select( event );
5373			}
5374		}
5375	},
5376
5377	refresh: function() {
5378		var menus, items, newSubmenus, newItems, newWrappers,
5379			that = this,
5380			icon = this.options.icons.submenu,
5381			submenus = this.element.find( this.options.menus );
5382
5383		this._toggleClass( "ui-menu-icons", null, !!this.element.find( ".ui-icon" ).length );
5384
5385		// Initialize nested menus
5386		newSubmenus = submenus.filter( ":not(.ui-menu)" )
5387			.hide()
5388			.attr( {
5389				role: this.options.role,
5390				"aria-hidden": "true",
5391				"aria-expanded": "false"
5392			} )
5393			.each( function() {
5394				var menu = $( this ),
5395					item = menu.prev(),
5396					submenuCaret = $( "<span>" ).data( "ui-menu-submenu-caret", true );
5397
5398				that._addClass( submenuCaret, "ui-menu-icon", "ui-icon " + icon );
5399				item
5400					.attr( "aria-haspopup", "true" )
5401					.prepend( submenuCaret );
5402				menu.attr( "aria-labelledby", item.attr( "id" ) );
5403			} );
5404
5405		this._addClass( newSubmenus, "ui-menu", "ui-widget ui-widget-content ui-front" );
5406
5407		menus = submenus.add( this.element );
5408		items = menus.find( this.options.items );
5409
vendor: 4,715 bytes, lines 5410-5572
5410		// Initialize menu-items containing spaces and/or dashes only as dividers
5411		items.not( ".ui-menu-item" ).each( function() {
5412			var item = $( this );
5413			if ( that._isDivider( item ) ) {
5414				that._addClass( item, "ui-menu-divider", "ui-widget-content" );
5415			}
5416		} );
5417
5418		// Don't refresh list items that are already adapted
5419		newItems = items.not( ".ui-menu-item, .ui-menu-divider" );
5420		newWrappers = newItems.children()
5421			.not( ".ui-menu" )
5422				.uniqueId()
5423				.attr( {
5424					tabIndex: -1,
5425					role: this._itemRole()
5426				} );
5427		this._addClass( newItems, "ui-menu-item" )
5428			._addClass( newWrappers, "ui-menu-item-wrapper" );
5429
5430		// Add aria-disabled attribute to any disabled menu item
5431		items.filter( ".ui-state-disabled" ).attr( "aria-disabled", "true" );
5432
5433		// If the active item has been removed, blur the menu
5434		if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
5435			this.blur();
5436		}
5437	},
5438
5439	_itemRole: function() {
5440		return {
5441			menu: "menuitem",
5442			listbox: "option"
5443		}[ this.options.role ];
5444	},
5445
5446	_setOption: function( key, value ) {
5447		if ( key === "icons" ) {
5448			var icons = this.element.find( ".ui-menu-icon" );
5449			this._removeClass( icons, null, this.options.icons.submenu )
5450				._addClass( icons, null, value.submenu );
5451		}
5452		this._super( key, value );
5453	},
5454
5455	_setOptionDisabled: function( value ) {
5456		this._super( value );
5457
5458		this.element.attr( "aria-disabled", String( value ) );
5459		this._toggleClass( null, "ui-state-disabled", !!value );
5460	},
5461
5462	focus: function( event, item ) {
5463		var nested, focused, activeParent;
5464		this.blur( event, event && event.type === "focus" );
5465
5466		this._scrollIntoView( item );
5467
5468		this.active = item.first();
5469
5470		focused = this.active.children( ".ui-menu-item-wrapper" );
5471		this._addClass( focused, null, "ui-state-active" );
5472
5473		// Only update aria-activedescendant if there's a role
5474		// otherwise we assume focus is managed elsewhere
5475		if ( this.options.role ) {
5476			this.element.attr( "aria-activedescendant", focused.attr( "id" ) );
5477		}
5478
5479		// Highlight active parent menu item, if any
5480		activeParent = this.active
5481			.parent()
5482				.closest( ".ui-menu-item" )
5483					.children( ".ui-menu-item-wrapper" );
5484		this._addClass( activeParent, null, "ui-state-active" );
5485
5486		if ( event && event.type === "keydown" ) {
5487			this._close();
5488		} else {
5489			this.timer = this._delay( function() {
5490				this._close();
5491			}, this.delay );
5492		}
5493
5494		nested = item.children( ".ui-menu" );
5495		if ( nested.length && event && ( /^mouse/.test( event.type ) ) ) {
5496			this._startOpening( nested );
5497		}
5498		this.activeMenu = item.parent();
5499
5500		this._trigger( "focus", event, { item: item } );
5501	},
5502
5503	_scrollIntoView: function( item ) {
5504		var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight;
5505		if ( this._hasScroll() ) {
5506			borderTop = parseFloat( $.css( this.activeMenu[ 0 ], "borderTopWidth" ) ) || 0;
5507			paddingTop = parseFloat( $.css( this.activeMenu[ 0 ], "paddingTop" ) ) || 0;
5508			offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop;
5509			scroll = this.activeMenu.scrollTop();
5510			elementHeight = this.activeMenu.height();
5511			itemHeight = item.outerHeight();
5512
5513			if ( offset < 0 ) {
5514				this.activeMenu.scrollTop( scroll + offset );
5515			} else if ( offset + itemHeight > elementHeight ) {
5516				this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight );
5517			}
5518		}
5519	},
5520
5521	blur: function( event, fromFocus ) {
5522		if ( !fromFocus ) {
5523			clearTimeout( this.timer );
5524		}
5525
5526		if ( !this.active ) {
5527			return;
5528		}
5529
5530		this._removeClass( this.active.children( ".ui-menu-item-wrapper" ),
5531			null, "ui-state-active" );
5532
5533		this._trigger( "blur", event, { item: this.active } );
5534		this.active = null;
5535	},
5536
5537	_startOpening: function( submenu ) {
5538		clearTimeout( this.timer );
5539
5540		// Don't open if already open fixes a Firefox bug that caused a .5 pixel
5541		// shift in the submenu position when mousing over the caret icon
5542		if ( submenu.attr( "aria-hidden" ) !== "true" ) {
5543			return;
5544		}
5545
5546		this.timer = this._delay( function() {
5547			this._close();
5548			this._open( submenu );
5549		}, this.delay );
5550	},
5551
5552	_open: function( submenu ) {
5553		var position = $.extend( {
5554			of: this.active
5555		}, this.options.position );
5556
5557		clearTimeout( this.timer );
5558		this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) )
5559			.hide()
5560			.attr( "aria-hidden", "true" );
5561
5562		submenu
5563			.show()
5564			.removeAttr( "aria-hidden" )
5565			.attr( "aria-expanded", "true" )
5566			.position( position );
5567	},
5568
5569	collapseAll: function( event, all ) {
5570		clearTimeout( this.timer );
5571		this.timer = this._delay( function() {
5572
vendor: 36,980 bytes, lines 5573-6892
5573			// If we were passed an event, look for the submenu that contains the event
5574			var currentMenu = all ? this.element :
5575				$( event && event.target ).closest( this.element.find( ".ui-menu" ) );
5576
5577			// If we found no valid submenu ancestor, use the main menu to close all
5578			// sub menus anyway
5579			if ( !currentMenu.length ) {
5580				currentMenu = this.element;
5581			}
5582
5583			this._close( currentMenu );
5584
5585			this.blur( event );
5586
5587			// Work around active item staying active after menu is blurred
5588			this._removeClass( currentMenu.find( ".ui-state-active" ), null, "ui-state-active" );
5589
5590			this.activeMenu = currentMenu;
5591		}, this.delay );
5592	},
5593
5594	// With no arguments, closes the currently active menu - if nothing is active
5595	// it closes all menus.  If passed an argument, it will search for menus BELOW
5596	_close: function( startMenu ) {
5597		if ( !startMenu ) {
5598			startMenu = this.active ? this.active.parent() : this.element;
5599		}
5600
5601		startMenu.find( ".ui-menu" )
5602			.hide()
5603			.attr( "aria-hidden", "true" )
5604			.attr( "aria-expanded", "false" );
5605	},
5606
5607	_closeOnDocumentClick: function( event ) {
5608		return !$( event.target ).closest( ".ui-menu" ).length;
5609	},
5610
5611	_isDivider: function( item ) {
5612
5613		// Match hyphen, em dash, en dash
5614		return !/[^\-\u2014\u2013\s]/.test( item.text() );
5615	},
5616
5617	collapse: function( event ) {
5618		var newItem = this.active &&
5619			this.active.parent().closest( ".ui-menu-item", this.element );
5620		if ( newItem && newItem.length ) {
5621			this._close();
5622			this.focus( event, newItem );
5623		}
5624	},
5625
5626	expand: function( event ) {
5627		var newItem = this.active &&
5628			this.active
5629				.children( ".ui-menu " )
5630					.find( this.options.items )
5631						.first();
5632
5633		if ( newItem && newItem.length ) {
5634			this._open( newItem.parent() );
5635
5636			// Delay so Firefox will not hide activedescendant change in expanding submenu from AT
5637			this._delay( function() {
5638				this.focus( event, newItem );
5639			} );
5640		}
5641	},
5642
5643	next: function( event ) {
5644		this._move( "next", "first", event );
5645	},
5646
5647	previous: function( event ) {
5648		this._move( "prev", "last", event );
5649	},
5650
5651	isFirstItem: function() {
5652		return this.active && !this.active.prevAll( ".ui-menu-item" ).length;
5653	},
5654
5655	isLastItem: function() {
5656		return this.active && !this.active.nextAll( ".ui-menu-item" ).length;
5657	},
5658
5659	_move: function( direction, filter, event ) {
5660		var next;
5661		if ( this.active ) {
5662			if ( direction === "first" || direction === "last" ) {
5663				next = this.active
5664					[ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" )
5665					.eq( -1 );
5666			} else {
5667				next = this.active
5668					[ direction + "All" ]( ".ui-menu-item" )
5669					.eq( 0 );
5670			}
5671		}
5672		if ( !next || !next.length || !this.active ) {
5673			next = this.activeMenu.find( this.options.items )[ filter ]();
5674		}
5675
5676		this.focus( event, next );
5677	},
5678
5679	nextPage: function( event ) {
5680		var item, base, height;
5681
5682		if ( !this.active ) {
5683			this.next( event );
5684			return;
5685		}
5686		if ( this.isLastItem() ) {
5687			return;
5688		}
5689		if ( this._hasScroll() ) {
5690			base = this.active.offset().top;
5691			height = this.element.height();
5692			this.active.nextAll( ".ui-menu-item" ).each( function() {
5693				item = $( this );
5694				return item.offset().top - base - height < 0;
5695			} );
5696
5697			this.focus( event, item );
5698		} else {
5699			this.focus( event, this.activeMenu.find( this.options.items )
5700				[ !this.active ? "first" : "last" ]() );
5701		}
5702	},
5703
5704	previousPage: function( event ) {
5705		var item, base, height;
5706		if ( !this.active ) {
5707			this.next( event );
5708			return;
5709		}
5710		if ( this.isFirstItem() ) {
5711			return;
5712		}
5713		if ( this._hasScroll() ) {
5714			base = this.active.offset().top;
5715			height = this.element.height();
5716			this.active.prevAll( ".ui-menu-item" ).each( function() {
5717				item = $( this );
5718				return item.offset().top - base + height > 0;
5719			} );
5720
5721			this.focus( event, item );
5722		} else {
5723			this.focus( event, this.activeMenu.find( this.options.items ).first() );
5724		}
5725	},
5726
5727	_hasScroll: function() {
5728		return this.element.outerHeight() < this.element.prop( "scrollHeight" );
5729	},
5730
5731	select: function( event ) {
5732
5733		// TODO: It should never be possible to not have an active item at this
5734		// point, but the tests don't trigger mouseenter before click.
5735		this.active = this.active || $( event.target ).closest( ".ui-menu-item" );
5736		var ui = { item: this.active };
5737		if ( !this.active.has( ".ui-menu" ).length ) {
5738			this.collapseAll( event, true );
5739		}
5740		this._trigger( "select", event, ui );
5741	},
5742
5743	_filterMenuItems: function( character ) {
5744		var escapedCharacter = character.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ),
5745			regex = new RegExp( "^" + escapedCharacter, "i" );
5746
5747		return this.activeMenu
5748			.find( this.options.items )
5749
5750				// Only match on items, not dividers or other content (#10571)
5751				.filter( ".ui-menu-item" )
5752					.filter( function() {
5753						return regex.test(
5754							$.trim( $( this ).children( ".ui-menu-item-wrapper" ).text() ) );
5755					} );
5756	}
5757} );
5758
5759
5760/*!
5761 * jQuery UI Autocomplete 1.12.1
5762 * http://jqueryui.com
5763 *
5764 * Copyright jQuery Foundation and other contributors
5765 * Released under the MIT license.
5766 * http://jquery.org/license
5767 */
5768
5769//>>label: Autocomplete
5770//>>group: Widgets
5771//>>description: Lists suggested words as the user is typing.
5772//>>docs: http://api.jqueryui.com/autocomplete/
5773//>>demos: http://jqueryui.com/autocomplete/
5774//>>css.structure: ../../themes/base/core.css
5775//>>css.structure: ../../themes/base/autocomplete.css
5776//>>css.theme: ../../themes/base/theme.css
5777
5778
5779
5780$.widget( "ui.autocomplete", {
5781	version: "1.12.1",
5782	defaultElement: "<input>",
5783	options: {
5784		appendTo: null,
5785		autoFocus: false,
5786		delay: 300,
5787		minLength: 1,
5788		position: {
5789			my: "left top",
5790			at: "left bottom",
5791			collision: "none"
5792		},
5793		source: null,
5794
5795		// Callbacks
5796		change: null,
5797		close: null,
5798		focus: null,
5799		open: null,
5800		response: null,
5801		search: null,
5802		select: null
5803	},
5804
5805	requestIndex: 0,
5806	pending: 0,
5807
5808	_create: function() {
5809
5810		// Some browsers only repeat keydown events, not keypress events,
5811		// so we use the suppressKeyPress flag to determine if we've already
5812		// handled the keydown event. #7269
5813		// Unfortunately the code for & in keypress is the same as the up arrow,
5814		// so we use the suppressKeyPressRepeat flag to avoid handling keypress
5815		// events when we know the keydown event was used to modify the
5816		// search term. #7799
5817		var suppressKeyPress, suppressKeyPressRepeat, suppressInput,
5818			nodeName = this.element[ 0 ].nodeName.toLowerCase(),
5819			isTextarea = nodeName === "textarea",
5820			isInput = nodeName === "input";
5821
5822		// Textareas are always multi-line
5823		// Inputs are always single-line, even if inside a contentEditable element
5824		// IE also treats inputs as contentEditable
5825		// All other element types are determined by whether or not they're contentEditable
5826		this.isMultiLine = isTextarea || !isInput && this._isContentEditable( this.element );
5827
5828		this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ];
5829		this.isNewMenu = true;
5830
5831		this._addClass( "ui-autocomplete-input" );
5832		this.element.attr( "autocomplete", "off" );
5833
5834		this._on( this.element, {
5835			keydown: function( event ) {
5836				if ( this.element.prop( "readOnly" ) ) {
5837					suppressKeyPress = true;
5838					suppressInput = true;
5839					suppressKeyPressRepeat = true;
5840					return;
5841				}
5842
5843				suppressKeyPress = false;
5844				suppressInput = false;
5845				suppressKeyPressRepeat = false;
5846				var keyCode = $.ui.keyCode;
5847				switch ( event.keyCode ) {
5848				case keyCode.PAGE_UP:
5849					suppressKeyPress = true;
5850					this._move( "previousPage", event );
5851					break;
5852				case keyCode.PAGE_DOWN:
5853					suppressKeyPress = true;
5854					this._move( "nextPage", event );
5855					break;
5856				case keyCode.UP:
5857					suppressKeyPress = true;
5858					this._keyEvent( "previous", event );
5859					break;
5860				case keyCode.DOWN:
5861					suppressKeyPress = true;
5862					this._keyEvent( "next", event );
5863					break;
5864				case keyCode.ENTER:
5865
5866					// when menu is open and has focus
5867					if ( this.menu.active ) {
5868
5869						// #6055 - Opera still allows the keypress to occur
5870						// which causes forms to submit
5871						suppressKeyPress = true;
5872						event.preventDefault();
5873						this.menu.select( event );
5874					}
5875					break;
5876				case keyCode.TAB:
5877					if ( this.menu.active ) {
5878						this.menu.select( event );
5879					}
5880					break;
5881				case keyCode.ESCAPE:
5882					if ( this.menu.element.is( ":visible" ) ) {
5883						if ( !this.isMultiLine ) {
5884							this._value( this.term );
5885						}
5886						this.close( event );
5887
5888						// Different browsers have different default behavior for escape
5889						// Single press can mean undo or clear
5890						// Double press in IE means clear the whole form
5891						event.preventDefault();
5892					}
5893					break;
5894				default:
5895					suppressKeyPressRepeat = true;
5896
5897					// search timeout should be triggered before the input value is changed
5898					this._searchTimeout( event );
5899					break;
5900				}
5901			},
5902			keypress: function( event ) {
5903				if ( suppressKeyPress ) {
5904					suppressKeyPress = false;
5905					if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
5906						event.preventDefault();
5907					}
5908					return;
5909				}
5910				if ( suppressKeyPressRepeat ) {
5911					return;
5912				}
5913
5914				// Replicate some key handlers to allow them to repeat in Firefox and Opera
5915				var keyCode = $.ui.keyCode;
5916				switch ( event.keyCode ) {
5917				case keyCode.PAGE_UP:
5918					this._move( "previousPage", event );
5919					break;
5920				case keyCode.PAGE_DOWN:
5921					this._move( "nextPage", event );
5922					break;
5923				case keyCode.UP:
5924					this._keyEvent( "previous", event );
5925					break;
5926				case keyCode.DOWN:
5927					this._keyEvent( "next", event );
5928					break;
5929				}
5930			},
5931			input: function( event ) {
5932				if ( suppressInput ) {
5933					suppressInput = false;
5934					event.preventDefault();
5935					return;
5936				}
5937				this._searchTimeout( event );
5938			},
5939			focus: function() {
5940				this.selectedItem = null;
5941				this.previous = this._value();
5942			},
5943			blur: function( event ) {
5944				if ( this.cancelBlur ) {
5945					delete this.cancelBlur;
5946					return;
5947				}
5948
5949				clearTimeout( this.searching );
5950				this.close( event );
5951				this._change( event );
5952			}
5953		} );
5954
5955		this._initSource();
5956		this.menu = $( "<ul>" )
5957			.appendTo( this._appendTo() )
5958			.menu( {
5959
5960				// disable ARIA support, the live region takes care of that
5961				role: null
5962			} )
5963			.hide()
5964			.menu( "instance" );
5965
5966		this._addClass( this.menu.element, "ui-autocomplete", "ui-front" );
5967		this._on( this.menu.element, {
5968			mousedown: function( event ) {
5969
5970				// prevent moving focus out of the text field
5971				event.preventDefault();
5972
5973				// IE doesn't prevent moving focus even with event.preventDefault()
5974				// so we set a flag to know when we should ignore the blur event
5975				this.cancelBlur = true;
5976				this._delay( function() {
5977					delete this.cancelBlur;
5978
5979					// Support: IE 8 only
5980					// Right clicking a menu item or selecting text from the menu items will
5981					// result in focus moving out of the input. However, we've already received
5982					// and ignored the blur event because of the cancelBlur flag set above. So
5983					// we restore focus to ensure that the menu closes properly based on the user's
5984					// next actions.
5985					if ( this.element[ 0 ] !== $.ui.safeActiveElement( this.document[ 0 ] ) ) {
5986						this.element.trigger( "focus" );
5987					}
5988				} );
5989			},
5990			menufocus: function( event, ui ) {
5991				var label, item;
5992
5993				// support: Firefox
5994				// Prevent accidental activation of menu items in Firefox (#7024 #9118)
5995				if ( this.isNewMenu ) {
5996					this.isNewMenu = false;
5997					if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) {
5998						this.menu.blur();
5999
6000						this.document.one( "mousemove", function() {
6001							$( event.target ).trigger( event.originalEvent );
6002						} );
6003
6004						return;
6005					}
6006				}
6007
6008				item = ui.item.data( "ui-autocomplete-item" );
6009				if ( false !== this._trigger( "focus", event, { item: item } ) ) {
6010
6011					// use value to match what will end up in the input, if it was a key event
6012					if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) {
6013						this._value( item.value );
6014					}
6015				}
6016
6017				// Announce the value in the liveRegion
6018				label = ui.item.attr( "aria-label" ) || item.value;
6019				if ( label && $.trim( label ).length ) {
6020					this.liveRegion.children().hide();
6021					$( "<div>" ).text( label ).appendTo( this.liveRegion );
6022				}
6023			},
6024			menuselect: function( event, ui ) {
6025				var item = ui.item.data( "ui-autocomplete-item" ),
6026					previous = this.previous;
6027
6028				// Only trigger when focus was lost (click on menu)
6029				if ( this.element[ 0 ] !== $.ui.safeActiveElement( this.document[ 0 ] ) ) {
6030					this.element.trigger( "focus" );
6031					this.previous = previous;
6032
6033					// #6109 - IE triggers two focus events and the second
6034					// is asynchronous, so we need to reset the previous
6035					// term synchronously and asynchronously :-(
6036					this._delay( function() {
6037						this.previous = previous;
6038						this.selectedItem = item;
6039					} );
6040				}
6041
6042				if ( false !== this._trigger( "select", event, { item: item } ) ) {
6043					this._value( item.value );
6044				}
6045
6046				// reset the term after the select event
6047				// this allows custom select handling to work properly
6048				this.term = this._value();
6049
6050				this.close( event );
6051				this.selectedItem = item;
6052			}
6053		} );
6054
6055		this.liveRegion = $( "<div>", {
6056			role: "status",
6057			"aria-live": "assertive",
6058			"aria-relevant": "additions"
6059		} )
6060			.appendTo( this.document[ 0 ].body );
6061
6062		this._addClass( this.liveRegion, null, "ui-helper-hidden-accessible" );
6063
6064		// Turning off autocomplete prevents the browser from remembering the
6065		// value when navigating through history, so we re-enable autocomplete
6066		// if the page is unloaded before the widget is destroyed. #7790
6067		this._on( this.window, {
6068			beforeunload: function() {
6069				this.element.removeAttr( "autocomplete" );
6070			}
6071		} );
6072	},
6073
6074	_destroy: function() {
6075		clearTimeout( this.searching );
6076		this.element.removeAttr( "autocomplete" );
6077		this.menu.element.remove();
6078		this.liveRegion.remove();
6079	},
6080
6081	_setOption: function( key, value ) {
6082		this._super( key, value );
6083		if ( key === "source" ) {
6084			this._initSource();
6085		}
6086		if ( key === "appendTo" ) {
6087			this.menu.element.appendTo( this._appendTo() );
6088		}
6089		if ( key === "disabled" && value && this.xhr ) {
6090			this.xhr.abort();
6091		}
6092	},
6093
6094	_isEventTargetInWidget: function( event ) {
6095		var menuElement = this.menu.element[ 0 ];
6096
6097		return event.target === this.element[ 0 ] ||
6098			event.target === menuElement ||
6099			$.contains( menuElement, event.target );
6100	},
6101
6102	_closeOnClickOutside: function( event ) {
6103		if ( !this._isEventTargetInWidget( event ) ) {
6104			this.close();
6105		}
6106	},
6107
6108	_appendTo: function() {
6109		var element = this.options.appendTo;
6110
6111		if ( element ) {
6112			element = element.jquery || element.nodeType ?
6113				$( element ) :
6114				this.document.find( element ).eq( 0 );
6115		}
6116
6117		if ( !element || !element[ 0 ] ) {
6118			element = this.element.closest( ".ui-front, dialog" );
6119		}
6120
6121		if ( !element.length ) {
6122			element = this.document[ 0 ].body;
6123		}
6124
6125		return element;
6126	},
6127
6128	_initSource: function() {
6129		var array, url,
6130			that = this;
6131		if ( $.isArray( this.options.source ) ) {
6132			array = this.options.source;
6133			this.source = function( request, response ) {
6134				response( $.ui.autocomplete.filter( array, request.term ) );
6135			};
6136		} else if ( typeof this.options.source === "string" ) {
6137			url = this.options.source;
6138			this.source = function( request, response ) {
6139				if ( that.xhr ) {
6140					that.xhr.abort();
6141				}
6142				that.xhr = $.ajax( {
6143					url: url,
6144					data: request,
6145					dataType: "json",
6146					success: function( data ) {
6147						response( data );
6148					},
6149					error: function() {
6150						response( [] );
6151					}
6152				} );
6153			};
6154		} else {
6155			this.source = this.options.source;
6156		}
6157	},
6158
6159	_searchTimeout: function( event ) {
6160		clearTimeout( this.searching );
6161		this.searching = this._delay( function() {
6162
6163			// Search if the value has changed, or if the user retypes the same value (see #7434)
6164			var equalValues = this.term === this._value(),
6165				menuVisible = this.menu.element.is( ":visible" ),
6166				modifierKey = event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;
6167
6168			if ( !equalValues || ( equalValues && !menuVisible && !modifierKey ) ) {
6169				this.selectedItem = null;
6170				this.search( null, event );
6171			}
6172		}, this.options.delay );
6173	},
6174
6175	search: function( value, event ) {
6176		value = value != null ? value : this._value();
6177
6178		// Always save the actual value, not the one passed as an argument
6179		this.term = this._value();
6180
6181		if ( value.length < this.options.minLength ) {
6182			return this.close( event );
6183		}
6184
6185		if ( this._trigger( "search", event ) === false ) {
6186			return;
6187		}
6188
6189		return this._search( value );
6190	},
6191
6192	_search: function( value ) {
6193		this.pending++;
6194		this._addClass( "ui-autocomplete-loading" );
6195		this.cancelSearch = false;
6196
6197		this.source( { term: value }, this._response() );
6198	},
6199
6200	_response: function() {
6201		var index = ++this.requestIndex;
6202
6203		return $.proxy( function( content ) {
6204			if ( index === this.requestIndex ) {
6205				this.__response( content );
6206			}
6207
6208			this.pending--;
6209			if ( !this.pending ) {
6210				this._removeClass( "ui-autocomplete-loading" );
6211			}
6212		}, this );
6213	},
6214
6215	__response: function( content ) {
6216		if ( content ) {
6217			content = this._normalize( content );
6218		}
6219		this._trigger( "response", null, { content: content } );
6220		if ( !this.options.disabled && content && content.length && !this.cancelSearch ) {
6221			this._suggest( content );
6222			this._trigger( "open" );
6223		} else {
6224
6225			// use ._close() instead of .close() so we don't cancel future searches
6226			this._close();
6227		}
6228	},
6229
6230	close: function( event ) {
6231		this.cancelSearch = true;
6232		this._close( event );
6233	},
6234
6235	_close: function( event ) {
6236
6237		// Remove the handler that closes the menu on outside clicks
6238		this._off( this.document, "mousedown" );
6239
6240		if ( this.menu.element.is( ":visible" ) ) {
6241			this.menu.element.hide();
6242			this.menu.blur();
6243			this.isNewMenu = true;
6244			this._trigger( "close", event );
6245		}
6246	},
6247
6248	_change: function( event ) {
6249		if ( this.previous !== this._value() ) {
6250			this._trigger( "change", event, { item: this.selectedItem } );
6251		}
6252	},
6253
6254	_normalize: function( items ) {
6255
6256		// assume all items have the right format when the first item is complete
6257		if ( items.length && items[ 0 ].label && items[ 0 ].value ) {
6258			return items;
6259		}
6260		return $.map( items, function( item ) {
6261			if ( typeof item === "string" ) {
6262				return {
6263					label: item,
6264					value: item
6265				};
6266			}
6267			return $.extend( {}, item, {
6268				label: item.label || item.value,
6269				value: item.value || item.label
6270			} );
6271		} );
6272	},
6273
6274	_suggest: function( items ) {
6275		var ul = this.menu.element.empty();
6276		this._renderMenu( ul, items );
6277		this.isNewMenu = true;
6278		this.menu.refresh();
6279
6280		// Size and position menu
6281		ul.show();
6282		this._resizeMenu();
6283		ul.position( $.extend( {
6284			of: this.element
6285		}, this.options.position ) );
6286
6287		if ( this.options.autoFocus ) {
6288			this.menu.next();
6289		}
6290
6291		// Listen for interactions outside of the widget (#6642)
6292		this._on( this.document, {
6293			mousedown: "_closeOnClickOutside"
6294		} );
6295	},
6296
6297	_resizeMenu: function() {
6298		var ul = this.menu.element;
6299		ul.outerWidth( Math.max(
6300
6301			// Firefox wraps long text (possibly a rounding bug)
6302			// so we add 1px to avoid the wrapping (#7513)
6303			ul.width( "" ).outerWidth() + 1,
6304			this.element.outerWidth()
6305		) );
6306	},
6307
6308	_renderMenu: function( ul, items ) {
6309		var that = this;
6310		$.each( items, function( index, item ) {
6311			that._renderItemData( ul, item );
6312		} );
6313	},
6314
6315	_renderItemData: function( ul, item ) {
6316		return this._renderItem( ul, item ).data( "ui-autocomplete-item", item );
6317	},
6318
6319	_renderItem: function( ul, item ) {
6320		return $( "<li>" )
6321			.append( $( "<div>" ).text( item.label ) )
6322			.appendTo( ul );
6323	},
6324
6325	_move: function( direction, event ) {
6326		if ( !this.menu.element.is( ":visible" ) ) {
6327			this.search( null, event );
6328			return;
6329		}
6330		if ( this.menu.isFirstItem() && /^previous/.test( direction ) ||
6331				this.menu.isLastItem() && /^next/.test( direction ) ) {
6332
6333			if ( !this.isMultiLine ) {
6334				this._value( this.term );
6335			}
6336
6337			this.menu.blur();
6338			return;
6339		}
6340		this.menu[ direction ]( event );
6341	},
6342
6343	widget: function() {
6344		return this.menu.element;
6345	},
6346
6347	_value: function() {
6348		return this.valueMethod.apply( this.element, arguments );
6349	},
6350
6351	_keyEvent: function( keyEvent, event ) {
6352		if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
6353			this._move( keyEvent, event );
6354
6355			// Prevents moving cursor to beginning/end of the text field in some browsers
6356			event.preventDefault();
6357		}
6358	},
6359
6360	// Support: Chrome <=50
6361	// We should be able to just use this.element.prop( "isContentEditable" )
6362	// but hidden elements always report false in Chrome.
6363	// https://code.google.com/p/chromium/issues/detail?id=313082
6364	_isContentEditable: function( element ) {
6365		if ( !element.length ) {
6366			return false;
6367		}
6368
6369		var editable = element.prop( "contentEditable" );
6370
6371		if ( editable === "inherit" ) {
6372		  return this._isContentEditable( element.parent() );
6373		}
6374
6375		return editable === "true";
6376	}
6377} );
6378
6379$.extend( $.ui.autocomplete, {
6380	escapeRegex: function( value ) {
6381		return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" );
6382	},
6383	filter: function( array, term ) {
6384		var matcher = new RegExp( $.ui.autocomplete.escapeRegex( term ), "i" );
6385		return $.grep( array, function( value ) {
6386			return matcher.test( value.label || value.value || value );
6387		} );
6388	}
6389} );
6390
6391// Live region extension, adding a `messages` option
6392// NOTE: This is an experimental API. We are still investigating
6393// a full solution for string manipulation and internationalization.
6394$.widget( "ui.autocomplete", $.ui.autocomplete, {
6395	options: {
6396		messages: {
6397			noResults: "No search results.",
6398			results: function( amount ) {
6399				return amount + ( amount > 1 ? " results are" : " result is" ) +
6400					" available, use up and down arrow keys to navigate.";
6401			}
6402		}
6403	},
6404
6405	__response: function( content ) {
6406		var message;
6407		this._superApply( arguments );
6408		if ( this.options.disabled || this.cancelSearch ) {
6409			return;
6410		}
6411		if ( content && content.length ) {
6412			message = this.options.messages.results( content.length );
6413		} else {
6414			message = this.options.messages.noResults;
6415		}
6416		this.liveRegion.children().hide();
6417		$( "<div>" ).text( message ).appendTo( this.liveRegion );
6418	}
6419} );
6420
6421var widgetsAutocomplete = $.ui.autocomplete;
6422
6423
6424/*!
6425 * jQuery UI Controlgroup 1.12.1
6426 * http://jqueryui.com
6427 *
6428 * Copyright jQuery Foundation and other contributors
6429 * Released under the MIT license.
6430 * http://jquery.org/license
6431 */
6432
6433//>>label: Controlgroup
6434//>>group: Widgets
6435//>>description: Visually groups form control widgets
6436//>>docs: http://api.jqueryui.com/controlgroup/
6437//>>demos: http://jqueryui.com/controlgroup/
6438//>>css.structure: ../../themes/base/core.css
6439//>>css.structure: ../../themes/base/controlgroup.css
6440//>>css.theme: ../../themes/base/theme.css
6441
6442
6443var controlgroupCornerRegex = /ui-corner-([a-z]){2,6}/g;
6444
6445var widgetsControlgroup = $.widget( "ui.controlgroup", {
6446	version: "1.12.1",
6447	defaultElement: "<div>",
6448	options: {
6449		direction: "horizontal",
6450		disabled: null,
6451		onlyVisible: true,
6452		items: {
6453			"button": "input[type=button], input[type=submit], input[type=reset], button, a",
6454			"controlgroupLabel": ".ui-controlgroup-label",
6455			"checkboxradio": "input[type='checkbox'], input[type='radio']",
6456			"selectmenu": "select",
6457			"spinner": ".ui-spinner-input"
6458		}
6459	},
6460
6461	_create: function() {
6462		this._enhance();
6463	},
6464
6465	// To support the enhanced option in jQuery Mobile, we isolate DOM manipulation
6466	_enhance: function() {
6467		this.element.attr( "role", "toolbar" );
6468		this.refresh();
6469	},
6470
6471	_destroy: function() {
6472		this._callChildMethod( "destroy" );
6473		this.childWidgets.removeData( "ui-controlgroup-data" );
6474		this.element.removeAttr( "role" );
6475		if ( this.options.items.controlgroupLabel ) {
6476			this.element
6477				.find( this.options.items.controlgroupLabel )
6478				.find( ".ui-controlgroup-label-contents" )
6479				.contents().unwrap();
6480		}
6481	},
6482
6483	_initWidgets: function() {
6484		var that = this,
6485			childWidgets = [];
6486
6487		// First we iterate over each of the items options
6488		$.each( this.options.items, function( widget, selector ) {
6489			var labels;
6490			var options = {};
6491
6492			// Make sure the widget has a selector set
6493			if ( !selector ) {
6494				return;
6495			}
6496
6497			if ( widget === "controlgroupLabel" ) {
6498				labels = that.element.find( selector );
6499				labels.each( function() {
6500					var element = $( this );
6501
6502					if ( element.children( ".ui-controlgroup-label-contents" ).length ) {
6503						return;
6504					}
6505					element.contents()
6506						.wrapAll( "<span class='ui-controlgroup-label-contents'></span>" );
6507				} );
6508				that._addClass( labels, null, "ui-widget ui-widget-content ui-state-default" );
6509				childWidgets = childWidgets.concat( labels.get() );
6510				return;
6511			}
6512
6513			// Make sure the widget actually exists
6514			if ( !$.fn[ widget ] ) {
6515				return;
6516			}
6517
6518			// We assume everything is in the middle to start because we can't determine
6519			// first / last elements until all enhancments are done.
6520			if ( that[ "_" + widget + "Options" ] ) {
6521				options = that[ "_" + widget + "Options" ]( "middle" );
6522			} else {
6523				options = { classes: {} };
6524			}
6525
6526			// Find instances of this widget inside controlgroup and init them
6527			that.element
6528				.find( selector )
6529				.each( function() {
6530					var element = $( this );
6531					var instance = element[ widget ]( "instance" );
6532
6533					// We need to clone the default options for this type of widget to avoid
6534					// polluting the variable options which has a wider scope than a single widget.
6535					var instanceOptions = $.widget.extend( {}, options );
6536
6537					// If the button is the child of a spinner ignore it
6538					// TODO: Find a more generic solution
6539					if ( widget === "button" && element.parent( ".ui-spinner" ).length ) {
6540						return;
6541					}
6542
6543					// Create the widget if it doesn't exist
6544					if ( !instance ) {
6545						instance = element[ widget ]()[ widget ]( "instance" );
6546					}
6547					if ( instance ) {
6548						instanceOptions.classes =
6549							that._resolveClassesValues( instanceOptions.classes, instance );
6550					}
6551					element[ widget ]( instanceOptions );
6552
6553					// Store an instance of the controlgroup to be able to reference
6554					// from the outermost element for changing options and refresh
6555					var widgetElement = element[ widget ]( "widget" );
6556					$.data( widgetElement[ 0 ], "ui-controlgroup-data",
6557						instance ? instance : element[ widget ]( "instance" ) );
6558
6559					childWidgets.push( widgetElement[ 0 ] );
6560				} );
6561		} );
6562
6563		this.childWidgets = $( $.unique( childWidgets ) );
6564		this._addClass( this.childWidgets, "ui-controlgroup-item" );
6565	},
6566
6567	_callChildMethod: function( method ) {
6568		this.childWidgets.each( function() {
6569			var element = $( this ),
6570				data = element.data( "ui-controlgroup-data" );
6571			if ( data && data[ method ] ) {
6572				data[ method ]();
6573			}
6574		} );
6575	},
6576
6577	_updateCornerClass: function( element, position ) {
6578		var remove = "ui-corner-top ui-corner-bottom ui-corner-left ui-corner-right ui-corner-all";
6579		var add = this._buildSimpleOptions( position, "label" ).classes.label;
6580
6581		this._removeClass( element, null, remove );
6582		this._addClass( element, null, add );
6583	},
6584
6585	_buildSimpleOptions: function( position, key ) {
6586		var direction = this.options.direction === "vertical";
6587		var result = {
6588			classes: {}
6589		};
6590		result.classes[ key ] = {
6591			"middle": "",
6592			"first": "ui-corner-" + ( direction ? "top" : "left" ),
6593			"last": "ui-corner-" + ( direction ? "bottom" : "right" ),
6594			"only": "ui-corner-all"
6595		}[ position ];
6596
6597		return result;
6598	},
6599
6600	_spinnerOptions: function( position ) {
6601		var options = this._buildSimpleOptions( position, "ui-spinner" );
6602
6603		options.classes[ "ui-spinner-up" ] = "";
6604		options.classes[ "ui-spinner-down" ] = "";
6605
6606		return options;
6607	},
6608
6609	_buttonOptions: function( position ) {
6610		return this._buildSimpleOptions( position, "ui-button" );
6611	},
6612
6613	_checkboxradioOptions: function( position ) {
6614		return this._buildSimpleOptions( position, "ui-checkboxradio-label" );
6615	},
6616
6617	_selectmenuOptions: function( position ) {
6618		var direction = this.options.direction === "vertical";
6619		return {
6620			width: direction ? "auto" : false,
6621			classes: {
6622				middle: {
6623					"ui-selectmenu-button-open": "",
6624					"ui-selectmenu-button-closed": ""
6625				},
6626				first: {
6627					"ui-selectmenu-button-open": "ui-corner-" + ( direction ? "top" : "tl" ),
6628					"ui-selectmenu-button-closed": "ui-corner-" + ( direction ? "top" : "left" )
6629				},
6630				last: {
6631					"ui-selectmenu-button-open": direction ? "" : "ui-corner-tr",
6632					"ui-selectmenu-button-closed": "ui-corner-" + ( direction ? "bottom" : "right" )
6633				},
6634				only: {
6635					"ui-selectmenu-button-open": "ui-corner-top",
6636					"ui-selectmenu-button-closed": "ui-corner-all"
6637				}
6638
6639			}[ position ]
6640		};
6641	},
6642
6643	_resolveClassesValues: function( classes, instance ) {
6644		var result = {};
6645		$.each( classes, function( key ) {
6646			var current = instance.options.classes[ key ] || "";
6647			current = $.trim( current.replace( controlgroupCornerRegex, "" ) );
6648			result[ key ] = ( current + " " + classes[ key ] ).replace( /\s+/g, " " );
6649		} );
6650		return result;
6651	},
6652
6653	_setOption: function( key, value ) {
6654		if ( key === "direction" ) {
6655			this._removeClass( "ui-controlgroup-" + this.options.direction );
6656		}
6657
6658		this._super( key, value );
6659		if ( key === "disabled" ) {
6660			this._callChildMethod( value ? "disable" : "enable" );
6661			return;
6662		}
6663
6664		this.refresh();
6665	},
6666
6667	refresh: function() {
6668		var children,
6669			that = this;
6670
6671		this._addClass( "ui-controlgroup ui-controlgroup-" + this.options.direction );
6672
6673		if ( this.options.direction === "horizontal" ) {
6674			this._addClass( null, "ui-helper-clearfix" );
6675		}
6676		this._initWidgets();
6677
6678		children = this.childWidgets;
6679
6680		// We filter here because we need to track all childWidgets not just the visible ones
6681		if ( this.options.onlyVisible ) {
6682			children = children.filter( ":visible" );
6683		}
6684
6685		if ( children.length ) {
6686
6687			// We do this last because we need to make sure all enhancment is done
6688			// before determining first and last
6689			$.each( [ "first", "last" ], function( index, value ) {
6690				var instance = children[ value ]().data( "ui-controlgroup-data" );
6691
6692				if ( instance && that[ "_" + instance.widgetName + "Options" ] ) {
6693					var options = that[ "_" + instance.widgetName + "Options" ](
6694						children.length === 1 ? "only" : value
6695					);
6696					options.classes = that._resolveClassesValues( options.classes, instance );
6697					instance.element[ instance.widgetName ]( options );
6698				} else {
6699					that._updateCornerClass( children[ value ](), value );
6700				}
6701			} );
6702
6703			// Finally call the refresh method on each of the child widgets.
6704			this._callChildMethod( "refresh" );
6705		}
6706	}
6707} );
6708
6709/*!
6710 * jQuery UI Checkboxradio 1.12.1
6711 * http://jqueryui.com
6712 *
6713 * Copyright jQuery Foundation and other contributors
6714 * Released under the MIT license.
6715 * http://jquery.org/license
6716 */
6717
6718//>>label: Checkboxradio
6719//>>group: Widgets
6720//>>description: Enhances a form with multiple themeable checkboxes or radio buttons.
6721//>>docs: http://api.jqueryui.com/checkboxradio/
6722//>>demos: http://jqueryui.com/checkboxradio/
6723//>>css.structure: ../../themes/base/core.css
6724//>>css.structure: ../../themes/base/button.css
6725//>>css.structure: ../../themes/base/checkboxradio.css
6726//>>css.theme: ../../themes/base/theme.css
6727
6728
6729
6730$.widget( "ui.checkboxradio", [ $.ui.formResetMixin, {
6731	version: "1.12.1",
6732	options: {
6733		disabled: null,
6734		label: null,
6735		icon: true,
6736		classes: {
6737			"ui-checkboxradio-label": "ui-corner-all",
6738			"ui-checkboxradio-icon": "ui-corner-all"
6739		}
6740	},
6741
6742	_getCreateOptions: function() {
6743		var disabled, labels;
6744		var that = this;
6745		var options = this._super() || {};
6746
6747		// We read the type here, because it makes more sense to throw a element type error first,
6748		// rather then the error for lack of a label. Often if its the wrong type, it
6749		// won't have a label (e.g. calling on a div, btn, etc)
6750		this._readType();
6751
6752		labels = this.element.labels();
6753
6754		// If there are multiple labels, use the last one
6755		this.label = $( labels[ labels.length - 1 ] );
6756		if ( !this.label.length ) {
6757			$.error( "No label found for checkboxradio widget" );
6758		}
6759
6760		this.originalLabel = "";
6761
6762		// We need to get the label text but this may also need to make sure it does not contain the
6763		// input itself.
6764		this.label.contents().not( this.element[ 0 ] ).each( function() {
6765
6766			// The label contents could be text, html, or a mix. We concat each element to get a
6767			// string representation of the label, without the input as part of it.
6768			that.originalLabel += this.nodeType === 3 ? $( this ).text() : this.outerHTML;
6769		} );
6770
6771		// Set the label option if we found label text
6772		if ( this.originalLabel ) {
6773			options.label = this.originalLabel;
6774		}
6775
6776		disabled = this.element[ 0 ].disabled;
6777		if ( disabled != null ) {
6778			options.disabled = disabled;
6779		}
6780		return options;
6781	},
6782
6783	_create: function() {
6784		var checked = this.element[ 0 ].checked;
6785
6786		this._bindFormResetHandler();
6787
6788		if ( this.options.disabled == null ) {
6789			this.options.disabled = this.element[ 0 ].disabled;
6790		}
6791
6792		this._setOption( "disabled", this.options.disabled );
6793		this._addClass( "ui-checkboxradio", "ui-helper-hidden-accessible" );
6794		this._addClass( this.label, "ui-checkboxradio-label", "ui-button ui-widget" );
6795
6796		if ( this.type === "radio" ) {
6797			this._addClass( this.label, "ui-checkboxradio-radio-label" );
6798		}
6799
6800		if ( this.options.label && this.options.label !== this.originalLabel ) {
6801			this._updateLabel();
6802		} else if ( this.originalLabel ) {
6803			this.options.label = this.originalLabel;
6804		}
6805
6806		this._enhance();
6807
6808		if ( checked ) {
6809			this._addClass( this.label, "ui-checkboxradio-checked", "ui-state-active" );
6810			if ( this.icon ) {
6811				this._addClass( this.icon, null, "ui-state-hover" );
6812			}
6813		}
6814
6815		this._on( {
6816			change: "_toggleClasses",
6817			focus: function() {
6818				this._addClass( this.label, null, "ui-state-focus ui-visual-focus" );
6819			},
6820			blur: function() {
6821				this._removeClass( this.label, null, "ui-state-focus ui-visual-focus" );
6822			}
6823		} );
6824	},
6825
6826	_readType: function() {
6827		var nodeName = this.element[ 0 ].nodeName.toLowerCase();
6828		this.type = this.element[ 0 ].type;
6829		if ( nodeName !== "input" || !/radio|checkbox/.test( this.type ) ) {
6830			$.error( "Can't create checkboxradio on element.nodeName=" + nodeName +
6831				" and element.type=" + this.type );
6832		}
6833	},
6834
6835	// Support jQuery Mobile enhanced option
6836	_enhance: function() {
6837		this._updateIcon( this.element[ 0 ].checked );
6838	},
6839
6840	widget: function() {
6841		return this.label;
6842	},
6843
6844	_getRadioGroup: function() {
6845		var group;
6846		var name = this.element[ 0 ].name;
6847		var nameSelector = "input[name='" + $.ui.escapeSelector( name ) + "']";
6848
6849		if ( !name ) {
6850			return $( [] );
6851		}
6852
6853		if ( this.form.length ) {
6854			group = $( this.form[ 0 ].elements ).filter( nameSelector );
6855		} else {
6856
6857			// Not inside a form, check all inputs that also are not inside a form
6858			group = $( nameSelector ).filter( function() {
6859				return $( this ).form().length === 0;
6860			} );
6861		}
6862
6863		return group.not( this.element );
6864	},
6865
6866	_toggleClasses: function() {
6867		var checked = this.element[ 0 ].checked;
6868		this._toggleClass( this.label, "ui-checkboxradio-checked", "ui-state-active", checked );
6869
6870		if ( this.options.icon && this.type === "checkbox" ) {
6871			this._toggleClass( this.icon, null, "ui-icon-check ui-state-checked", checked )
6872				._toggleClass( this.icon, null, "ui-icon-blank", !checked );
6873		}
6874
6875		if ( this.type === "radio" ) {
6876			this._getRadioGroup()
6877				.each( function() {
6878					var instance = $( this ).checkboxradio( "instance" );
6879
6880					if ( instance ) {
6881						instance._removeClass( instance.label,
6882							"ui-checkboxradio-checked", "ui-state-active" );
6883					}
6884				} );
6885		}
6886	},
6887
6888	_destroy: function() {
6889		this._unbindFormResetHandler();
6890
6891		if ( this.icon ) {
6892			this.icon.remove();
vendor: 4,659 bytes, lines 6893-7066
6893			this.iconSpace.remove();
6894		}
6895	},
6896
6897	_setOption: function( key, value ) {
6898
6899		// We don't allow the value to be set to nothing
6900		if ( key === "label" && !value ) {
6901			return;
6902		}
6903
6904		this._super( key, value );
6905
6906		if ( key === "disabled" ) {
6907			this._toggleClass( this.label, null, "ui-state-disabled", value );
6908			this.element[ 0 ].disabled = value;
6909
6910			// Don't refresh when setting disabled
6911			return;
6912		}
6913		this.refresh();
6914	},
6915
6916	_updateIcon: function( checked ) {
6917		var toAdd = "ui-icon ui-icon-background ";
6918
6919		if ( this.options.icon ) {
6920			if ( !this.icon ) {
6921				this.icon = $( "<span>" );
6922				this.iconSpace = $( "<span> </span>" );
6923				this._addClass( this.iconSpace, "ui-checkboxradio-icon-space" );
6924			}
6925
6926			if ( this.type === "checkbox" ) {
6927				toAdd += checked ? "ui-icon-check ui-state-checked" : "ui-icon-blank";
6928				this._removeClass( this.icon, null, checked ? "ui-icon-blank" : "ui-icon-check" );
6929			} else {
6930				toAdd += "ui-icon-blank";
6931			}
6932			this._addClass( this.icon, "ui-checkboxradio-icon", toAdd );
6933			if ( !checked ) {
6934				this._removeClass( this.icon, null, "ui-icon-check ui-state-checked" );
6935			}
6936			this.icon.prependTo( this.label ).after( this.iconSpace );
6937		} else if ( this.icon !== undefined ) {
6938			this.icon.remove();
6939			this.iconSpace.remove();
6940			delete this.icon;
6941		}
6942	},
6943
6944	_updateLabel: function() {
6945
6946		// Remove the contents of the label ( minus the icon, icon space, and input )
6947		var contents = this.label.contents().not( this.element[ 0 ] );
6948		if ( this.icon ) {
6949			contents = contents.not( this.icon[ 0 ] );
6950		}
6951		if ( this.iconSpace ) {
6952			contents = contents.not( this.iconSpace[ 0 ] );
6953		}
6954		contents.remove();
6955
6956		this.label.append( this.options.label );
6957	},
6958
6959	refresh: function() {
6960		var checked = this.element[ 0 ].checked,
6961			isDisabled = this.element[ 0 ].disabled;
6962
6963		this._updateIcon( checked );
6964		this._toggleClass( this.label, "ui-checkboxradio-checked", "ui-state-active", checked );
6965		if ( this.options.label !== null ) {
6966			this._updateLabel();
6967		}
6968
6969		if ( isDisabled !== this.options.disabled ) {
6970			this._setOptions( { "disabled": isDisabled } );
6971		}
6972	}
6973
6974} ] );
6975
6976var widgetsCheckboxradio = $.ui.checkboxradio;
6977
6978
6979/*!
6980 * jQuery UI Button 1.12.1
6981 * http://jqueryui.com
6982 *
6983 * Copyright jQuery Foundation and other contributors
6984 * Released under the MIT license.
6985 * http://jquery.org/license
6986 */
6987
6988//>>label: Button
6989//>>group: Widgets
6990//>>description: Enhances a form with themeable buttons.
6991//>>docs: http://api.jqueryui.com/button/
6992//>>demos: http://jqueryui.com/button/
6993//>>css.structure: ../../themes/base/core.css
6994//>>css.structure: ../../themes/base/button.css
6995//>>css.theme: ../../themes/base/theme.css
6996
6997
6998
6999$.widget( "ui.button", {
7000	version: "1.12.1",
7001	defaultElement: "<button>",
7002	options: {
7003		classes: {
7004			"ui-button": "ui-corner-all"
7005		},
7006		disabled: null,
7007		icon: null,
7008		iconPosition: "beginning",
7009		label: null,
7010		showLabel: true
7011	},
7012
7013	_getCreateOptions: function() {
7014		var disabled,
7015
7016			// This is to support cases like in jQuery Mobile where the base widget does have
7017			// an implementation of _getCreateOptions
7018			options = this._super() || {};
7019
7020		this.isInput = this.element.is( "input" );
7021
7022		disabled = this.element[ 0 ].disabled;
7023		if ( disabled != null ) {
7024			options.disabled = disabled;
7025		}
7026
7027		this.originalLabel = this.isInput ? this.element.val() : this.element.html();
7028		if ( this.originalLabel ) {
7029			options.label = this.originalLabel;
7030		}
7031
7032		return options;
7033	},
7034
7035	_create: function() {
7036		if ( !this.option.showLabel & !this.options.icon ) {
7037			this.options.showLabel = true;
7038		}
7039
7040		// We have to check the option again here even though we did in _getCreateOptions,
7041		// because null may have been passed on init which would override what was set in
7042		// _getCreateOptions
7043		if ( this.options.disabled == null ) {
7044			this.options.disabled = this.element[ 0 ].disabled || false;
7045		}
7046
7047		this.hasTitle = !!this.element.attr( "title" );
7048
7049		// Check to see if the label needs to be set or if its already correct
7050		if ( this.options.label && this.options.label !== this.originalLabel ) {
7051			if ( this.isInput ) {
7052				this.element.val( this.options.label );
7053			} else {
7054				this.element.html( this.options.label );
7055			}
7056		}
7057		this._addClass( "ui-button", "ui-widget" );
7058		this._setOption( "disabled", this.options.disabled );
7059		this._enhance();
7060
7061		if ( this.element.is( "a" ) ) {
7062			this._on( {
7063				"keyup": function( event ) {
7064					if ( event.keyCode === $.ui.keyCode.SPACE ) {
7065						event.preventDefault();
7066
vendor: 7,743 bytes, lines 7067-7349
7067						// Support: PhantomJS <= 1.9, IE 8 Only
7068						// If a native click is available use it so we actually cause navigation
7069						// otherwise just trigger a click event
7070						if ( this.element[ 0 ].click ) {
7071							this.element[ 0 ].click();
7072						} else {
7073							this.element.trigger( "click" );
7074						}
7075					}
7076				}
7077			} );
7078		}
7079	},
7080
7081	_enhance: function() {
7082		if ( !this.element.is( "button" ) ) {
7083			this.element.attr( "role", "button" );
7084		}
7085
7086		if ( this.options.icon ) {
7087			this._updateIcon( "icon", this.options.icon );
7088			this._updateTooltip();
7089		}
7090	},
7091
7092	_updateTooltip: function() {
7093		this.title = this.element.attr( "title" );
7094
7095		if ( !this.options.showLabel && !this.title ) {
7096			this.element.attr( "title", this.options.label );
7097		}
7098	},
7099
7100	_updateIcon: function( option, value ) {
7101		var icon = option !== "iconPosition",
7102			position = icon ? this.options.iconPosition : value,
7103			displayBlock = position === "top" || position === "bottom";
7104
7105		// Create icon
7106		if ( !this.icon ) {
7107			this.icon = $( "<span>" );
7108
7109			this._addClass( this.icon, "ui-button-icon", "ui-icon" );
7110
7111			if ( !this.options.showLabel ) {
7112				this._addClass( "ui-button-icon-only" );
7113			}
7114		} else if ( icon ) {
7115
7116			// If we are updating the icon remove the old icon class
7117			this._removeClass( this.icon, null, this.options.icon );
7118		}
7119
7120		// If we are updating the icon add the new icon class
7121		if ( icon ) {
7122			this._addClass( this.icon, null, value );
7123		}
7124
7125		this._attachIcon( position );
7126
7127		// If the icon is on top or bottom we need to add the ui-widget-icon-block class and remove
7128		// the iconSpace if there is one.
7129		if ( displayBlock ) {
7130			this._addClass( this.icon, null, "ui-widget-icon-block" );
7131			if ( this.iconSpace ) {
7132				this.iconSpace.remove();
7133			}
7134		} else {
7135
7136			// Position is beginning or end so remove the ui-widget-icon-block class and add the
7137			// space if it does not exist
7138			if ( !this.iconSpace ) {
7139				this.iconSpace = $( "<span> </span>" );
7140				this._addClass( this.iconSpace, "ui-button-icon-space" );
7141			}
7142			this._removeClass( this.icon, null, "ui-wiget-icon-block" );
7143			this._attachIconSpace( position );
7144		}
7145	},
7146
7147	_destroy: function() {
7148		this.element.removeAttr( "role" );
7149
7150		if ( this.icon ) {
7151			this.icon.remove();
7152		}
7153		if ( this.iconSpace ) {
7154			this.iconSpace.remove();
7155		}
7156		if ( !this.hasTitle ) {
7157			this.element.removeAttr( "title" );
7158		}
7159	},
7160
7161	_attachIconSpace: function( iconPosition ) {
7162		this.icon[ /^(?:end|bottom)/.test( iconPosition ) ? "before" : "after" ]( this.iconSpace );
7163	},
7164
7165	_attachIcon: function( iconPosition ) {
7166		this.element[ /^(?:end|bottom)/.test( iconPosition ) ? "append" : "prepend" ]( this.icon );
7167	},
7168
7169	_setOptions: function( options ) {
7170		var newShowLabel = options.showLabel === undefined ?
7171				this.options.showLabel :
7172				options.showLabel,
7173			newIcon = options.icon === undefined ? this.options.icon : options.icon;
7174
7175		if ( !newShowLabel && !newIcon ) {
7176			options.showLabel = true;
7177		}
7178		this._super( options );
7179	},
7180
7181	_setOption: function( key, value ) {
7182		if ( key === "icon" ) {
7183			if ( value ) {
7184				this._updateIcon( key, value );
7185			} else if ( this.icon ) {
7186				this.icon.remove();
7187				if ( this.iconSpace ) {
7188					this.iconSpace.remove();
7189				}
7190			}
7191		}
7192
7193		if ( key === "iconPosition" ) {
7194			this._updateIcon( key, value );
7195		}
7196
7197		// Make sure we can't end up with a button that has neither text nor icon
7198		if ( key === "showLabel" ) {
7199				this._toggleClass( "ui-button-icon-only", null, !value );
7200				this._updateTooltip();
7201		}
7202
7203		if ( key === "label" ) {
7204			if ( this.isInput ) {
7205				this.element.val( value );
7206			} else {
7207
7208				// If there is an icon, append it, else nothing then append the value
7209				// this avoids removal of the icon when setting label text
7210				this.element.html( value );
7211				if ( this.icon ) {
7212					this._attachIcon( this.options.iconPosition );
7213					this._attachIconSpace( this.options.iconPosition );
7214				}
7215			}
7216		}
7217
7218		this._super( key, value );
7219
7220		if ( key === "disabled" ) {
7221			this._toggleClass( null, "ui-state-disabled", value );
7222			this.element[ 0 ].disabled = value;
7223			if ( value ) {
7224				this.element.blur();
7225			}
7226		}
7227	},
7228
7229	refresh: function() {
7230
7231		// Make sure to only check disabled if its an element that supports this otherwise
7232		// check for the disabled class to determine state
7233		var isDisabled = this.element.is( "input, button" ) ?
7234			this.element[ 0 ].disabled : this.element.hasClass( "ui-button-disabled" );
7235
7236		if ( isDisabled !== this.options.disabled ) {
7237			this._setOptions( { disabled: isDisabled } );
7238		}
7239
7240		this._updateTooltip();
7241	}
7242} );
7243
7244// DEPRECATED
7245if ( $.uiBackCompat !== false ) {
7246
7247	// Text and Icons options
7248	$.widget( "ui.button", $.ui.button, {
7249		options: {
7250			text: true,
7251			icons: {
7252				primary: null,
7253				secondary: null
7254			}
7255		},
7256
7257		_create: function() {
7258			if ( this.options.showLabel && !this.options.text ) {
7259				this.options.showLabel = this.options.text;
7260			}
7261			if ( !this.options.showLabel && this.options.text ) {
7262				this.options.text = this.options.showLabel;
7263			}
7264			if ( !this.options.icon && ( this.options.icons.primary ||
7265					this.options.icons.secondary ) ) {
7266				if ( this.options.icons.primary ) {
7267					this.options.icon = this.options.icons.primary;
7268				} else {
7269					this.options.icon = this.options.icons.secondary;
7270					this.options.iconPosition = "end";
7271				}
7272			} else if ( this.options.icon ) {
7273				this.options.icons.primary = this.options.icon;
7274			}
7275			this._super();
7276		},
7277
7278		_setOption: function( key, value ) {
7279			if ( key === "text" ) {
7280				this._super( "showLabel", value );
7281				return;
7282			}
7283			if ( key === "showLabel" ) {
7284				this.options.text = value;
7285			}
7286			if ( key === "icon" ) {
7287				this.options.icons.primary = value;
7288			}
7289			if ( key === "icons" ) {
7290				if ( value.primary ) {
7291					this._super( "icon", value.primary );
7292					this._super( "iconPosition", "beginning" );
7293				} else if ( value.secondary ) {
7294					this._super( "icon", value.secondary );
7295					this._super( "iconPosition", "end" );
7296				}
7297			}
7298			this._superApply( arguments );
7299		}
7300	} );
7301
7302	$.fn.button = ( function( orig ) {
7303		return function() {
7304			if ( !this.length || ( this.length && this[ 0 ].tagName !== "INPUT" ) ||
7305					( this.length && this[ 0 ].tagName === "INPUT" && (
7306						this.attr( "type" ) !== "checkbox" && this.attr( "type" ) !== "radio"
7307					) ) ) {
7308				return orig.apply( this, arguments );
7309			}
7310			if ( !$.ui.checkboxradio ) {
7311				$.error( "Checkboxradio widget missing" );
7312			}
7313			if ( arguments.length === 0 ) {
7314				return this.checkboxradio( {
7315					"icon": false
7316				} );
7317			}
7318			return this.checkboxradio.apply( this, arguments );
7319		};
7320	} )( $.fn.button );
7321
7322	$.fn.buttonset = function() {
7323		if ( !$.ui.controlgroup ) {
7324			$.error( "Controlgroup widget missing" );
7325		}
7326		if ( arguments[ 0 ] === "option" && arguments[ 1 ] === "items" && arguments[ 2 ] ) {
7327			return this.controlgroup.apply( this,
7328				[ arguments[ 0 ], "items.button", arguments[ 2 ] ] );
7329		}
7330		if ( arguments[ 0 ] === "option" && arguments[ 1 ] === "items" ) {
7331			return this.controlgroup.apply( this, [ arguments[ 0 ], "items.button" ] );
7332		}
7333		if ( typeof arguments[ 0 ] === "object" && arguments[ 0 ].items ) {
7334			arguments[ 0 ].items = {
7335				button: arguments[ 0 ].items
7336			};
7337		}
7338		return this.controlgroup.apply( this, arguments );
7339	};
7340}
7341
7342var widgetsButton = $.ui.button;
7343
7344
7345// jscs:disable maximumLineLength
7346/* jscs:disable requireCamelCaseOrUpperCaseIdentifiers */
7347/*!
7348 * jQuery UI Datepicker 1.12.1
7349 * http://jqueryui.com
vendor: 4,553 bytes, lines 7350-7436
7350 *
7351 * Copyright jQuery Foundation and other contributors
7352 * Released under the MIT license.
7353 * http://jquery.org/license
7354 */
7355
7356//>>label: Datepicker
7357//>>group: Widgets
7358//>>description: Displays a calendar from an input or inline for selecting dates.
7359//>>docs: http://api.jqueryui.com/datepicker/
7360//>>demos: http://jqueryui.com/datepicker/
7361//>>css.structure: ../../themes/base/core.css
7362//>>css.structure: ../../themes/base/datepicker.css
7363//>>css.theme: ../../themes/base/theme.css
7364
7365
7366
7367$.extend( $.ui, { datepicker: { version: "1.12.1" } } );
7368
7369var datepicker_instActive;
7370
7371function datepicker_getZindex( elem ) {
7372	var position, value;
7373	while ( elem.length && elem[ 0 ] !== document ) {
7374
7375		// Ignore z-index if position is set to a value where z-index is ignored by the browser
7376		// This makes behavior of this function consistent across browsers
7377		// WebKit always returns auto if the element is positioned
7378		position = elem.css( "position" );
7379		if ( position === "absolute" || position === "relative" || position === "fixed" ) {
7380
7381			// IE returns 0 when zIndex is not specified
7382			// other browsers return a string
7383			// we ignore the case of nested elements with an explicit value of 0
7384			// <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
7385			value = parseInt( elem.css( "zIndex" ), 10 );
7386			if ( !isNaN( value ) && value !== 0 ) {
7387				return value;
7388			}
7389		}
7390		elem = elem.parent();
7391	}
7392
7393	return 0;
7394}
7395/* Date picker manager.
7396   Use the singleton instance of this class, $.datepicker, to interact with the date picker.
7397   Settings for (groups of) date pickers are maintained in an instance object,
7398   allowing multiple different settings on the same page. */
7399
7400function Datepicker() {
7401	this._curInst = null; // The current instance in use
7402	this._keyEvent = false; // If the last event was a key event
7403	this._disabledInputs = []; // List of date picker inputs that have been disabled
7404	this._datepickerShowing = false; // True if the popup picker is showing , false if not
7405	this._inDialog = false; // True if showing within a "dialog", false if not
7406	this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division
7407	this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class
7408	this._appendClass = "ui-datepicker-append"; // The name of the append marker class
7409	this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class
7410	this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class
7411	this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class
7412	this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class
7413	this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class
7414	this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class
7415	this.regional = []; // Available regional settings, indexed by language code
7416	this.regional[ "" ] = { // Default regional settings
7417		closeText: "Done", // Display text for close link
7418		prevText: "Prev", // Display text for previous month link
7419		nextText: "Next", // Display text for next month link
7420		currentText: "Today", // Display text for current month link
7421		monthNames: [ "January","February","March","April","May","June",
7422			"July","August","September","October","November","December" ], // Names of months for drop-down and formatting
7423		monthNamesShort: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ], // For formatting
7424		dayNames: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ], // For formatting
7425		dayNamesShort: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ], // For formatting
7426		dayNamesMin: [ "Su","Mo","Tu","We","Th","Fr","Sa" ], // Column headings for days starting at Sunday
7427		weekHeader: "Wk", // Column header for week of the year
7428		dateFormat: "mm/dd/yy", // See format options on parseDate
7429		firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
7430		isRTL: false, // True if right-to-left language, false if left-to-right
7431		showMonthAfterYear: false, // True if the year select precedes month, false for month then year
7432		yearSuffix: "" // Additional text to append to the year in the month headers
7433	};
7434	this._defaults = { // Global defaults for all the date picker instances
7435		showOn: "focus", // "focus" for popup on focus,
7436			// "button" for trigger button, or "both" for either
vendor: 6,761 bytes, lines 7437-7569
7437		showAnim: "fadeIn", // Name of jQuery animation for popup
7438		showOptions: {}, // Options for enhanced animations
7439		defaultDate: null, // Used when field is blank: actual date,
7440			// +/-number for offset from today, null for today
7441		appendText: "", // Display text following the input box, e.g. showing the format
7442		buttonText: "...", // Text for trigger button
7443		buttonImage: "", // URL for trigger button image
7444		buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
7445		hideIfNoPrevNext: false, // True to hide next/previous month links
7446			// if not applicable, false to just disable them
7447		navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
7448		gotoCurrent: false, // True if today link goes back to current selection instead
7449		changeMonth: false, // True if month can be selected directly, false if only prev/next
7450		changeYear: false, // True if year can be selected directly, false if only prev/next
7451		yearRange: "c-10:c+10", // Range of years to display in drop-down,
7452			// either relative to today's year (-nn:+nn), relative to currently displayed year
7453			// (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
7454		showOtherMonths: false, // True to show dates in other months, false to leave blank
7455		selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
7456		showWeek: false, // True to show week of the year, false to not show it
7457		calculateWeek: this.iso8601Week, // How to calculate the week of the year,
7458			// takes a Date and returns the number of the week for it
7459		shortYearCutoff: "+10", // Short year values < this are in the current century,
7460			// > this are in the previous century,
7461			// string value starting with "+" for current year + value
7462		minDate: null, // The earliest selectable date, or null for no limit
7463		maxDate: null, // The latest selectable date, or null for no limit
7464		duration: "fast", // Duration of display/closure
7465		beforeShowDay: null, // Function that takes a date and returns an array with
7466			// [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "",
7467			// [2] = cell title (optional), e.g. $.datepicker.noWeekends
7468		beforeShow: null, // Function that takes an input field and
7469			// returns a set of custom settings for the date picker
7470		onSelect: null, // Define a callback function when a date is selected
7471		onChangeMonthYear: null, // Define a callback function when the month or year is changed
7472		onClose: null, // Define a callback function when the datepicker is closed
7473		numberOfMonths: 1, // Number of months to show at a time
7474		showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
7475		stepMonths: 1, // Number of months to step back/forward
7476		stepBigMonths: 12, // Number of months to step back/forward for the big links
7477		altField: "", // Selector for an alternate field to store selected dates into
7478		altFormat: "", // The date format to use for the alternate field
7479		constrainInput: true, // The input is constrained by the current date format
7480		showButtonPanel: false, // True to show button panel, false to not show it
7481		autoSize: false, // True to size the input for the date format, false to leave as is
7482		disabled: false // The initial disabled state
7483	};
7484	$.extend( this._defaults, this.regional[ "" ] );
7485	this.regional.en = $.extend( true, {}, this.regional[ "" ] );
7486	this.regional[ "en-US" ] = $.extend( true, {}, this.regional.en );
7487	this.dpDiv = datepicker_bindHover( $( "<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>" ) );
7488}
7489
7490$.extend( Datepicker.prototype, {
7491	/* Class name added to elements to indicate already configured with a date picker. */
7492	markerClassName: "hasDatepicker",
7493
7494	//Keep track of the maximum number of rows displayed (see #7043)
7495	maxRows: 4,
7496
7497	// TODO rename to "widget" when switching to widget factory
7498	_widgetDatepicker: function() {
7499		return this.dpDiv;
7500	},
7501
7502	/* Override the default settings for all instances of the date picker.
7503	 * @param  settings  object - the new settings to use as defaults (anonymous object)
7504	 * @return the manager object
7505	 */
7506	setDefaults: function( settings ) {
7507		datepicker_extendRemove( this._defaults, settings || {} );
7508		return this;
7509	},
7510
7511	/* Attach the date picker to a jQuery selection.
7512	 * @param  target	element - the target input field or division or span
7513	 * @param  settings  object - the new settings to use for this date picker instance (anonymous)
7514	 */
7515	_attachDatepicker: function( target, settings ) {
7516		var nodeName, inline, inst;
7517		nodeName = target.nodeName.toLowerCase();
7518		inline = ( nodeName === "div" || nodeName === "span" );
7519		if ( !target.id ) {
7520			this.uuid += 1;
7521			target.id = "dp" + this.uuid;
7522		}
7523		inst = this._newInst( $( target ), inline );
7524		inst.settings = $.extend( {}, settings || {} );
7525		if ( nodeName === "input" ) {
7526			this._connectDatepicker( target, inst );
7527		} else if ( inline ) {
7528			this._inlineDatepicker( target, inst );
7529		}
7530	},
7531
7532	/* Create a new instance object. */
7533	_newInst: function( target, inline ) {
7534		var id = target[ 0 ].id.replace( /([^A-Za-z0-9_\-])/g, "\\\\$1" ); // escape jQuery meta chars
7535		return { id: id, input: target, // associated target
7536			selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
7537			drawMonth: 0, drawYear: 0, // month being drawn
7538			inline: inline, // is datepicker inline or not
7539			dpDiv: ( !inline ? this.dpDiv : // presentation div
7540			datepicker_bindHover( $( "<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>" ) ) ) };
7541	},
7542
7543	/* Attach the date picker to an input field. */
7544	_connectDatepicker: function( target, inst ) {
7545		var input = $( target );
7546		inst.append = $( [] );
7547		inst.trigger = $( [] );
7548		if ( input.hasClass( this.markerClassName ) ) {
7549			return;
7550		}
7551		this._attachments( input, inst );
7552		input.addClass( this.markerClassName ).on( "keydown", this._doKeyDown ).
7553			on( "keypress", this._doKeyPress ).on( "keyup", this._doKeyUp );
7554		this._autoSize( inst );
7555		$.data( target, "datepicker", inst );
7556
7557		//If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
7558		if ( inst.settings.disabled ) {
7559			this._disableDatepicker( target );
7560		}
7561	},
7562
7563	/* Make attachments based on settings. */
7564	_attachments: function( input, inst ) {
7565		var showOn, buttonText, buttonImage,
7566			appendText = this._get( inst, "appendText" ),
7567			isRTL = this._get( inst, "isRTL" );
7568
7569		if ( inst.append ) {
vendor: 6,192 bytes, lines 7570-7727
7570			inst.append.remove();
7571		}
7572		if ( appendText ) {
7573			inst.append = $( "<span class='" + this._appendClass + "'>" + appendText + "</span>" );
7574			input[ isRTL ? "before" : "after" ]( inst.append );
7575		}
7576
7577		input.off( "focus", this._showDatepicker );
7578
7579		if ( inst.trigger ) {
7580			inst.trigger.remove();
7581		}
7582
7583		showOn = this._get( inst, "showOn" );
7584		if ( showOn === "focus" || showOn === "both" ) { // pop-up date picker when in the marked field
7585			input.on( "focus", this._showDatepicker );
7586		}
7587		if ( showOn === "button" || showOn === "both" ) { // pop-up date picker when button clicked
7588			buttonText = this._get( inst, "buttonText" );
7589			buttonImage = this._get( inst, "buttonImage" );
7590			inst.trigger = $( this._get( inst, "buttonImageOnly" ) ?
7591				$( "<img/>" ).addClass( this._triggerClass ).
7592					attr( { src: buttonImage, alt: buttonText, title: buttonText } ) :
7593				$( "<button type='button'></button>" ).addClass( this._triggerClass ).
7594					html( !buttonImage ? buttonText : $( "<img/>" ).attr(
7595					{ src:buttonImage, alt:buttonText, title:buttonText } ) ) );
7596			input[ isRTL ? "before" : "after" ]( inst.trigger );
7597			inst.trigger.on( "click", function() {
7598				if ( $.datepicker._datepickerShowing && $.datepicker._lastInput === input[ 0 ] ) {
7599					$.datepicker._hideDatepicker();
7600				} else if ( $.datepicker._datepickerShowing && $.datepicker._lastInput !== input[ 0 ] ) {
7601					$.datepicker._hideDatepicker();
7602					$.datepicker._showDatepicker( input[ 0 ] );
7603				} else {
7604					$.datepicker._showDatepicker( input[ 0 ] );
7605				}
7606				return false;
7607			} );
7608		}
7609	},
7610
7611	/* Apply the maximum length for the date format. */
7612	_autoSize: function( inst ) {
7613		if ( this._get( inst, "autoSize" ) && !inst.inline ) {
7614			var findMax, max, maxI, i,
7615				date = new Date( 2009, 12 - 1, 20 ), // Ensure double digits
7616				dateFormat = this._get( inst, "dateFormat" );
7617
7618			if ( dateFormat.match( /[DM]/ ) ) {
7619				findMax = function( names ) {
7620					max = 0;
7621					maxI = 0;
7622					for ( i = 0; i < names.length; i++ ) {
7623						if ( names[ i ].length > max ) {
7624							max = names[ i ].length;
7625							maxI = i;
7626						}
7627					}
7628					return maxI;
7629				};
7630				date.setMonth( findMax( this._get( inst, ( dateFormat.match( /MM/ ) ?
7631					"monthNames" : "monthNamesShort" ) ) ) );
7632				date.setDate( findMax( this._get( inst, ( dateFormat.match( /DD/ ) ?
7633					"dayNames" : "dayNamesShort" ) ) ) + 20 - date.getDay() );
7634			}
7635			inst.input.attr( "size", this._formatDate( inst, date ).length );
7636		}
7637	},
7638
7639	/* Attach an inline date picker to a div. */
7640	_inlineDatepicker: function( target, inst ) {
7641		var divSpan = $( target );
7642		if ( divSpan.hasClass( this.markerClassName ) ) {
7643			return;
7644		}
7645		divSpan.addClass( this.markerClassName ).append( inst.dpDiv );
7646		$.data( target, "datepicker", inst );
7647		this._setDate( inst, this._getDefaultDate( inst ), true );
7648		this._updateDatepicker( inst );
7649		this._updateAlternate( inst );
7650
7651		//If disabled option is true, disable the datepicker before showing it (see ticket #5665)
7652		if ( inst.settings.disabled ) {
7653			this._disableDatepicker( target );
7654		}
7655
7656		// Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
7657		// http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
7658		inst.dpDiv.css( "display", "block" );
7659	},
7660
7661	/* Pop-up the date picker in a "dialog" box.
7662	 * @param  input element - ignored
7663	 * @param  date	string or Date - the initial date to display
7664	 * @param  onSelect  function - the function to call when a date is selected
7665	 * @param  settings  object - update the dialog date picker instance's settings (anonymous object)
7666	 * @param  pos int[2] - coordinates for the dialog's position within the screen or
7667	 *					event - with x/y coordinates or
7668	 *					leave empty for default (screen centre)
7669	 * @return the manager object
7670	 */
7671	_dialogDatepicker: function( input, date, onSelect, settings, pos ) {
7672		var id, browserWidth, browserHeight, scrollX, scrollY,
7673			inst = this._dialogInst; // internal instance
7674
7675		if ( !inst ) {
7676			this.uuid += 1;
7677			id = "dp" + this.uuid;
7678			this._dialogInput = $( "<input type='text' id='" + id +
7679				"' style='position: absolute; top: -100px; width: 0px;'/>" );
7680			this._dialogInput.on( "keydown", this._doKeyDown );
7681			$( "body" ).append( this._dialogInput );
7682			inst = this._dialogInst = this._newInst( this._dialogInput, false );
7683			inst.settings = {};
7684			$.data( this._dialogInput[ 0 ], "datepicker", inst );
7685		}
7686		datepicker_extendRemove( inst.settings, settings || {} );
7687		date = ( date && date.constructor === Date ? this._formatDate( inst, date ) : date );
7688		this._dialogInput.val( date );
7689
7690		this._pos = ( pos ? ( pos.length ? pos : [ pos.pageX, pos.pageY ] ) : null );
7691		if ( !this._pos ) {
7692			browserWidth = document.documentElement.clientWidth;
7693			browserHeight = document.documentElement.clientHeight;
7694			scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
7695			scrollY = document.documentElement.scrollTop || document.body.scrollTop;
7696			this._pos = // should use actual width/height below
7697				[ ( browserWidth / 2 ) - 100 + scrollX, ( browserHeight / 2 ) - 150 + scrollY ];
7698		}
7699
7700		// Move input on screen for focus, but hidden behind dialog
7701		this._dialogInput.css( "left", ( this._pos[ 0 ] + 20 ) + "px" ).css( "top", this._pos[ 1 ] + "px" );
7702		inst.settings.onSelect = onSelect;
7703		this._inDialog = true;
7704		this.dpDiv.addClass( this._dialogClass );
7705		this._showDatepicker( this._dialogInput[ 0 ] );
7706		if ( $.blockUI ) {
7707			$.blockUI( this.dpDiv );
7708		}
7709		$.data( this._dialogInput[ 0 ], "datepicker", inst );
7710		return this;
7711	},
7712
7713	/* Detach a datepicker from its control.
7714	 * @param  target	element - the target input field or division or span
7715	 */
7716	_destroyDatepicker: function( target ) {
7717		var nodeName,
7718			$target = $( target ),
7719			inst = $.data( target, "datepicker" );
7720
7721		if ( !$target.hasClass( this.markerClassName ) ) {
7722			return;
7723		}
7724
7725		nodeName = target.nodeName.toLowerCase();
7726		$.removeData( target, "datepicker" );
7727		if ( nodeName === "input" ) {
vendor: 12,111 bytes, lines 7728-8068
7728			inst.append.remove();
7729			inst.trigger.remove();
7730			$target.removeClass( this.markerClassName ).
7731				off( "focus", this._showDatepicker ).
7732				off( "keydown", this._doKeyDown ).
7733				off( "keypress", this._doKeyPress ).
7734				off( "keyup", this._doKeyUp );
7735		} else if ( nodeName === "div" || nodeName === "span" ) {
7736			$target.removeClass( this.markerClassName ).empty();
7737		}
7738
7739		if ( datepicker_instActive === inst ) {
7740			datepicker_instActive = null;
7741		}
7742	},
7743
7744	/* Enable the date picker to a jQuery selection.
7745	 * @param  target	element - the target input field or division or span
7746	 */
7747	_enableDatepicker: function( target ) {
7748		var nodeName, inline,
7749			$target = $( target ),
7750			inst = $.data( target, "datepicker" );
7751
7752		if ( !$target.hasClass( this.markerClassName ) ) {
7753			return;
7754		}
7755
7756		nodeName = target.nodeName.toLowerCase();
7757		if ( nodeName === "input" ) {
7758			target.disabled = false;
7759			inst.trigger.filter( "button" ).
7760				each( function() { this.disabled = false; } ).end().
7761				filter( "img" ).css( { opacity: "1.0", cursor: "" } );
7762		} else if ( nodeName === "div" || nodeName === "span" ) {
7763			inline = $target.children( "." + this._inlineClass );
7764			inline.children().removeClass( "ui-state-disabled" );
7765			inline.find( "select.ui-datepicker-month, select.ui-datepicker-year" ).
7766				prop( "disabled", false );
7767		}
7768		this._disabledInputs = $.map( this._disabledInputs,
7769			function( value ) { return ( value === target ? null : value ); } ); // delete entry
7770	},
7771
7772	/* Disable the date picker to a jQuery selection.
7773	 * @param  target	element - the target input field or division or span
7774	 */
7775	_disableDatepicker: function( target ) {
7776		var nodeName, inline,
7777			$target = $( target ),
7778			inst = $.data( target, "datepicker" );
7779
7780		if ( !$target.hasClass( this.markerClassName ) ) {
7781			return;
7782		}
7783
7784		nodeName = target.nodeName.toLowerCase();
7785		if ( nodeName === "input" ) {
7786			target.disabled = true;
7787			inst.trigger.filter( "button" ).
7788				each( function() { this.disabled = true; } ).end().
7789				filter( "img" ).css( { opacity: "0.5", cursor: "default" } );
7790		} else if ( nodeName === "div" || nodeName === "span" ) {
7791			inline = $target.children( "." + this._inlineClass );
7792			inline.children().addClass( "ui-state-disabled" );
7793			inline.find( "select.ui-datepicker-month, select.ui-datepicker-year" ).
7794				prop( "disabled", true );
7795		}
7796		this._disabledInputs = $.map( this._disabledInputs,
7797			function( value ) { return ( value === target ? null : value ); } ); // delete entry
7798		this._disabledInputs[ this._disabledInputs.length ] = target;
7799	},
7800
7801	/* Is the first field in a jQuery collection disabled as a datepicker?
7802	 * @param  target	element - the target input field or division or span
7803	 * @return boolean - true if disabled, false if enabled
7804	 */
7805	_isDisabledDatepicker: function( target ) {
7806		if ( !target ) {
7807			return false;
7808		}
7809		for ( var i = 0; i < this._disabledInputs.length; i++ ) {
7810			if ( this._disabledInputs[ i ] === target ) {
7811				return true;
7812			}
7813		}
7814		return false;
7815	},
7816
7817	/* Retrieve the instance data for the target control.
7818	 * @param  target  element - the target input field or division or span
7819	 * @return  object - the associated instance data
7820	 * @throws  error if a jQuery problem getting data
7821	 */
7822	_getInst: function( target ) {
7823		try {
7824			return $.data( target, "datepicker" );
7825		}
7826		catch ( err ) {
7827			throw "Missing instance data for this datepicker";
7828		}
7829	},
7830
7831	/* Update or retrieve the settings for a date picker attached to an input field or division.
7832	 * @param  target  element - the target input field or division or span
7833	 * @param  name	object - the new settings to update or
7834	 *				string - the name of the setting to change or retrieve,
7835	 *				when retrieving also "all" for all instance settings or
7836	 *				"defaults" for all global defaults
7837	 * @param  value   any - the new value for the setting
7838	 *				(omit if above is an object or to retrieve a value)
7839	 */
7840	_optionDatepicker: function( target, name, value ) {
7841		var settings, date, minDate, maxDate,
7842			inst = this._getInst( target );
7843
7844		if ( arguments.length === 2 && typeof name === "string" ) {
7845			return ( name === "defaults" ? $.extend( {}, $.datepicker._defaults ) :
7846				( inst ? ( name === "all" ? $.extend( {}, inst.settings ) :
7847				this._get( inst, name ) ) : null ) );
7848		}
7849
7850		settings = name || {};
7851		if ( typeof name === "string" ) {
7852			settings = {};
7853			settings[ name ] = value;
7854		}
7855
7856		if ( inst ) {
7857			if ( this._curInst === inst ) {
7858				this._hideDatepicker();
7859			}
7860
7861			date = this._getDateDatepicker( target, true );
7862			minDate = this._getMinMaxDate( inst, "min" );
7863			maxDate = this._getMinMaxDate( inst, "max" );
7864			datepicker_extendRemove( inst.settings, settings );
7865
7866			// reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
7867			if ( minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined ) {
7868				inst.settings.minDate = this._formatDate( inst, minDate );
7869			}
7870			if ( maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined ) {
7871				inst.settings.maxDate = this._formatDate( inst, maxDate );
7872			}
7873			if ( "disabled" in settings ) {
7874				if ( settings.disabled ) {
7875					this._disableDatepicker( target );
7876				} else {
7877					this._enableDatepicker( target );
7878				}
7879			}
7880			this._attachments( $( target ), inst );
7881			this._autoSize( inst );
7882			this._setDate( inst, date );
7883			this._updateAlternate( inst );
7884			this._updateDatepicker( inst );
7885		}
7886	},
7887
7888	// Change method deprecated
7889	_changeDatepicker: function( target, name, value ) {
7890		this._optionDatepicker( target, name, value );
7891	},
7892
7893	/* Redraw the date picker attached to an input field or division.
7894	 * @param  target  element - the target input field or division or span
7895	 */
7896	_refreshDatepicker: function( target ) {
7897		var inst = this._getInst( target );
7898		if ( inst ) {
7899			this._updateDatepicker( inst );
7900		}
7901	},
7902
7903	/* Set the dates for a jQuery selection.
7904	 * @param  target element - the target input field or division or span
7905	 * @param  date	Date - the new date
7906	 */
7907	_setDateDatepicker: function( target, date ) {
7908		var inst = this._getInst( target );
7909		if ( inst ) {
7910			this._setDate( inst, date );
7911			this._updateDatepicker( inst );
7912			this._updateAlternate( inst );
7913		}
7914	},
7915
7916	/* Get the date(s) for the first entry in a jQuery selection.
7917	 * @param  target element - the target input field or division or span
7918	 * @param  noDefault boolean - true if no default date is to be used
7919	 * @return Date - the current date
7920	 */
7921	_getDateDatepicker: function( target, noDefault ) {
7922		var inst = this._getInst( target );
7923		if ( inst && !inst.inline ) {
7924			this._setDateFromField( inst, noDefault );
7925		}
7926		return ( inst ? this._getDate( inst ) : null );
7927	},
7928
7929	/* Handle keystrokes. */
7930	_doKeyDown: function( event ) {
7931		var onSelect, dateStr, sel,
7932			inst = $.datepicker._getInst( event.target ),
7933			handled = true,
7934			isRTL = inst.dpDiv.is( ".ui-datepicker-rtl" );
7935
7936		inst._keyEvent = true;
7937		if ( $.datepicker._datepickerShowing ) {
7938			switch ( event.keyCode ) {
7939				case 9: $.datepicker._hideDatepicker();
7940						handled = false;
7941						break; // hide on tab out
7942				case 13: sel = $( "td." + $.datepicker._dayOverClass + ":not(." +
7943									$.datepicker._currentClass + ")", inst.dpDiv );
7944						if ( sel[ 0 ] ) {
7945							$.datepicker._selectDay( event.target, inst.selectedMonth, inst.selectedYear, sel[ 0 ] );
7946						}
7947
7948						onSelect = $.datepicker._get( inst, "onSelect" );
7949						if ( onSelect ) {
7950							dateStr = $.datepicker._formatDate( inst );
7951
7952							// Trigger custom callback
7953							onSelect.apply( ( inst.input ? inst.input[ 0 ] : null ), [ dateStr, inst ] );
7954						} else {
7955							$.datepicker._hideDatepicker();
7956						}
7957
7958						return false; // don't submit the form
7959				case 27: $.datepicker._hideDatepicker();
7960						break; // hide on escape
7961				case 33: $.datepicker._adjustDate( event.target, ( event.ctrlKey ?
7962							-$.datepicker._get( inst, "stepBigMonths" ) :
7963							-$.datepicker._get( inst, "stepMonths" ) ), "M" );
7964						break; // previous month/year on page up/+ ctrl
7965				case 34: $.datepicker._adjustDate( event.target, ( event.ctrlKey ?
7966							+$.datepicker._get( inst, "stepBigMonths" ) :
7967							+$.datepicker._get( inst, "stepMonths" ) ), "M" );
7968						break; // next month/year on page down/+ ctrl
7969				case 35: if ( event.ctrlKey || event.metaKey ) {
7970							$.datepicker._clearDate( event.target );
7971						}
7972						handled = event.ctrlKey || event.metaKey;
7973						break; // clear on ctrl or command +end
7974				case 36: if ( event.ctrlKey || event.metaKey ) {
7975							$.datepicker._gotoToday( event.target );
7976						}
7977						handled = event.ctrlKey || event.metaKey;
7978						break; // current on ctrl or command +home
7979				case 37: if ( event.ctrlKey || event.metaKey ) {
7980							$.datepicker._adjustDate( event.target, ( isRTL ? +1 : -1 ), "D" );
7981						}
7982						handled = event.ctrlKey || event.metaKey;
7983
7984						// -1 day on ctrl or command +left
7985						if ( event.originalEvent.altKey ) {
7986							$.datepicker._adjustDate( event.target, ( event.ctrlKey ?
7987								-$.datepicker._get( inst, "stepBigMonths" ) :
7988								-$.datepicker._get( inst, "stepMonths" ) ), "M" );
7989						}
7990
7991						// next month/year on alt +left on Mac
7992						break;
7993				case 38: if ( event.ctrlKey || event.metaKey ) {
7994							$.datepicker._adjustDate( event.target, -7, "D" );
7995						}
7996						handled = event.ctrlKey || event.metaKey;
7997						break; // -1 week on ctrl or command +up
7998				case 39: if ( event.ctrlKey || event.metaKey ) {
7999							$.datepicker._adjustDate( event.target, ( isRTL ? -1 : +1 ), "D" );
8000						}
8001						handled = event.ctrlKey || event.metaKey;
8002
8003						// +1 day on ctrl or command +right
8004						if ( event.originalEvent.altKey ) {
8005							$.datepicker._adjustDate( event.target, ( event.ctrlKey ?
8006								+$.datepicker._get( inst, "stepBigMonths" ) :
8007								+$.datepicker._get( inst, "stepMonths" ) ), "M" );
8008						}
8009
8010						// next month/year on alt +right
8011						break;
8012				case 40: if ( event.ctrlKey || event.metaKey ) {
8013							$.datepicker._adjustDate( event.target, +7, "D" );
8014						}
8015						handled = event.ctrlKey || event.metaKey;
8016						break; // +1 week on ctrl or command +down
8017				default: handled = false;
8018			}
8019		} else if ( event.keyCode === 36 && event.ctrlKey ) { // display the date picker on ctrl+home
8020			$.datepicker._showDatepicker( this );
8021		} else {
8022			handled = false;
8023		}
8024
8025		if ( handled ) {
8026			event.preventDefault();
8027			event.stopPropagation();
8028		}
8029	},
8030
8031	/* Filter entered characters - based on date format. */
8032	_doKeyPress: function( event ) {
8033		var chars, chr,
8034			inst = $.datepicker._getInst( event.target );
8035
8036		if ( $.datepicker._get( inst, "constrainInput" ) ) {
8037			chars = $.datepicker._possibleChars( $.datepicker._get( inst, "dateFormat" ) );
8038			chr = String.fromCharCode( event.charCode == null ? event.keyCode : event.charCode );
8039			return event.ctrlKey || event.metaKey || ( chr < " " || !chars || chars.indexOf( chr ) > -1 );
8040		}
8041	},
8042
8043	/* Synchronise manual entry and field/alternate field. */
8044	_doKeyUp: function( event ) {
8045		var date,
8046			inst = $.datepicker._getInst( event.target );
8047
8048		if ( inst.input.val() !== inst.lastVal ) {
8049			try {
8050				date = $.datepicker.parseDate( $.datepicker._get( inst, "dateFormat" ),
8051					( inst.input ? inst.input.val() : null ),
8052					$.datepicker._getFormatConfig( inst ) );
8053
8054				if ( date ) { // only if valid
8055					$.datepicker._setDateFromField( inst );
8056					$.datepicker._updateAlternate( inst );
8057					$.datepicker._updateDatepicker( inst );
8058				}
8059			}
8060			catch ( err ) {
8061			}
8062		}
8063		return true;
8064	},
8065
8066	/* Pop-up the date picker for a given input field.
8067	 * If false returned from beforeShow event handler do not show.
8068	 * @param  input  element - the input field attached to the date picker or
vendor: 1,885 bytes, lines 8069-8126
8069	 *					event - if triggered by focus
8070	 */
8071	_showDatepicker: function( input ) {
8072		input = input.target || input;
8073		if ( input.nodeName.toLowerCase() !== "input" ) { // find from button/image trigger
8074			input = $( "input", input.parentNode )[ 0 ];
8075		}
8076
8077		if ( $.datepicker._isDisabledDatepicker( input ) || $.datepicker._lastInput === input ) { // already here
8078			return;
8079		}
8080
8081		var inst, beforeShow, beforeShowSettings, isFixed,
8082			offset, showAnim, duration;
8083
8084		inst = $.datepicker._getInst( input );
8085		if ( $.datepicker._curInst && $.datepicker._curInst !== inst ) {
8086			$.datepicker._curInst.dpDiv.stop( true, true );
8087			if ( inst && $.datepicker._datepickerShowing ) {
8088				$.datepicker._hideDatepicker( $.datepicker._curInst.input[ 0 ] );
8089			}
8090		}
8091
8092		beforeShow = $.datepicker._get( inst, "beforeShow" );
8093		beforeShowSettings = beforeShow ? beforeShow.apply( input, [ input, inst ] ) : {};
8094		if ( beforeShowSettings === false ) {
8095			return;
8096		}
8097		datepicker_extendRemove( inst.settings, beforeShowSettings );
8098
8099		inst.lastVal = null;
8100		$.datepicker._lastInput = input;
8101		$.datepicker._setDateFromField( inst );
8102
8103		if ( $.datepicker._inDialog ) { // hide cursor
8104			input.value = "";
8105		}
8106		if ( !$.datepicker._pos ) { // position below input
8107			$.datepicker._pos = $.datepicker._findPos( input );
8108			$.datepicker._pos[ 1 ] += input.offsetHeight; // add the height
8109		}
8110
8111		isFixed = false;
8112		$( input ).parents().each( function() {
8113			isFixed |= $( this ).css( "position" ) === "fixed";
8114			return !isFixed;
8115		} );
8116
8117		offset = { left: $.datepicker._pos[ 0 ], top: $.datepicker._pos[ 1 ] };
8118		$.datepicker._pos = null;
8119
8120		//to avoid flashes on Firefox
8121		inst.dpDiv.empty();
8122
8123		// determine sizing offscreen
8124		inst.dpDiv.css( { position: "absolute", display: "block", top: "-1000px" } );
8125		$.datepicker._updateDatepicker( inst );
8126
vendor: 12,837 bytes, lines 8127-8479
8127		// fix width for dynamic number of date pickers
8128		// and adjust position before showing
8129		offset = $.datepicker._checkOffset( inst, offset, isFixed );
8130		inst.dpDiv.css( { position: ( $.datepicker._inDialog && $.blockUI ?
8131			"static" : ( isFixed ? "fixed" : "absolute" ) ), display: "none",
8132			left: offset.left + "px", top: offset.top + "px" } );
8133
8134		if ( !inst.inline ) {
8135			showAnim = $.datepicker._get( inst, "showAnim" );
8136			duration = $.datepicker._get( inst, "duration" );
8137			inst.dpDiv.css( "z-index", datepicker_getZindex( $( input ) ) + 1 );
8138			$.datepicker._datepickerShowing = true;
8139
8140			if ( $.effects && $.effects.effect[ showAnim ] ) {
8141				inst.dpDiv.show( showAnim, $.datepicker._get( inst, "showOptions" ), duration );
8142			} else {
8143				inst.dpDiv[ showAnim || "show" ]( showAnim ? duration : null );
8144			}
8145
8146			if ( $.datepicker._shouldFocusInput( inst ) ) {
8147				inst.input.trigger( "focus" );
8148			}
8149
8150			$.datepicker._curInst = inst;
8151		}
8152	},
8153
8154	/* Generate the date picker content. */
8155	_updateDatepicker: function( inst ) {
8156		this.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
8157		datepicker_instActive = inst; // for delegate hover events
8158		inst.dpDiv.empty().append( this._generateHTML( inst ) );
8159		this._attachHandlers( inst );
8160
8161		var origyearshtml,
8162			numMonths = this._getNumberOfMonths( inst ),
8163			cols = numMonths[ 1 ],
8164			width = 17,
8165			activeCell = inst.dpDiv.find( "." + this._dayOverClass + " a" );
8166
8167		if ( activeCell.length > 0 ) {
8168			datepicker_handleMouseover.apply( activeCell.get( 0 ) );
8169		}
8170
8171		inst.dpDiv.removeClass( "ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4" ).width( "" );
8172		if ( cols > 1 ) {
8173			inst.dpDiv.addClass( "ui-datepicker-multi-" + cols ).css( "width", ( width * cols ) + "em" );
8174		}
8175		inst.dpDiv[ ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ? "add" : "remove" ) +
8176			"Class" ]( "ui-datepicker-multi" );
8177		inst.dpDiv[ ( this._get( inst, "isRTL" ) ? "add" : "remove" ) +
8178			"Class" ]( "ui-datepicker-rtl" );
8179
8180		if ( inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) {
8181			inst.input.trigger( "focus" );
8182		}
8183
8184		// Deffered render of the years select (to avoid flashes on Firefox)
8185		if ( inst.yearshtml ) {
8186			origyearshtml = inst.yearshtml;
8187			setTimeout( function() {
8188
8189				//assure that inst.yearshtml didn't change.
8190				if ( origyearshtml === inst.yearshtml && inst.yearshtml ) {
8191					inst.dpDiv.find( "select.ui-datepicker-year:first" ).replaceWith( inst.yearshtml );
8192				}
8193				origyearshtml = inst.yearshtml = null;
8194			}, 0 );
8195		}
8196	},
8197
8198	// #6694 - don't focus the input if it's already focused
8199	// this breaks the change event in IE
8200	// Support: IE and jQuery <1.9
8201	_shouldFocusInput: function( inst ) {
8202		return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" ) && !inst.input.is( ":focus" );
8203	},
8204
8205	/* Check positioning to remain on screen. */
8206	_checkOffset: function( inst, offset, isFixed ) {
8207		var dpWidth = inst.dpDiv.outerWidth(),
8208			dpHeight = inst.dpDiv.outerHeight(),
8209			inputWidth = inst.input ? inst.input.outerWidth() : 0,
8210			inputHeight = inst.input ? inst.input.outerHeight() : 0,
8211			viewWidth = document.documentElement.clientWidth + ( isFixed ? 0 : $( document ).scrollLeft() ),
8212			viewHeight = document.documentElement.clientHeight + ( isFixed ? 0 : $( document ).scrollTop() );
8213
8214		offset.left -= ( this._get( inst, "isRTL" ) ? ( dpWidth - inputWidth ) : 0 );
8215		offset.left -= ( isFixed && offset.left === inst.input.offset().left ) ? $( document ).scrollLeft() : 0;
8216		offset.top -= ( isFixed && offset.top === ( inst.input.offset().top + inputHeight ) ) ? $( document ).scrollTop() : 0;
8217
8218		// Now check if datepicker is showing outside window viewport - move to a better place if so.
8219		offset.left -= Math.min( offset.left, ( offset.left + dpWidth > viewWidth && viewWidth > dpWidth ) ?
8220			Math.abs( offset.left + dpWidth - viewWidth ) : 0 );
8221		offset.top -= Math.min( offset.top, ( offset.top + dpHeight > viewHeight && viewHeight > dpHeight ) ?
8222			Math.abs( dpHeight + inputHeight ) : 0 );
8223
8224		return offset;
8225	},
8226
8227	/* Find an object's position on the screen. */
8228	_findPos: function( obj ) {
8229		var position,
8230			inst = this._getInst( obj ),
8231			isRTL = this._get( inst, "isRTL" );
8232
8233		while ( obj && ( obj.type === "hidden" || obj.nodeType !== 1 || $.expr.filters.hidden( obj ) ) ) {
8234			obj = obj[ isRTL ? "previousSibling" : "nextSibling" ];
8235		}
8236
8237		position = $( obj ).offset();
8238		return [ position.left, position.top ];
8239	},
8240
8241	/* Hide the date picker from view.
8242	 * @param  input  element - the input field attached to the date picker
8243	 */
8244	_hideDatepicker: function( input ) {
8245		var showAnim, duration, postProcess, onClose,
8246			inst = this._curInst;
8247
8248		if ( !inst || ( input && inst !== $.data( input, "datepicker" ) ) ) {
8249			return;
8250		}
8251
8252		if ( this._datepickerShowing ) {
8253			showAnim = this._get( inst, "showAnim" );
8254			duration = this._get( inst, "duration" );
8255			postProcess = function() {
8256				$.datepicker._tidyDialog( inst );
8257			};
8258
8259			// DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed
8260			if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) {
8261				inst.dpDiv.hide( showAnim, $.datepicker._get( inst, "showOptions" ), duration, postProcess );
8262			} else {
8263				inst.dpDiv[ ( showAnim === "slideDown" ? "slideUp" :
8264					( showAnim === "fadeIn" ? "fadeOut" : "hide" ) ) ]( ( showAnim ? duration : null ), postProcess );
8265			}
8266
8267			if ( !showAnim ) {
8268				postProcess();
8269			}
8270			this._datepickerShowing = false;
8271
8272			onClose = this._get( inst, "onClose" );
8273			if ( onClose ) {
8274				onClose.apply( ( inst.input ? inst.input[ 0 ] : null ), [ ( inst.input ? inst.input.val() : "" ), inst ] );
8275			}
8276
8277			this._lastInput = null;
8278			if ( this._inDialog ) {
8279				this._dialogInput.css( { position: "absolute", left: "0", top: "-100px" } );
8280				if ( $.blockUI ) {
8281					$.unblockUI();
8282					$( "body" ).append( this.dpDiv );
8283				}
8284			}
8285			this._inDialog = false;
8286		}
8287	},
8288
8289	/* Tidy up after a dialog display. */
8290	_tidyDialog: function( inst ) {
8291		inst.dpDiv.removeClass( this._dialogClass ).off( ".ui-datepicker-calendar" );
8292	},
8293
8294	/* Close date picker if clicked elsewhere. */
8295	_checkExternalClick: function( event ) {
8296		if ( !$.datepicker._curInst ) {
8297			return;
8298		}
8299
8300		var $target = $( event.target ),
8301			inst = $.datepicker._getInst( $target[ 0 ] );
8302
8303		if ( ( ( $target[ 0 ].id !== $.datepicker._mainDivId &&
8304				$target.parents( "#" + $.datepicker._mainDivId ).length === 0 &&
8305				!$target.hasClass( $.datepicker.markerClassName ) &&
8306				!$target.closest( "." + $.datepicker._triggerClass ).length &&
8307				$.datepicker._datepickerShowing && !( $.datepicker._inDialog && $.blockUI ) ) ) ||
8308			( $target.hasClass( $.datepicker.markerClassName ) && $.datepicker._curInst !== inst ) ) {
8309				$.datepicker._hideDatepicker();
8310		}
8311	},
8312
8313	/* Adjust one of the date sub-fields. */
8314	_adjustDate: function( id, offset, period ) {
8315		var target = $( id ),
8316			inst = this._getInst( target[ 0 ] );
8317
8318		if ( this._isDisabledDatepicker( target[ 0 ] ) ) {
8319			return;
8320		}
8321		this._adjustInstDate( inst, offset +
8322			( period === "M" ? this._get( inst, "showCurrentAtPos" ) : 0 ), // undo positioning
8323			period );
8324		this._updateDatepicker( inst );
8325	},
8326
8327	/* Action for current link. */
8328	_gotoToday: function( id ) {
8329		var date,
8330			target = $( id ),
8331			inst = this._getInst( target[ 0 ] );
8332
8333		if ( this._get( inst, "gotoCurrent" ) && inst.currentDay ) {
8334			inst.selectedDay = inst.currentDay;
8335			inst.drawMonth = inst.selectedMonth = inst.currentMonth;
8336			inst.drawYear = inst.selectedYear = inst.currentYear;
8337		} else {
8338			date = new Date();
8339			inst.selectedDay = date.getDate();
8340			inst.drawMonth = inst.selectedMonth = date.getMonth();
8341			inst.drawYear = inst.selectedYear = date.getFullYear();
8342		}
8343		this._notifyChange( inst );
8344		this._adjustDate( target );
8345	},
8346
8347	/* Action for selecting a new month/year. */
8348	_selectMonthYear: function( id, select, period ) {
8349		var target = $( id ),
8350			inst = this._getInst( target[ 0 ] );
8351
8352		inst[ "selected" + ( period === "M" ? "Month" : "Year" ) ] =
8353		inst[ "draw" + ( period === "M" ? "Month" : "Year" ) ] =
8354			parseInt( select.options[ select.selectedIndex ].value, 10 );
8355
8356		this._notifyChange( inst );
8357		this._adjustDate( target );
8358	},
8359
8360	/* Action for selecting a day. */
8361	_selectDay: function( id, month, year, td ) {
8362		var inst,
8363			target = $( id );
8364
8365		if ( $( td ).hasClass( this._unselectableClass ) || this._isDisabledDatepicker( target[ 0 ] ) ) {
8366			return;
8367		}
8368
8369		inst = this._getInst( target[ 0 ] );
8370		inst.selectedDay = inst.currentDay = $( "a", td ).html();
8371		inst.selectedMonth = inst.currentMonth = month;
8372		inst.selectedYear = inst.currentYear = year;
8373		this._selectDate( id, this._formatDate( inst,
8374			inst.currentDay, inst.currentMonth, inst.currentYear ) );
8375	},
8376
8377	/* Erase the input field and hide the date picker. */
8378	_clearDate: function( id ) {
8379		var target = $( id );
8380		this._selectDate( target, "" );
8381	},
8382
8383	/* Update the input field with the selected date. */
8384	_selectDate: function( id, dateStr ) {
8385		var onSelect,
8386			target = $( id ),
8387			inst = this._getInst( target[ 0 ] );
8388
8389		dateStr = ( dateStr != null ? dateStr : this._formatDate( inst ) );
8390		if ( inst.input ) {
8391			inst.input.val( dateStr );
8392		}
8393		this._updateAlternate( inst );
8394
8395		onSelect = this._get( inst, "onSelect" );
8396		if ( onSelect ) {
8397			onSelect.apply( ( inst.input ? inst.input[ 0 ] : null ), [ dateStr, inst ] );  // trigger custom callback
8398		} else if ( inst.input ) {
8399			inst.input.trigger( "change" ); // fire the change event
8400		}
8401
8402		if ( inst.inline ) {
8403			this._updateDatepicker( inst );
8404		} else {
8405			this._hideDatepicker();
8406			this._lastInput = inst.input[ 0 ];
8407			if ( typeof( inst.input[ 0 ] ) !== "object" ) {
8408				inst.input.trigger( "focus" ); // restore focus
8409			}
8410			this._lastInput = null;
8411		}
8412	},
8413
8414	/* Update any alternate field to synchronise with the main field. */
8415	_updateAlternate: function( inst ) {
8416		var altFormat, date, dateStr,
8417			altField = this._get( inst, "altField" );
8418
8419		if ( altField ) { // update alternate field too
8420			altFormat = this._get( inst, "altFormat" ) || this._get( inst, "dateFormat" );
8421			date = this._getDate( inst );
8422			dateStr = this.formatDate( altFormat, date, this._getFormatConfig( inst ) );
8423			$( altField ).val( dateStr );
8424		}
8425	},
8426
8427	/* Set as beforeShowDay function to prevent selection of weekends.
8428	 * @param  date  Date - the date to customise
8429	 * @return [boolean, string] - is this date selectable?, what is its CSS class?
8430	 */
8431	noWeekends: function( date ) {
8432		var day = date.getDay();
8433		return [ ( day > 0 && day < 6 ), "" ];
8434	},
8435
8436	/* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
8437	 * @param  date  Date - the date to get the week for
8438	 * @return  number - the number of the week within the year that contains this date
8439	 */
8440	iso8601Week: function( date ) {
8441		var time,
8442			checkDate = new Date( date.getTime() );
8443
8444		// Find Thursday of this week starting on Monday
8445		checkDate.setDate( checkDate.getDate() + 4 - ( checkDate.getDay() || 7 ) );
8446
8447		time = checkDate.getTime();
8448		checkDate.setMonth( 0 ); // Compare with Jan 1
8449		checkDate.setDate( 1 );
8450		return Math.floor( Math.round( ( time - checkDate ) / 86400000 ) / 7 ) + 1;
8451	},
8452
8453	/* Parse a string value into a date object.
8454	 * See formatDate below for the possible formats.
8455	 *
8456	 * @param  format string - the expected format of the date
8457	 * @param  value string - the date in the above format
8458	 * @param  settings Object - attributes include:
8459	 *					shortYearCutoff  number - the cutoff year for determining the century (optional)
8460	 *					dayNamesShort	string[7] - abbreviated names of the days from Sunday (optional)
8461	 *					dayNames		string[7] - names of the days from Sunday (optional)
8462	 *					monthNamesShort string[12] - abbreviated names of the months (optional)
8463	 *					monthNames		string[12] - names of the months (optional)
8464	 * @return  Date - the extracted date value or null if value is blank
8465	 */
8466	parseDate: function( format, value, settings ) {
8467		if ( format == null || value == null ) {
8468			throw "Invalid arguments";
8469		}
8470
8471		value = ( typeof value === "object" ? value.toString() : value + "" );
8472		if ( value === "" ) {
8473			return null;
8474		}
8475
8476		var iFormat, dim, extra,
8477			iValue = 0,
8478			shortYearCutoffTemp = ( settings ? settings.shortYearCutoff : null ) || this._defaults.shortYearCutoff,
8479			shortYearCutoff = ( typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp 
vendor: 15,177 bytes, lines 8479-8955
8479:
8480				new Date().getFullYear() % 100 + parseInt( shortYearCutoffTemp, 10 ) ),
8481			dayNamesShort = ( settings ? settings.dayNamesShort : null ) || this._defaults.dayNamesShort,
8482			dayNames = ( settings ? settings.dayNames : null ) || this._defaults.dayNames,
8483			monthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort,
8484			monthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames,
8485			year = -1,
8486			month = -1,
8487			day = -1,
8488			doy = -1,
8489			literal = false,
8490			date,
8491
8492			// Check whether a format character is doubled
8493			lookAhead = function( match ) {
8494				var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );
8495				if ( matches ) {
8496					iFormat++;
8497				}
8498				return matches;
8499			},
8500
8501			// Extract a number from the string value
8502			getNumber = function( match ) {
8503				var isDoubled = lookAhead( match ),
8504					size = ( match === "@" ? 14 : ( match === "!" ? 20 :
8505					( match === "y" && isDoubled ? 4 : ( match === "o" ? 3 : 2 ) ) ) ),
8506					minSize = ( match === "y" ? size : 1 ),
8507					digits = new RegExp( "^\\d{" + minSize + "," + size + "}" ),
8508					num = value.substring( iValue ).match( digits );
8509				if ( !num ) {
8510					throw "Missing number at position " + iValue;
8511				}
8512				iValue += num[ 0 ].length;
8513				return parseInt( num[ 0 ], 10 );
8514			},
8515
8516			// Extract a name from the string value and convert to an index
8517			getName = function( match, shortNames, longNames ) {
8518				var index = -1,
8519					names = $.map( lookAhead( match ) ? longNames : shortNames, function( v, k ) {
8520						return [ [ k, v ] ];
8521					} ).sort( function( a, b ) {
8522						return -( a[ 1 ].length - b[ 1 ].length );
8523					} );
8524
8525				$.each( names, function( i, pair ) {
8526					var name = pair[ 1 ];
8527					if ( value.substr( iValue, name.length ).toLowerCase() === name.toLowerCase() ) {
8528						index = pair[ 0 ];
8529						iValue += name.length;
8530						return false;
8531					}
8532				} );
8533				if ( index !== -1 ) {
8534					return index + 1;
8535				} else {
8536					throw "Unknown name at position " + iValue;
8537				}
8538			},
8539
8540			// Confirm that a literal character matches the string value
8541			checkLiteral = function() {
8542				if ( value.charAt( iValue ) !== format.charAt( iFormat ) ) {
8543					throw "Unexpected literal at position " + iValue;
8544				}
8545				iValue++;
8546			};
8547
8548		for ( iFormat = 0; iFormat < format.length; iFormat++ ) {
8549			if ( literal ) {
8550				if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) {
8551					literal = false;
8552				} else {
8553					checkLiteral();
8554				}
8555			} else {
8556				switch ( format.charAt( iFormat ) ) {
8557					case "d":
8558						day = getNumber( "d" );
8559						break;
8560					case "D":
8561						getName( "D", dayNamesShort, dayNames );
8562						break;
8563					case "o":
8564						doy = getNumber( "o" );
8565						break;
8566					case "m":
8567						month = getNumber( "m" );
8568						break;
8569					case "M":
8570						month = getName( "M", monthNamesShort, monthNames );
8571						break;
8572					case "y":
8573						year = getNumber( "y" );
8574						break;
8575					case "@":
8576						date = new Date( getNumber( "@" ) );
8577						year = date.getFullYear();
8578						month = date.getMonth() + 1;
8579						day = date.getDate();
8580						break;
8581					case "!":
8582						date = new Date( ( getNumber( "!" ) - this._ticksTo1970 ) / 10000 );
8583						year = date.getFullYear();
8584						month = date.getMonth() + 1;
8585						day = date.getDate();
8586						break;
8587					case "'":
8588						if ( lookAhead( "'" ) ) {
8589							checkLiteral();
8590						} else {
8591							literal = true;
8592						}
8593						break;
8594					default:
8595						checkLiteral();
8596				}
8597			}
8598		}
8599
8600		if ( iValue < value.length ) {
8601			extra = value.substr( iValue );
8602			if ( !/^\s+/.test( extra ) ) {
8603				throw "Extra/unparsed characters found in date: " + extra;
8604			}
8605		}
8606
8607		if ( year === -1 ) {
8608			year = new Date().getFullYear();
8609		} else if ( year < 100 ) {
8610			year += new Date().getFullYear() - new Date().getFullYear() % 100 +
8611				( year <= shortYearCutoff ? 0 : -100 );
8612		}
8613
8614		if ( doy > -1 ) {
8615			month = 1;
8616			day = doy;
8617			do {
8618				dim = this._getDaysInMonth( year, month - 1 );
8619				if ( day <= dim ) {
8620					break;
8621				}
8622				month++;
8623				day -= dim;
8624			} while ( true );
8625		}
8626
8627		date = this._daylightSavingAdjust( new Date( year, month - 1, day ) );
8628		if ( date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day ) {
8629			throw "Invalid date"; // E.g. 31/02/00
8630		}
8631		return date;
8632	},
8633
8634	/* Standard date formats. */
8635	ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601)
8636	COOKIE: "D, dd M yy",
8637	ISO_8601: "yy-mm-dd",
8638	RFC_822: "D, d M y",
8639	RFC_850: "DD, dd-M-y",
8640	RFC_1036: "D, d M y",
8641	RFC_1123: "D, d M yy",
8642	RFC_2822: "D, d M yy",
8643	RSS: "D, d M y", // RFC 822
8644	TICKS: "!",
8645	TIMESTAMP: "@",
8646	W3C: "yy-mm-dd", // ISO 8601
8647
8648	_ticksTo1970: ( ( ( 1970 - 1 ) * 365 + Math.floor( 1970 / 4 ) - Math.floor( 1970 / 100 ) +
8649		Math.floor( 1970 / 400 ) ) * 24 * 60 * 60 * 10000000 ),
8650
8651	/* Format a date object into a string value.
8652	 * The format can be combinations of the following:
8653	 * d  - day of month (no leading zero)
8654	 * dd - day of month (two digit)
8655	 * o  - day of year (no leading zeros)
8656	 * oo - day of year (three digit)
8657	 * D  - day name short
8658	 * DD - day name long
8659	 * m  - month of year (no leading zero)
8660	 * mm - month of year (two digit)
8661	 * M  - month name short
8662	 * MM - month name long
8663	 * y  - year (two digit)
8664	 * yy - year (four digit)
8665	 * @ - Unix timestamp (ms since 01/01/1970)
8666	 * ! - Windows ticks (100ns since 01/01/0001)
8667	 * "..." - literal text
8668	 * '' - single quote
8669	 *
8670	 * @param  format string - the desired format of the date
8671	 * @param  date Date - the date value to format
8672	 * @param  settings Object - attributes include:
8673	 *					dayNamesShort	string[7] - abbreviated names of the days from Sunday (optional)
8674	 *					dayNames		string[7] - names of the days from Sunday (optional)
8675	 *					monthNamesShort string[12] - abbreviated names of the months (optional)
8676	 *					monthNames		string[12] - names of the months (optional)
8677	 * @return  string - the date in the above format
8678	 */
8679	formatDate: function( format, date, settings ) {
8680		if ( !date ) {
8681			return "";
8682		}
8683
8684		var iFormat,
8685			dayNamesShort = ( settings ? settings.dayNamesShort : null ) || this._defaults.dayNamesShort,
8686			dayNames = ( settings ? settings.dayNames : null ) || this._defaults.dayNames,
8687			monthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort,
8688			monthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames,
8689
8690			// Check whether a format character is doubled
8691			lookAhead = function( match ) {
8692				var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );
8693				if ( matches ) {
8694					iFormat++;
8695				}
8696				return matches;
8697			},
8698
8699			// Format a number, with leading zero if necessary
8700			formatNumber = function( match, value, len ) {
8701				var num = "" + value;
8702				if ( lookAhead( match ) ) {
8703					while ( num.length < len ) {
8704						num = "0" + num;
8705					}
8706				}
8707				return num;
8708			},
8709
8710			// Format a name, short or long as requested
8711			formatName = function( match, value, shortNames, longNames ) {
8712				return ( lookAhead( match ) ? longNames[ value ] : shortNames[ value ] );
8713			},
8714			output = "",
8715			literal = false;
8716
8717		if ( date ) {
8718			for ( iFormat = 0; iFormat < format.length; iFormat++ ) {
8719				if ( literal ) {
8720					if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) {
8721						literal = false;
8722					} else {
8723						output += format.charAt( iFormat );
8724					}
8725				} else {
8726					switch ( format.charAt( iFormat ) ) {
8727						case "d":
8728							output += formatNumber( "d", date.getDate(), 2 );
8729							break;
8730						case "D":
8731							output += formatName( "D", date.getDay(), dayNamesShort, dayNames );
8732							break;
8733						case "o":
8734							output += formatNumber( "o",
8735								Math.round( ( new Date( date.getFullYear(), date.getMonth(), date.getDate() ).getTime() - new Date( date.getFullYear(), 0, 0 ).getTime() ) / 86400000 ), 3 );
8736							break;
8737						case "m":
8738							output += formatNumber( "m", date.getMonth() + 1, 2 );
8739							break;
8740						case "M":
8741							output += formatName( "M", date.getMonth(), monthNamesShort, monthNames );
8742							break;
8743						case "y":
8744							output += ( lookAhead( "y" ) ? date.getFullYear() :
8745								( date.getFullYear() % 100 < 10 ? "0" : "" ) + date.getFullYear() % 100 );
8746							break;
8747						case "@":
8748							output += date.getTime();
8749							break;
8750						case "!":
8751							output += date.getTime() * 10000 + this._ticksTo1970;
8752							break;
8753						case "'":
8754							if ( lookAhead( "'" ) ) {
8755								output += "'";
8756							} else {
8757								literal = true;
8758							}
8759							break;
8760						default:
8761							output += format.charAt( iFormat );
8762					}
8763				}
8764			}
8765		}
8766		return output;
8767	},
8768
8769	/* Extract all possible characters from the date format. */
8770	_possibleChars: function( format ) {
8771		var iFormat,
8772			chars = "",
8773			literal = false,
8774
8775			// Check whether a format character is doubled
8776			lookAhead = function( match ) {
8777				var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );
8778				if ( matches ) {
8779					iFormat++;
8780				}
8781				return matches;
8782			};
8783
8784		for ( iFormat = 0; iFormat < format.length; iFormat++ ) {
8785			if ( literal ) {
8786				if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) {
8787					literal = false;
8788				} else {
8789					chars += format.charAt( iFormat );
8790				}
8791			} else {
8792				switch ( format.charAt( iFormat ) ) {
8793					case "d": case "m": case "y": case "@":
8794						chars += "0123456789";
8795						break;
8796					case "D": case "M":
8797						return null; // Accept anything
8798					case "'":
8799						if ( lookAhead( "'" ) ) {
8800							chars += "'";
8801						} else {
8802							literal = true;
8803						}
8804						break;
8805					default:
8806						chars += format.charAt( iFormat );
8807				}
8808			}
8809		}
8810		return chars;
8811	},
8812
8813	/* Get a setting value, defaulting if necessary. */
8814	_get: function( inst, name ) {
8815		return inst.settings[ name ] !== undefined ?
8816			inst.settings[ name ] : this._defaults[ name ];
8817	},
8818
8819	/* Parse existing date and initialise date picker. */
8820	_setDateFromField: function( inst, noDefault ) {
8821		if ( inst.input.val() === inst.lastVal ) {
8822			return;
8823		}
8824
8825		var dateFormat = this._get( inst, "dateFormat" ),
8826			dates = inst.lastVal = inst.input ? inst.input.val() : null,
8827			defaultDate = this._getDefaultDate( inst ),
8828			date = defaultDate,
8829			settings = this._getFormatConfig( inst );
8830
8831		try {
8832			date = this.parseDate( dateFormat, dates, settings ) || defaultDate;
8833		} catch ( event ) {
8834			dates = ( noDefault ? "" : dates );
8835		}
8836		inst.selectedDay = date.getDate();
8837		inst.drawMonth = inst.selectedMonth = date.getMonth();
8838		inst.drawYear = inst.selectedYear = date.getFullYear();
8839		inst.currentDay = ( dates ? date.getDate() : 0 );
8840		inst.currentMonth = ( dates ? date.getMonth() : 0 );
8841		inst.currentYear = ( dates ? date.getFullYear() : 0 );
8842		this._adjustInstDate( inst );
8843	},
8844
8845	/* Retrieve the default date shown on opening. */
8846	_getDefaultDate: function( inst ) {
8847		return this._restrictMinMax( inst,
8848			this._determineDate( inst, this._get( inst, "defaultDate" ), new Date() ) );
8849	},
8850
8851	/* A date may be specified as an exact value or a relative one. */
8852	_determineDate: function( inst, date, defaultDate ) {
8853		var offsetNumeric = function( offset ) {
8854				var date = new Date();
8855				date.setDate( date.getDate() + offset );
8856				return date;
8857			},
8858			offsetString = function( offset ) {
8859				try {
8860					return $.datepicker.parseDate( $.datepicker._get( inst, "dateFormat" ),
8861						offset, $.datepicker._getFormatConfig( inst ) );
8862				}
8863				catch ( e ) {
8864
8865					// Ignore
8866				}
8867
8868				var date = ( offset.toLowerCase().match( /^c/ ) ?
8869					$.datepicker._getDate( inst ) : null ) || new Date(),
8870					year = date.getFullYear(),
8871					month = date.getMonth(),
8872					day = date.getDate(),
8873					pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,
8874					matches = pattern.exec( offset );
8875
8876				while ( matches ) {
8877					switch ( matches[ 2 ] || "d" ) {
8878						case "d" : case "D" :
8879							day += parseInt( matches[ 1 ], 10 ); break;
8880						case "w" : case "W" :
8881							day += parseInt( matches[ 1 ], 10 ) * 7; break;
8882						case "m" : case "M" :
8883							month += parseInt( matches[ 1 ], 10 );
8884							day = Math.min( day, $.datepicker._getDaysInMonth( year, month ) );
8885							break;
8886						case "y": case "Y" :
8887							year += parseInt( matches[ 1 ], 10 );
8888							day = Math.min( day, $.datepicker._getDaysInMonth( year, month ) );
8889							break;
8890					}
8891					matches = pattern.exec( offset );
8892				}
8893				return new Date( year, month, day );
8894			},
8895			newDate = ( date == null || date === "" ? defaultDate : ( typeof date === "string" ? offsetString( date ) :
8896				( typeof date === "number" ? ( isNaN( date ) ? defaultDate : offsetNumeric( date ) ) : new Date( date.getTime() ) ) ) );
8897
8898		newDate = ( newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate );
8899		if ( newDate ) {
8900			newDate.setHours( 0 );
8901			newDate.setMinutes( 0 );
8902			newDate.setSeconds( 0 );
8903			newDate.setMilliseconds( 0 );
8904		}
8905		return this._daylightSavingAdjust( newDate );
8906	},
8907
8908	/* Handle switch to/from daylight saving.
8909	 * Hours may be non-zero on daylight saving cut-over:
8910	 * > 12 when midnight changeover, but then cannot generate
8911	 * midnight datetime, so jump to 1AM, otherwise reset.
8912	 * @param  date  (Date) the date to check
8913	 * @return  (Date) the corrected date
8914	 */
8915	_daylightSavingAdjust: function( date ) {
8916		if ( !date ) {
8917			return null;
8918		}
8919		date.setHours( date.getHours() > 12 ? date.getHours() + 2 : 0 );
8920		return date;
8921	},
8922
8923	/* Set the date(s) directly. */
8924	_setDate: function( inst, date, noChange ) {
8925		var clear = !date,
8926			origMonth = inst.selectedMonth,
8927			origYear = inst.selectedYear,
8928			newDate = this._restrictMinMax( inst, this._determineDate( inst, date, new Date() ) );
8929
8930		inst.selectedDay = inst.currentDay = newDate.getDate();
8931		inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
8932		inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
8933		if ( ( origMonth !== inst.selectedMonth || origYear !== inst.selectedYear ) && !noChange ) {
8934			this._notifyChange( inst );
8935		}
8936		this._adjustInstDate( inst );
8937		if ( inst.input ) {
8938			inst.input.val( clear ? "" : this._formatDate( inst ) );
8939		}
8940	},
8941
8942	/* Retrieve the date(s) directly. */
8943	_getDate: function( inst ) {
8944		var startDate = ( !inst.currentYear || ( inst.input && inst.input.val() === "" ) ? null :
8945			this._daylightSavingAdjust( new Date(
8946			inst.currentYear, inst.currentMonth, inst.currentDay ) ) );
8947			return startDate;
8948	},
8949
8950	/* Attach the onxxx handlers.  These are declared statically so
8951	 * they work with static code transformers like Caja.
8952	 */
8953	_attachHandlers: function( inst ) {
8954		var stepMonths = this._get( inst, "stepMonths" ),
8955			id = "#" + inst.id.replace( /\\\\/g, "\\" );
vendor: 48,709 bytes, lines 8956-10446
8956		inst.dpDiv.find( "[data-handler]" ).map( function() {
8957			var handler = {
8958				prev: function() {
8959					$.datepicker._adjustDate( id, -stepMonths, "M" );
8960				},
8961				next: function() {
8962					$.datepicker._adjustDate( id, +stepMonths, "M" );
8963				},
8964				hide: function() {
8965					$.datepicker._hideDatepicker();
8966				},
8967				today: function() {
8968					$.datepicker._gotoToday( id );
8969				},
8970				selectDay: function() {
8971					$.datepicker._selectDay( id, +this.getAttribute( "data-month" ), +this.getAttribute( "data-year" ), this );
8972					return false;
8973				},
8974				selectMonth: function() {
8975					$.datepicker._selectMonthYear( id, this, "M" );
8976					return false;
8977				},
8978				selectYear: function() {
8979					$.datepicker._selectMonthYear( id, this, "Y" );
8980					return false;
8981				}
8982			};
8983			$( this ).on( this.getAttribute( "data-event" ), handler[ this.getAttribute( "data-handler" ) ] );
8984		} );
8985	},
8986
8987	/* Generate the HTML for the current state of the date picker. */
8988	_generateHTML: function( inst ) {
8989		var maxDraw, prevText, prev, nextText, next, currentText, gotoDate,
8990			controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin,
8991			monthNames, monthNamesShort, beforeShowDay, showOtherMonths,
8992			selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate,
8993			cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows,
8994			printDate, dRow, tbody, daySettings, otherMonth, unselectable,
8995			tempDate = new Date(),
8996			today = this._daylightSavingAdjust(
8997				new Date( tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate() ) ), // clear time
8998			isRTL = this._get( inst, "isRTL" ),
8999			showButtonPanel = this._get( inst, "showButtonPanel" ),
9000			hideIfNoPrevNext = this._get( inst, "hideIfNoPrevNext" ),
9001			navigationAsDateFormat = this._get( inst, "navigationAsDateFormat" ),
9002			numMonths = this._getNumberOfMonths( inst ),
9003			showCurrentAtPos = this._get( inst, "showCurrentAtPos" ),
9004			stepMonths = this._get( inst, "stepMonths" ),
9005			isMultiMonth = ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ),
9006			currentDate = this._daylightSavingAdjust( ( !inst.currentDay ? new Date( 9999, 9, 9 ) :
9007				new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) ),
9008			minDate = this._getMinMaxDate( inst, "min" ),
9009			maxDate = this._getMinMaxDate( inst, "max" ),
9010			drawMonth = inst.drawMonth - showCurrentAtPos,
9011			drawYear = inst.drawYear;
9012
9013		if ( drawMonth < 0 ) {
9014			drawMonth += 12;
9015			drawYear--;
9016		}
9017		if ( maxDate ) {
9018			maxDraw = this._daylightSavingAdjust( new Date( maxDate.getFullYear(),
9019				maxDate.getMonth() - ( numMonths[ 0 ] * numMonths[ 1 ] ) + 1, maxDate.getDate() ) );
9020			maxDraw = ( minDate && maxDraw < minDate ? minDate : maxDraw );
9021			while ( this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 ) ) > maxDraw ) {
9022				drawMonth--;
9023				if ( drawMonth < 0 ) {
9024					drawMonth = 11;
9025					drawYear--;
9026				}
9027			}
9028		}
9029		inst.drawMonth = drawMonth;
9030		inst.drawYear = drawYear;
9031
9032		prevText = this._get( inst, "prevText" );
9033		prevText = ( !navigationAsDateFormat ? prevText : this.formatDate( prevText,
9034			this._daylightSavingAdjust( new Date( drawYear, drawMonth - stepMonths, 1 ) ),
9035			this._getFormatConfig( inst ) ) );
9036
9037		prev = ( this._canAdjustMonth( inst, -1, drawYear, drawMonth ) ?
9038			"<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click'" +
9039			" title='" + prevText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w" ) + "'>" + prevText + "</span></a>" :
9040			( hideIfNoPrevNext ? "" : "<a class='ui-datepicker-prev ui-corner-all ui-state-disabled' title='" + prevText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w" ) + "'>" + prevText + "</span></a>" ) );
9041
9042		nextText = this._get( inst, "nextText" );
9043		nextText = ( !navigationAsDateFormat ? nextText : this.formatDate( nextText,
9044			this._daylightSavingAdjust( new Date( drawYear, drawMonth + stepMonths, 1 ) ),
9045			this._getFormatConfig( inst ) ) );
9046
9047		next = ( this._canAdjustMonth( inst, +1, drawYear, drawMonth ) ?
9048			"<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click'" +
9049			" title='" + nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e" ) + "'>" + nextText + "</span></a>" :
9050			( hideIfNoPrevNext ? "" : "<a class='ui-datepicker-next ui-corner-all ui-state-disabled' title='" + nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e" ) + "'>" + nextText + "</span></a>" ) );
9051
9052		currentText = this._get( inst, "currentText" );
9053		gotoDate = ( this._get( inst, "gotoCurrent" ) && inst.currentDay ? currentDate : today );
9054		currentText = ( !navigationAsDateFormat ? currentText :
9055			this.formatDate( currentText, gotoDate, this._getFormatConfig( inst ) ) );
9056
9057		controls = ( !inst.inline ? "<button type='button' class='ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all' data-handler='hide' data-event='click'>" +
9058			this._get( inst, "closeText" ) + "</button>" : "" );
9059
9060		buttonPanel = ( showButtonPanel ) ? "<div class='ui-datepicker-buttonpane ui-widget-content'>" + ( isRTL ? controls : "" ) +
9061			( this._isInRange( inst, gotoDate ) ? "<button type='button' class='ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all' data-handler='today' data-event='click'" +
9062			">" + currentText + "</button>" : "" ) + ( isRTL ? "" : controls ) + "</div>" : "";
9063
9064		firstDay = parseInt( this._get( inst, "firstDay" ), 10 );
9065		firstDay = ( isNaN( firstDay ) ? 0 : firstDay );
9066
9067		showWeek = this._get( inst, "showWeek" );
9068		dayNames = this._get( inst, "dayNames" );
9069		dayNamesMin = this._get( inst, "dayNamesMin" );
9070		monthNames = this._get( inst, "monthNames" );
9071		monthNamesShort = this._get( inst, "monthNamesShort" );
9072		beforeShowDay = this._get( inst, "beforeShowDay" );
9073		showOtherMonths = this._get( inst, "showOtherMonths" );
9074		selectOtherMonths = this._get( inst, "selectOtherMonths" );
9075		defaultDate = this._getDefaultDate( inst );
9076		html = "";
9077
9078		for ( row = 0; row < numMonths[ 0 ]; row++ ) {
9079			group = "";
9080			this.maxRows = 4;
9081			for ( col = 0; col < numMonths[ 1 ]; col++ ) {
9082				selectedDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, inst.selectedDay ) );
9083				cornerClass = " ui-corner-all";
9084				calender = "";
9085				if ( isMultiMonth ) {
9086					calender += "<div class='ui-datepicker-group";
9087					if ( numMonths[ 1 ] > 1 ) {
9088						switch ( col ) {
9089							case 0: calender += " ui-datepicker-group-first";
9090								cornerClass = " ui-corner-" + ( isRTL ? "right" : "left" ); break;
9091							case numMonths[ 1 ] - 1: calender += " ui-datepicker-group-last";
9092								cornerClass = " ui-corner-" + ( isRTL ? "left" : "right" ); break;
9093							default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break;
9094						}
9095					}
9096					calender += "'>";
9097				}
9098				calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" +
9099					( /all|left/.test( cornerClass ) && row === 0 ? ( isRTL ? next : prev ) : "" ) +
9100					( /all|right/.test( cornerClass ) && row === 0 ? ( isRTL ? prev : next ) : "" ) +
9101					this._generateMonthYearHeader( inst, drawMonth, drawYear, minDate, maxDate,
9102					row > 0 || col > 0, monthNames, monthNamesShort ) + // draw month headers
9103					"</div><table class='ui-datepicker-calendar'><thead>" +
9104					"<tr>";
9105				thead = ( showWeek ? "<th class='ui-datepicker-week-col'>" + this._get( inst, "weekHeader" ) + "</th>" : "" );
9106				for ( dow = 0; dow < 7; dow++ ) { // days of the week
9107					day = ( dow + firstDay ) % 7;
9108					thead += "<th scope='col'" + ( ( dow + firstDay + 6 ) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "" ) + ">" +
9109						"<span title='" + dayNames[ day ] + "'>" + dayNamesMin[ day ] + "</span></th>";
9110				}
9111				calender += thead + "</tr></thead><tbody>";
9112				daysInMonth = this._getDaysInMonth( drawYear, drawMonth );
9113				if ( drawYear === inst.selectedYear && drawMonth === inst.selectedMonth ) {
9114					inst.selectedDay = Math.min( inst.selectedDay, daysInMonth );
9115				}
9116				leadDays = ( this._getFirstDayOfMonth( drawYear, drawMonth ) - firstDay + 7 ) % 7;
9117				curRows = Math.ceil( ( leadDays + daysInMonth ) / 7 ); // calculate the number of rows to generate
9118				numRows = ( isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows ); //If multiple months, use the higher number of rows (see #7043)
9119				this.maxRows = numRows;
9120				printDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 - leadDays ) );
9121				for ( dRow = 0; dRow < numRows; dRow++ ) { // create date picker rows
9122					calender += "<tr>";
9123					tbody = ( !showWeek ? "" : "<td class='ui-datepicker-week-col'>" +
9124						this._get( inst, "calculateWeek" )( printDate ) + "</td>" );
9125					for ( dow = 0; dow < 7; dow++ ) { // create date picker days
9126						daySettings = ( beforeShowDay ?
9127							beforeShowDay.apply( ( inst.input ? inst.input[ 0 ] : null ), [ printDate ] ) : [ true, "" ] );
9128						otherMonth = ( printDate.getMonth() !== drawMonth );
9129						unselectable = ( otherMonth && !selectOtherMonths ) || !daySettings[ 0 ] ||
9130							( minDate && printDate < minDate ) || ( maxDate && printDate > maxDate );
9131						tbody += "<td class='" +
9132							( ( dow + firstDay + 6 ) % 7 >= 5 ? " ui-datepicker-week-end" : "" ) + // highlight weekends
9133							( otherMonth ? " ui-datepicker-other-month" : "" ) + // highlight days from other months
9134							( ( printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent ) || // user pressed key
9135							( defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime() ) ?
9136
9137							// or defaultDate is current printedDate and defaultDate is selectedDate
9138							" " + this._dayOverClass : "" ) + // highlight selected day
9139							( unselectable ? " " + this._unselectableClass + " ui-state-disabled" : "" ) +  // highlight unselectable days
9140							( otherMonth && !showOtherMonths ? "" : " " + daySettings[ 1 ] + // highlight custom dates
9141							( printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "" ) + // highlight selected day
9142							( printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "" ) ) + "'" + // highlight today (if different)
9143							( ( !otherMonth || showOtherMonths ) && daySettings[ 2 ] ? " title='" + daySettings[ 2 ].replace( /'/g, "&#39;" ) + "'" : "" ) + // cell title
9144							( unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'" ) + ">" + // actions
9145							( otherMonth && !showOtherMonths ? "&#xa0;" : // display for other months
9146							( unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" +
9147							( printDate.getTime() === today.getTime() ? " ui-state-highlight" : "" ) +
9148							( printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "" ) + // highlight selected day
9149							( otherMonth ? " ui-priority-secondary" : "" ) + // distinguish dates from other months
9150							"' href='#'>" + printDate.getDate() + "</a>" ) ) + "</td>"; // display selectable date
9151						printDate.setDate( printDate.getDate() + 1 );
9152						printDate = this._daylightSavingAdjust( printDate );
9153					}
9154					calender += tbody + "</tr>";
9155				}
9156				drawMonth++;
9157				if ( drawMonth > 11 ) {
9158					drawMonth = 0;
9159					drawYear++;
9160				}
9161				calender += "</tbody></table>" + ( isMultiMonth ? "</div>" +
9162							( ( numMonths[ 0 ] > 0 && col === numMonths[ 1 ] - 1 ) ? "<div class='ui-datepicker-row-break'></div>" : "" ) : "" );
9163				group += calender;
9164			}
9165			html += group;
9166		}
9167		html += buttonPanel;
9168		inst._keyEvent = false;
9169		return html;
9170	},
9171
9172	/* Generate the month and year header. */
9173	_generateMonthYearHeader: function( inst, drawMonth, drawYear, minDate, maxDate,
9174			secondary, monthNames, monthNamesShort ) {
9175
9176		var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear,
9177			changeMonth = this._get( inst, "changeMonth" ),
9178			changeYear = this._get( inst, "changeYear" ),
9179			showMonthAfterYear = this._get( inst, "showMonthAfterYear" ),
9180			html = "<div class='ui-datepicker-title'>",
9181			monthHtml = "";
9182
9183		// Month selection
9184		if ( secondary || !changeMonth ) {
9185			monthHtml += "<span class='ui-datepicker-month'>" + monthNames[ drawMonth ] + "</span>";
9186		} else {
9187			inMinYear = ( minDate && minDate.getFullYear() === drawYear );
9188			inMaxYear = ( maxDate && maxDate.getFullYear() === drawYear );
9189			monthHtml += "<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>";
9190			for ( month = 0; month < 12; month++ ) {
9191				if ( ( !inMinYear || month >= minDate.getMonth() ) && ( !inMaxYear || month <= maxDate.getMonth() ) ) {
9192					monthHtml += "<option value='" + month + "'" +
9193						( month === drawMonth ? " selected='selected'" : "" ) +
9194						">" + monthNamesShort[ month ] + "</option>";
9195				}
9196			}
9197			monthHtml += "</select>";
9198		}
9199
9200		if ( !showMonthAfterYear ) {
9201			html += monthHtml + ( secondary || !( changeMonth && changeYear ) ? "&#xa0;" : "" );
9202		}
9203
9204		// Year selection
9205		if ( !inst.yearshtml ) {
9206			inst.yearshtml = "";
9207			if ( secondary || !changeYear ) {
9208				html += "<span class='ui-datepicker-year'>" + drawYear + "</span>";
9209			} else {
9210
9211				// determine range of years to display
9212				years = this._get( inst, "yearRange" ).split( ":" );
9213				thisYear = new Date().getFullYear();
9214				determineYear = function( value ) {
9215					var year = ( value.match( /c[+\-].*/ ) ? drawYear + parseInt( value.substring( 1 ), 10 ) :
9216						( value.match( /[+\-].*/ ) ? thisYear + parseInt( value, 10 ) :
9217						parseInt( value, 10 ) ) );
9218					return ( isNaN( year ) ? thisYear : year );
9219				};
9220				year = determineYear( years[ 0 ] );
9221				endYear = Math.max( year, determineYear( years[ 1 ] || "" ) );
9222				year = ( minDate ? Math.max( year, minDate.getFullYear() ) : year );
9223				endYear = ( maxDate ? Math.min( endYear, maxDate.getFullYear() ) : endYear );
9224				inst.yearshtml += "<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>";
9225				for ( ; year <= endYear; year++ ) {
9226					inst.yearshtml += "<option value='" + year + "'" +
9227						( year === drawYear ? " selected='selected'" : "" ) +
9228						">" + year + "</option>";
9229				}
9230				inst.yearshtml += "</select>";
9231
9232				html += inst.yearshtml;
9233				inst.yearshtml = null;
9234			}
9235		}
9236
9237		html += this._get( inst, "yearSuffix" );
9238		if ( showMonthAfterYear ) {
9239			html += ( secondary || !( changeMonth && changeYear ) ? "&#xa0;" : "" ) + monthHtml;
9240		}
9241		html += "</div>"; // Close datepicker_header
9242		return html;
9243	},
9244
9245	/* Adjust one of the date sub-fields. */
9246	_adjustInstDate: function( inst, offset, period ) {
9247		var year = inst.selectedYear + ( period === "Y" ? offset : 0 ),
9248			month = inst.selectedMonth + ( period === "M" ? offset : 0 ),
9249			day = Math.min( inst.selectedDay, this._getDaysInMonth( year, month ) ) + ( period === "D" ? offset : 0 ),
9250			date = this._restrictMinMax( inst, this._daylightSavingAdjust( new Date( year, month, day ) ) );
9251
9252		inst.selectedDay = date.getDate();
9253		inst.drawMonth = inst.selectedMonth = date.getMonth();
9254		inst.drawYear = inst.selectedYear = date.getFullYear();
9255		if ( period === "M" || period === "Y" ) {
9256			this._notifyChange( inst );
9257		}
9258	},
9259
9260	/* Ensure a date is within any min/max bounds. */
9261	_restrictMinMax: function( inst, date ) {
9262		var minDate = this._getMinMaxDate( inst, "min" ),
9263			maxDate = this._getMinMaxDate( inst, "max" ),
9264			newDate = ( minDate && date < minDate ? minDate : date );
9265		return ( maxDate && newDate > maxDate ? maxDate : newDate );
9266	},
9267
9268	/* Notify change of month/year. */
9269	_notifyChange: function( inst ) {
9270		var onChange = this._get( inst, "onChangeMonthYear" );
9271		if ( onChange ) {
9272			onChange.apply( ( inst.input ? inst.input[ 0 ] : null ),
9273				[ inst.selectedYear, inst.selectedMonth + 1, inst ] );
9274		}
9275	},
9276
9277	/* Determine the number of months to show. */
9278	_getNumberOfMonths: function( inst ) {
9279		var numMonths = this._get( inst, "numberOfMonths" );
9280		return ( numMonths == null ? [ 1, 1 ] : ( typeof numMonths === "number" ? [ 1, numMonths ] : numMonths ) );
9281	},
9282
9283	/* Determine the current maximum date - ensure no time components are set. */
9284	_getMinMaxDate: function( inst, minMax ) {
9285		return this._determineDate( inst, this._get( inst, minMax + "Date" ), null );
9286	},
9287
9288	/* Find the number of days in a given month. */
9289	_getDaysInMonth: function( year, month ) {
9290		return 32 - this._daylightSavingAdjust( new Date( year, month, 32 ) ).getDate();
9291	},
9292
9293	/* Find the day of the week of the first of a month. */
9294	_getFirstDayOfMonth: function( year, month ) {
9295		return new Date( year, month, 1 ).getDay();
9296	},
9297
9298	/* Determines if we should allow a "next/prev" month display change. */
9299	_canAdjustMonth: function( inst, offset, curYear, curMonth ) {
9300		var numMonths = this._getNumberOfMonths( inst ),
9301			date = this._daylightSavingAdjust( new Date( curYear,
9302			curMonth + ( offset < 0 ? offset : numMonths[ 0 ] * numMonths[ 1 ] ), 1 ) );
9303
9304		if ( offset < 0 ) {
9305			date.setDate( this._getDaysInMonth( date.getFullYear(), date.getMonth() ) );
9306		}
9307		return this._isInRange( inst, date );
9308	},
9309
9310	/* Is the given date in the accepted range? */
9311	_isInRange: function( inst, date ) {
9312		var yearSplit, currentYear,
9313			minDate = this._getMinMaxDate( inst, "min" ),
9314			maxDate = this._getMinMaxDate( inst, "max" ),
9315			minYear = null,
9316			maxYear = null,
9317			years = this._get( inst, "yearRange" );
9318			if ( years ) {
9319				yearSplit = years.split( ":" );
9320				currentYear = new Date().getFullYear();
9321				minYear = parseInt( yearSplit[ 0 ], 10 );
9322				maxYear = parseInt( yearSplit[ 1 ], 10 );
9323				if ( yearSplit[ 0 ].match( /[+\-].*/ ) ) {
9324					minYear += currentYear;
9325				}
9326				if ( yearSplit[ 1 ].match( /[+\-].*/ ) ) {
9327					maxYear += currentYear;
9328				}
9329			}
9330
9331		return ( ( !minDate || date.getTime() >= minDate.getTime() ) &&
9332			( !maxDate || date.getTime() <= maxDate.getTime() ) &&
9333			( !minYear || date.getFullYear() >= minYear ) &&
9334			( !maxYear || date.getFullYear() <= maxYear ) );
9335	},
9336
9337	/* Provide the configuration settings for formatting/parsing. */
9338	_getFormatConfig: function( inst ) {
9339		var shortYearCutoff = this._get( inst, "shortYearCutoff" );
9340		shortYearCutoff = ( typeof shortYearCutoff !== "string" ? shortYearCutoff :
9341			new Date().getFullYear() % 100 + parseInt( shortYearCutoff, 10 ) );
9342		return { shortYearCutoff: shortYearCutoff,
9343			dayNamesShort: this._get( inst, "dayNamesShort" ), dayNames: this._get( inst, "dayNames" ),
9344			monthNamesShort: this._get( inst, "monthNamesShort" ), monthNames: this._get( inst, "monthNames" ) };
9345	},
9346
9347	/* Format the given date for display. */
9348	_formatDate: function( inst, day, month, year ) {
9349		if ( !day ) {
9350			inst.currentDay = inst.selectedDay;
9351			inst.currentMonth = inst.selectedMonth;
9352			inst.currentYear = inst.selectedYear;
9353		}
9354		var date = ( day ? ( typeof day === "object" ? day :
9355			this._daylightSavingAdjust( new Date( year, month, day ) ) ) :
9356			this._daylightSavingAdjust( new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) );
9357		return this.formatDate( this._get( inst, "dateFormat" ), date, this._getFormatConfig( inst ) );
9358	}
9359} );
9360
9361/*
9362 * Bind hover events for datepicker elements.
9363 * Done via delegate so the binding only occurs once in the lifetime of the parent div.
9364 * Global datepicker_instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
9365 */
9366function datepicker_bindHover( dpDiv ) {
9367	var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";
9368	return dpDiv.on( "mouseout", selector, function() {
9369			$( this ).removeClass( "ui-state-hover" );
9370			if ( this.className.indexOf( "ui-datepicker-prev" ) !== -1 ) {
9371				$( this ).removeClass( "ui-datepicker-prev-hover" );
9372			}
9373			if ( this.className.indexOf( "ui-datepicker-next" ) !== -1 ) {
9374				$( this ).removeClass( "ui-datepicker-next-hover" );
9375			}
9376		} )
9377		.on( "mouseover", selector, datepicker_handleMouseover );
9378}
9379
9380function datepicker_handleMouseover() {
9381	if ( !$.datepicker._isDisabledDatepicker( datepicker_instActive.inline ? datepicker_instActive.dpDiv.parent()[ 0 ] : datepicker_instActive.input[ 0 ] ) ) {
9382		$( this ).parents( ".ui-datepicker-calendar" ).find( "a" ).removeClass( "ui-state-hover" );
9383		$( this ).addClass( "ui-state-hover" );
9384		if ( this.className.indexOf( "ui-datepicker-prev" ) !== -1 ) {
9385			$( this ).addClass( "ui-datepicker-prev-hover" );
9386		}
9387		if ( this.className.indexOf( "ui-datepicker-next" ) !== -1 ) {
9388			$( this ).addClass( "ui-datepicker-next-hover" );
9389		}
9390	}
9391}
9392
9393/* jQuery extend now ignores nulls! */
9394function datepicker_extendRemove( target, props ) {
9395	$.extend( target, props );
9396	for ( var name in props ) {
9397		if ( props[ name ] == null ) {
9398			target[ name ] = props[ name ];
9399		}
9400	}
9401	return target;
9402}
9403
9404/* Invoke the datepicker functionality.
9405   @param  options  string - a command, optionally followed by additional parameters or
9406					Object - settings for attaching new datepicker functionality
9407   @return  jQuery object */
9408$.fn.datepicker = function( options ) {
9409
9410	/* Verify an empty collection wasn't passed - Fixes #6976 */
9411	if ( !this.length ) {
9412		return this;
9413	}
9414
9415	/* Initialise the date picker. */
9416	if ( !$.datepicker.initialized ) {
9417		$( document ).on( "mousedown", $.datepicker._checkExternalClick );
9418		$.datepicker.initialized = true;
9419	}
9420
9421	/* Append datepicker main container to body if not exist. */
9422	if ( $( "#" + $.datepicker._mainDivId ).length === 0 ) {
9423		$( "body" ).append( $.datepicker.dpDiv );
9424	}
9425
9426	var otherArgs = Array.prototype.slice.call( arguments, 1 );
9427	if ( typeof options === "string" && ( options === "isDisabled" || options === "getDate" || options === "widget" ) ) {
9428		return $.datepicker[ "_" + options + "Datepicker" ].
9429			apply( $.datepicker, [ this[ 0 ] ].concat( otherArgs ) );
9430	}
9431	if ( options === "option" && arguments.length === 2 && typeof arguments[ 1 ] === "string" ) {
9432		return $.datepicker[ "_" + options + "Datepicker" ].
9433			apply( $.datepicker, [ this[ 0 ] ].concat( otherArgs ) );
9434	}
9435	return this.each( function() {
9436		typeof options === "string" ?
9437			$.datepicker[ "_" + options + "Datepicker" ].
9438				apply( $.datepicker, [ this ].concat( otherArgs ) ) :
9439			$.datepicker._attachDatepicker( this, options );
9440	} );
9441};
9442
9443$.datepicker = new Datepicker(); // singleton instance
9444$.datepicker.initialized = false;
9445$.datepicker.uuid = new Date().getTime();
9446$.datepicker.version = "1.12.1";
9447
9448var widgetsDatepicker = $.datepicker;
9449
9450
9451/*!
9452 * jQuery UI Dialog 1.12.1
9453 * http://jqueryui.com
9454 *
9455 * Copyright jQuery Foundation and other contributors
9456 * Released under the MIT license.
9457 * http://jquery.org/license
9458 */
9459
9460//>>label: Dialog
9461//>>group: Widgets
9462//>>description: Displays customizable dialog windows.
9463//>>docs: http://api.jqueryui.com/dialog/
9464//>>demos: http://jqueryui.com/dialog/
9465//>>css.structure: ../../themes/base/core.css
9466//>>css.structure: ../../themes/base/dialog.css
9467//>>css.theme: ../../themes/base/theme.css
9468
9469
9470
9471$.widget( "ui.dialog", {
9472	version: "1.12.1",
9473	options: {
9474		appendTo: "body",
9475		autoOpen: true,
9476		buttons: [],
9477		classes: {
9478			"ui-dialog": "ui-corner-all",
9479			"ui-dialog-titlebar": "ui-corner-all"
9480		},
9481		closeOnEscape: true,
9482		closeText: "Close",
9483		draggable: true,
9484		hide: null,
9485		height: "auto",
9486		maxHeight: null,
9487		maxWidth: null,
9488		minHeight: 150,
9489		minWidth: 150,
9490		modal: false,
9491		position: {
9492			my: "center",
9493			at: "center",
9494			of: window,
9495			collision: "fit",
9496
9497			// Ensure the titlebar is always visible
9498			using: function( pos ) {
9499				var topOffset = $( this ).css( pos ).offset().top;
9500				if ( topOffset < 0 ) {
9501					$( this ).css( "top", pos.top - topOffset );
9502				}
9503			}
9504		},
9505		resizable: true,
9506		show: null,
9507		title: null,
9508		width: 300,
9509
9510		// Callbacks
9511		beforeClose: null,
9512		close: null,
9513		drag: null,
9514		dragStart: null,
9515		dragStop: null,
9516		focus: null,
9517		open: null,
9518		resize: null,
9519		resizeStart: null,
9520		resizeStop: null
9521	},
9522
9523	sizeRelatedOptions: {
9524		buttons: true,
9525		height: true,
9526		maxHeight: true,
9527		maxWidth: true,
9528		minHeight: true,
9529		minWidth: true,
9530		width: true
9531	},
9532
9533	resizableRelatedOptions: {
9534		maxHeight: true,
9535		maxWidth: true,
9536		minHeight: true,
9537		minWidth: true
9538	},
9539
9540	_create: function() {
9541		this.originalCss = {
9542			display: this.element[ 0 ].style.display,
9543			width: this.element[ 0 ].style.width,
9544			minHeight: this.element[ 0 ].style.minHeight,
9545			maxHeight: this.element[ 0 ].style.maxHeight,
9546			height: this.element[ 0 ].style.height
9547		};
9548		this.originalPosition = {
9549			parent: this.element.parent(),
9550			index: this.element.parent().children().index( this.element )
9551		};
9552		this.originalTitle = this.element.attr( "title" );
9553		if ( this.options.title == null && this.originalTitle != null ) {
9554			this.options.title = this.originalTitle;
9555		}
9556
9557		// Dialogs can't be disabled
9558		if ( this.options.disabled ) {
9559			this.options.disabled = false;
9560		}
9561
9562		this._createWrapper();
9563
9564		this.element
9565			.show()
9566			.removeAttr( "title" )
9567			.appendTo( this.uiDialog );
9568
9569		this._addClass( "ui-dialog-content", "ui-widget-content" );
9570
9571		this._createTitlebar();
9572		this._createButtonPane();
9573
9574		if ( this.options.draggable && $.fn.draggable ) {
9575			this._makeDraggable();
9576		}
9577		if ( this.options.resizable && $.fn.resizable ) {
9578			this._makeResizable();
9579		}
9580
9581		this._isOpen = false;
9582
9583		this._trackFocus();
9584	},
9585
9586	_init: function() {
9587		if ( this.options.autoOpen ) {
9588			this.open();
9589		}
9590	},
9591
9592	_appendTo: function() {
9593		var element = this.options.appendTo;
9594		if ( element && ( element.jquery || element.nodeType ) ) {
9595			return $( element );
9596		}
9597		return this.document.find( element || "body" ).eq( 0 );
9598	},
9599
9600	_destroy: function() {
9601		var next,
9602			originalPosition = this.originalPosition;
9603
9604		this._untrackInstance();
9605		this._destroyOverlay();
9606
9607		this.element
9608			.removeUniqueId()
9609			.css( this.originalCss )
9610
9611			// Without detaching first, the following becomes really slow
9612			.detach();
9613
9614		this.uiDialog.remove();
9615
9616		if ( this.originalTitle ) {
9617			this.element.attr( "title", this.originalTitle );
9618		}
9619
9620		next = originalPosition.parent.children().eq( originalPosition.index );
9621
9622		// Don't try to place the dialog next to itself (#8613)
9623		if ( next.length && next[ 0 ] !== this.element[ 0 ] ) {
9624			next.before( this.element );
9625		} else {
9626			originalPosition.parent.append( this.element );
9627		}
9628	},
9629
9630	widget: function() {
9631		return this.uiDialog;
9632	},
9633
9634	disable: $.noop,
9635	enable: $.noop,
9636
9637	close: function( event ) {
9638		var that = this;
9639
9640		if ( !this._isOpen || this._trigger( "beforeClose", event ) === false ) {
9641			return;
9642		}
9643
9644		this._isOpen = false;
9645		this._focusedElement = null;
9646		this._destroyOverlay();
9647		this._untrackInstance();
9648
9649		if ( !this.opener.filter( ":focusable" ).trigger( "focus" ).length ) {
9650
9651			// Hiding a focused element doesn't trigger blur in WebKit
9652			// so in case we have nothing to focus on, explicitly blur the active element
9653			// https://bugs.webkit.org/show_bug.cgi?id=47182
9654			$.ui.safeBlur( $.ui.safeActiveElement( this.document[ 0 ] ) );
9655		}
9656
9657		this._hide( this.uiDialog, this.options.hide, function() {
9658			that._trigger( "close", event );
9659		} );
9660	},
9661
9662	isOpen: function() {
9663		return this._isOpen;
9664	},
9665
9666	moveToTop: function() {
9667		this._moveToTop();
9668	},
9669
9670	_moveToTop: function( event, silent ) {
9671		var moved = false,
9672			zIndices = this.uiDialog.siblings( ".ui-front:visible" ).map( function() {
9673				return +$( this ).css( "z-index" );
9674			} ).get(),
9675			zIndexMax = Math.max.apply( null, zIndices );
9676
9677		if ( zIndexMax >= +this.uiDialog.css( "z-index" ) ) {
9678			this.uiDialog.css( "z-index", zIndexMax + 1 );
9679			moved = true;
9680		}
9681
9682		if ( moved && !silent ) {
9683			this._trigger( "focus", event );
9684		}
9685		return moved;
9686	},
9687
9688	open: function() {
9689		var that = this;
9690		if ( this._isOpen ) {
9691			if ( this._moveToTop() ) {
9692				this._focusTabbable();
9693			}
9694			return;
9695		}
9696
9697		this._isOpen = true;
9698		this.opener = $( $.ui.safeActiveElement( this.document[ 0 ] ) );
9699
9700		this._size();
9701		this._position();
9702		this._createOverlay();
9703		this._moveToTop( null, true );
9704
9705		// Ensure the overlay is moved to the top with the dialog, but only when
9706		// opening. The overlay shouldn't move after the dialog is open so that
9707		// modeless dialogs opened after the modal dialog stack properly.
9708		if ( this.overlay ) {
9709			this.overlay.css( "z-index", this.uiDialog.css( "z-index" ) - 1 );
9710		}
9711
9712		this._show( this.uiDialog, this.options.show, function() {
9713			that._focusTabbable();
9714			that._trigger( "focus" );
9715		} );
9716
9717		// Track the dialog immediately upon openening in case a focus event
9718		// somehow occurs outside of the dialog before an element inside the
9719		// dialog is focused (#10152)
9720		this._makeFocusTarget();
9721
9722		this._trigger( "open" );
9723	},
9724
9725	_focusTabbable: function() {
9726
9727		// Set focus to the first match:
9728		// 1. An element that was focused previously
9729		// 2. First element inside the dialog matching [autofocus]
9730		// 3. Tabbable element inside the content element
9731		// 4. Tabbable element inside the buttonpane
9732		// 5. The close button
9733		// 6. The dialog itself
9734		var hasFocus = this._focusedElement;
9735		if ( !hasFocus ) {
9736			hasFocus = this.element.find( "[autofocus]" );
9737		}
9738		if ( !hasFocus.length ) {
9739			hasFocus = this.element.find( ":tabbable" );
9740		}
9741		if ( !hasFocus.length ) {
9742			hasFocus = this.uiDialogButtonPane.find( ":tabbable" );
9743		}
9744		if ( !hasFocus.length ) {
9745			hasFocus = this.uiDialogTitlebarClose.filter( ":tabbable" );
9746		}
9747		if ( !hasFocus.length ) {
9748			hasFocus = this.uiDialog;
9749		}
9750		hasFocus.eq( 0 ).trigger( "focus" );
9751	},
9752
9753	_keepFocus: function( event ) {
9754		function checkFocus() {
9755			var activeElement = $.ui.safeActiveElement( this.document[ 0 ] ),
9756				isActive = this.uiDialog[ 0 ] === activeElement ||
9757					$.contains( this.uiDialog[ 0 ], activeElement );
9758			if ( !isActive ) {
9759				this._focusTabbable();
9760			}
9761		}
9762		event.preventDefault();
9763		checkFocus.call( this );
9764
9765		// support: IE
9766		// IE <= 8 doesn't prevent moving focus even with event.preventDefault()
9767		// so we check again later
9768		this._delay( checkFocus );
9769	},
9770
9771	_createWrapper: function() {
9772		this.uiDialog = $( "<div>" )
9773			.hide()
9774			.attr( {
9775
9776				// Setting tabIndex makes the div focusable
9777				tabIndex: -1,
9778				role: "dialog"
9779			} )
9780			.appendTo( this._appendTo() );
9781
9782		this._addClass( this.uiDialog, "ui-dialog", "ui-widget ui-widget-content ui-front" );
9783		this._on( this.uiDialog, {
9784			keydown: function( event ) {
9785				if ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
9786						event.keyCode === $.ui.keyCode.ESCAPE ) {
9787					event.preventDefault();
9788					this.close( event );
9789					return;
9790				}
9791
9792				// Prevent tabbing out of dialogs
9793				if ( event.keyCode !== $.ui.keyCode.TAB || event.isDefaultPrevented() ) {
9794					return;
9795				}
9796				var tabbables = this.uiDialog.find( ":tabbable" ),
9797					first = tabbables.filter( ":first" ),
9798					last = tabbables.filter( ":last" );
9799
9800				if ( ( event.target === last[ 0 ] || event.target === this.uiDialog[ 0 ] ) &&
9801						!event.shiftKey ) {
9802					this._delay( function() {
9803						first.trigger( "focus" );
9804					} );
9805					event.preventDefault();
9806				} else if ( ( event.target === first[ 0 ] ||
9807						event.target === this.uiDialog[ 0 ] ) && event.shiftKey ) {
9808					this._delay( function() {
9809						last.trigger( "focus" );
9810					} );
9811					event.preventDefault();
9812				}
9813			},
9814			mousedown: function( event ) {
9815				if ( this._moveToTop( event ) ) {
9816					this._focusTabbable();
9817				}
9818			}
9819		} );
9820
9821		// We assume that any existing aria-describedby attribute means
9822		// that the dialog content is marked up properly
9823		// otherwise we brute force the content as the description
9824		if ( !this.element.find( "[aria-describedby]" ).length ) {
9825			this.uiDialog.attr( {
9826				"aria-describedby": this.element.uniqueId().attr( "id" )
9827			} );
9828		}
9829	},
9830
9831	_createTitlebar: function() {
9832		var uiDialogTitle;
9833
9834		this.uiDialogTitlebar = $( "<div>" );
9835		this._addClass( this.uiDialogTitlebar,
9836			"ui-dialog-titlebar", "ui-widget-header ui-helper-clearfix" );
9837		this._on( this.uiDialogTitlebar, {
9838			mousedown: function( event ) {
9839
9840				// Don't prevent click on close button (#8838)
9841				// Focusing a dialog that is partially scrolled out of view
9842				// causes the browser to scroll it into view, preventing the click event
9843				if ( !$( event.target ).closest( ".ui-dialog-titlebar-close" ) ) {
9844
9845					// Dialog isn't getting focus when dragging (#8063)
9846					this.uiDialog.trigger( "focus" );
9847				}
9848			}
9849		} );
9850
9851		// Support: IE
9852		// Use type="button" to prevent enter keypresses in textboxes from closing the
9853		// dialog in IE (#9312)
9854		this.uiDialogTitlebarClose = $( "<button type='button'></button>" )
9855			.button( {
9856				label: $( "<a>" ).text( this.options.closeText ).html(),
9857				icon: "ui-icon-closethick",
9858				showLabel: false
9859			} )
9860			.appendTo( this.uiDialogTitlebar );
9861
9862		this._addClass( this.uiDialogTitlebarClose, "ui-dialog-titlebar-close" );
9863		this._on( this.uiDialogTitlebarClose, {
9864			click: function( event ) {
9865				event.preventDefault();
9866				this.close( event );
9867			}
9868		} );
9869
9870		uiDialogTitle = $( "<span>" ).uniqueId().prependTo( this.uiDialogTitlebar );
9871		this._addClass( uiDialogTitle, "ui-dialog-title" );
9872		this._title( uiDialogTitle );
9873
9874		this.uiDialogTitlebar.prependTo( this.uiDialog );
9875
9876		this.uiDialog.attr( {
9877			"aria-labelledby": uiDialogTitle.attr( "id" )
9878		} );
9879	},
9880
9881	_title: function( title ) {
9882		if ( this.options.title ) {
9883			title.text( this.options.title );
9884		} else {
9885			title.html( "&#160;" );
9886		}
9887	},
9888
9889	_createButtonPane: function() {
9890		this.uiDialogButtonPane = $( "<div>" );
9891		this._addClass( this.uiDialogButtonPane, "ui-dialog-buttonpane",
9892			"ui-widget-content ui-helper-clearfix" );
9893
9894		this.uiButtonSet = $( "<div>" )
9895			.appendTo( this.uiDialogButtonPane );
9896		this._addClass( this.uiButtonSet, "ui-dialog-buttonset" );
9897
9898		this._createButtons();
9899	},
9900
9901	_createButtons: function() {
9902		var that = this,
9903			buttons = this.options.buttons;
9904
9905		// If we already have a button pane, remove it
9906		this.uiDialogButtonPane.remove();
9907		this.uiButtonSet.empty();
9908
9909		if ( $.isEmptyObject( buttons ) || ( $.isArray( buttons ) && !buttons.length ) ) {
9910			this._removeClass( this.uiDialog, "ui-dialog-buttons" );
9911			return;
9912		}
9913
9914		$.each( buttons, function( name, props ) {
9915			var click, buttonOptions;
9916			props = $.isFunction( props ) ?
9917				{ click: props, text: name } :
9918				props;
9919
9920			// Default to a non-submitting button
9921			props = $.extend( { type: "button" }, props );
9922
9923			// Change the context for the click callback to be the main element
9924			click = props.click;
9925			buttonOptions = {
9926				icon: props.icon,
9927				iconPosition: props.iconPosition,
9928				showLabel: props.showLabel,
9929
9930				// Deprecated options
9931				icons: props.icons,
9932				text: props.text
9933			};
9934
9935			delete props.click;
9936			delete props.icon;
9937			delete props.iconPosition;
9938			delete props.showLabel;
9939
9940			// Deprecated options
9941			delete props.icons;
9942			if ( typeof props.text === "boolean" ) {
9943				delete props.text;
9944			}
9945
9946			$( "<button></button>", props )
9947				.button( buttonOptions )
9948				.appendTo( that.uiButtonSet )
9949				.on( "click", function() {
9950					click.apply( that.element[ 0 ], arguments );
9951				} );
9952		} );
9953		this._addClass( this.uiDialog, "ui-dialog-buttons" );
9954		this.uiDialogButtonPane.appendTo( this.uiDialog );
9955	},
9956
9957	_makeDraggable: function() {
9958		var that = this,
9959			options = this.options;
9960
9961		function filteredUi( ui ) {
9962			return {
9963				position: ui.position,
9964				offset: ui.offset
9965			};
9966		}
9967
9968		this.uiDialog.draggable( {
9969			cancel: ".ui-dialog-content, .ui-dialog-titlebar-close",
9970			handle: ".ui-dialog-titlebar",
9971			containment: "document",
9972			start: function( event, ui ) {
9973				that._addClass( $( this ), "ui-dialog-dragging" );
9974				that._blockFrames();
9975				that._trigger( "dragStart", event, filteredUi( ui ) );
9976			},
9977			drag: function( event, ui ) {
9978				that._trigger( "drag", event, filteredUi( ui ) );
9979			},
9980			stop: function( event, ui ) {
9981				var left = ui.offset.left - that.document.scrollLeft(),
9982					top = ui.offset.top - that.document.scrollTop();
9983
9984				options.position = {
9985					my: "left top",
9986					at: "left" + ( left >= 0 ? "+" : "" ) + left + " " +
9987						"top" + ( top >= 0 ? "+" : "" ) + top,
9988					of: that.window
9989				};
9990				that._removeClass( $( this ), "ui-dialog-dragging" );
9991				that._unblockFrames();
9992				that._trigger( "dragStop", event, filteredUi( ui ) );
9993			}
9994		} );
9995	},
9996
9997	_makeResizable: function() {
9998		var that = this,
9999			options = this.options,
10000			handles = options.resizable,
10001
10002			// .ui-resizable has position: relative defined in the stylesheet
10003			// but dialogs have to use absolute or fixed positioning
10004			position = this.uiDialog.css( "position" ),
10005			resizeHandles = typeof handles === "string" ?
10006				handles :
10007				"n,e,s,w,se,sw,ne,nw";
10008
10009		function filteredUi( ui ) {
10010			return {
10011				originalPosition: ui.originalPosition,
10012				originalSize: ui.originalSize,
10013				position: ui.position,
10014				size: ui.size
10015			};
10016		}
10017
10018		this.uiDialog.resizable( {
10019			cancel: ".ui-dialog-content",
10020			containment: "document",
10021			alsoResize: this.element,
10022			maxWidth: options.maxWidth,
10023			maxHeight: options.maxHeight,
10024			minWidth: options.minWidth,
10025			minHeight: this._minHeight(),
10026			handles: resizeHandles,
10027			start: function( event, ui ) {
10028				that._addClass( $( this ), "ui-dialog-resizing" );
10029				that._blockFrames();
10030				that._trigger( "resizeStart", event, filteredUi( ui ) );
10031			},
10032			resize: function( event, ui ) {
10033				that._trigger( "resize", event, filteredUi( ui ) );
10034			},
10035			stop: function( event, ui ) {
10036				var offset = that.uiDialog.offset(),
10037					left = offset.left - that.document.scrollLeft(),
10038					top = offset.top - that.document.scrollTop();
10039
10040				options.height = that.uiDialog.height();
10041				options.width = that.uiDialog.width();
10042				options.position = {
10043					my: "left top",
10044					at: "left" + ( left >= 0 ? "+" : "" ) + left + " " +
10045						"top" + ( top >= 0 ? "+" : "" ) + top,
10046					of: that.window
10047				};
10048				that._removeClass( $( this ), "ui-dialog-resizing" );
10049				that._unblockFrames();
10050				that._trigger( "resizeStop", event, filteredUi( ui ) );
10051			}
10052		} )
10053			.css( "position", position );
10054	},
10055
10056	_trackFocus: function() {
10057		this._on( this.widget(), {
10058			focusin: function( event ) {
10059				this._makeFocusTarget();
10060				this._focusedElement = $( event.target );
10061			}
10062		} );
10063	},
10064
10065	_makeFocusTarget: function() {
10066		this._untrackInstance();
10067		this._trackingInstances().unshift( this );
10068	},
10069
10070	_untrackInstance: function() {
10071		var instances = this._trackingInstances(),
10072			exists = $.inArray( this, instances );
10073		if ( exists !== -1 ) {
10074			instances.splice( exists, 1 );
10075		}
10076	},
10077
10078	_trackingInstances: function() {
10079		var instances = this.document.data( "ui-dialog-instances" );
10080		if ( !instances ) {
10081			instances = [];
10082			this.document.data( "ui-dialog-instances", instances );
10083		}
10084		return instances;
10085	},
10086
10087	_minHeight: function() {
10088		var options = this.options;
10089
10090		return options.height === "auto" ?
10091			options.minHeight :
10092			Math.min( options.minHeight, options.height );
10093	},
10094
10095	_position: function() {
10096
10097		// Need to show the dialog to get the actual offset in the position plugin
10098		var isVisible = this.uiDialog.is( ":visible" );
10099		if ( !isVisible ) {
10100			this.uiDialog.show();
10101		}
10102		this.uiDialog.position( this.options.position );
10103		if ( !isVisible ) {
10104			this.uiDialog.hide();
10105		}
10106	},
10107
10108	_setOptions: function( options ) {
10109		var that = this,
10110			resize = false,
10111			resizableOptions = {};
10112
10113		$.each( options, function( key, value ) {
10114			that._setOption( key, value );
10115
10116			if ( key in that.sizeRelatedOptions ) {
10117				resize = true;
10118			}
10119			if ( key in that.resizableRelatedOptions ) {
10120				resizableOptions[ key ] = value;
10121			}
10122		} );
10123
10124		if ( resize ) {
10125			this._size();
10126			this._position();
10127		}
10128		if ( this.uiDialog.is( ":data(ui-resizable)" ) ) {
10129			this.uiDialog.resizable( "option", resizableOptions );
10130		}
10131	},
10132
10133	_setOption: function( key, value ) {
10134		var isDraggable, isResizable,
10135			uiDialog = this.uiDialog;
10136
10137		if ( key === "disabled" ) {
10138			return;
10139		}
10140
10141		this._super( key, value );
10142
10143		if ( key === "appendTo" ) {
10144			this.uiDialog.appendTo( this._appendTo() );
10145		}
10146
10147		if ( key === "buttons" ) {
10148			this._createButtons();
10149		}
10150
10151		if ( key === "closeText" ) {
10152			this.uiDialogTitlebarClose.button( {
10153
10154				// Ensure that we always pass a string
10155				label: $( "<a>" ).text( "" + this.options.closeText ).html()
10156			} );
10157		}
10158
10159		if ( key === "draggable" ) {
10160			isDraggable = uiDialog.is( ":data(ui-draggable)" );
10161			if ( isDraggable && !value ) {
10162				uiDialog.draggable( "destroy" );
10163			}
10164
10165			if ( !isDraggable && value ) {
10166				this._makeDraggable();
10167			}
10168		}
10169
10170		if ( key === "position" ) {
10171			this._position();
10172		}
10173
10174		if ( key === "resizable" ) {
10175
10176			// currently resizable, becoming non-resizable
10177			isResizable = uiDialog.is( ":data(ui-resizable)" );
10178			if ( isResizable && !value ) {
10179				uiDialog.resizable( "destroy" );
10180			}
10181
10182			// Currently resizable, changing handles
10183			if ( isResizable && typeof value === "string" ) {
10184				uiDialog.resizable( "option", "handles", value );
10185			}
10186
10187			// Currently non-resizable, becoming resizable
10188			if ( !isResizable && value !== false ) {
10189				this._makeResizable();
10190			}
10191		}
10192
10193		if ( key === "title" ) {
10194			this._title( this.uiDialogTitlebar.find( ".ui-dialog-title" ) );
10195		}
10196	},
10197
10198	_size: function() {
10199
10200		// If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
10201		// divs will both have width and height set, so we need to reset them
10202		var nonContentHeight, minContentHeight, maxContentHeight,
10203			options = this.options;
10204
10205		// Reset content sizing
10206		this.element.show().css( {
10207			width: "auto",
10208			minHeight: 0,
10209			maxHeight: "none",
10210			height: 0
10211		} );
10212
10213		if ( options.minWidth > options.width ) {
10214			options.width = options.minWidth;
10215		}
10216
10217		// Reset wrapper sizing
10218		// determine the height of all the non-content elements
10219		nonContentHeight = this.uiDialog.css( {
10220			height: "auto",
10221			width: options.width
10222		} )
10223			.outerHeight();
10224		minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
10225		maxContentHeight = typeof options.maxHeight === "number" ?
10226			Math.max( 0, options.maxHeight - nonContentHeight ) :
10227			"none";
10228
10229		if ( options.height === "auto" ) {
10230			this.element.css( {
10231				minHeight: minContentHeight,
10232				maxHeight: maxContentHeight,
10233				height: "auto"
10234			} );
10235		} else {
10236			this.element.height( Math.max( 0, options.height - nonContentHeight ) );
10237		}
10238
10239		if ( this.uiDialog.is( ":data(ui-resizable)" ) ) {
10240			this.uiDialog.resizable( "option", "minHeight", this._minHeight() );
10241		}
10242	},
10243
10244	_blockFrames: function() {
10245		this.iframeBlocks = this.document.find( "iframe" ).map( function() {
10246			var iframe = $( this );
10247
10248			return $( "<div>" )
10249				.css( {
10250					position: "absolute",
10251					width: iframe.outerWidth(),
10252					height: iframe.outerHeight()
10253				} )
10254				.appendTo( iframe.parent() )
10255				.offset( iframe.offset() )[ 0 ];
10256		} );
10257	},
10258
10259	_unblockFrames: function() {
10260		if ( this.iframeBlocks ) {
10261			this.iframeBlocks.remove();
10262			delete this.iframeBlocks;
10263		}
10264	},
10265
10266	_allowInteraction: function( event ) {
10267		if ( $( event.target ).closest( ".ui-dialog" ).length ) {
10268			return true;
10269		}
10270
10271		// TODO: Remove hack when datepicker implements
10272		// the .ui-front logic (#8989)
10273		return !!$( event.target ).closest( ".ui-datepicker" ).length;
10274	},
10275
10276	_createOverlay: function() {
10277		if ( !this.options.modal ) {
10278			return;
10279		}
10280
10281		// We use a delay in case the overlay is created from an
10282		// event that we're going to be cancelling (#2804)
10283		var isOpening = true;
10284		this._delay( function() {
10285			isOpening = false;
10286		} );
10287
10288		if ( !this.document.data( "ui-dialog-overlays" ) ) {
10289
10290			// Prevent use of anchors and inputs
10291			// Using _on() for an event handler shared across many instances is
10292			// safe because the dialogs stack and must be closed in reverse order
10293			this._on( this.document, {
10294				focusin: function( event ) {
10295					if ( isOpening ) {
10296						return;
10297					}
10298
10299					if ( !this._allowInteraction( event ) ) {
10300						event.preventDefault();
10301						this._trackingInstances()[ 0 ]._focusTabbable();
10302					}
10303				}
10304			} );
10305		}
10306
10307		this.overlay = $( "<div>" )
10308			.appendTo( this._appendTo() );
10309
10310		this._addClass( this.overlay, null, "ui-widget-overlay ui-front" );
10311		this._on( this.overlay, {
10312			mousedown: "_keepFocus"
10313		} );
10314		this.document.data( "ui-dialog-overlays",
10315			( this.document.data( "ui-dialog-overlays" ) || 0 ) + 1 );
10316	},
10317
10318	_destroyOverlay: function() {
10319		if ( !this.options.modal ) {
10320			return;
10321		}
10322
10323		if ( this.overlay ) {
10324			var overlays = this.document.data( "ui-dialog-overlays" ) - 1;
10325
10326			if ( !overlays ) {
10327				this._off( this.document, "focusin" );
10328				this.document.removeData( "ui-dialog-overlays" );
10329			} else {
10330				this.document.data( "ui-dialog-overlays", overlays );
10331			}
10332
10333			this.overlay.remove();
10334			this.overlay = null;
10335		}
10336	}
10337} );
10338
10339// DEPRECATED
10340// TODO: switch return back to widget declaration at top of file when this is removed
10341if ( $.uiBackCompat !== false ) {
10342
10343	// Backcompat for dialogClass option
10344	$.widget( "ui.dialog", $.ui.dialog, {
10345		options: {
10346			dialogClass: ""
10347		},
10348		_createWrapper: function() {
10349			this._super();
10350			this.uiDialog.addClass( this.options.dialogClass );
10351		},
10352		_setOption: function( key, value ) {
10353			if ( key === "dialogClass" ) {
10354				this.uiDialog
10355					.removeClass( this.options.dialogClass )
10356					.addClass( value );
10357			}
10358			this._superApply( arguments );
10359		}
10360	} );
10361}
10362
10363var widgetsDialog = $.ui.dialog;
10364
10365
10366/*!
10367 * jQuery UI Progressbar 1.12.1
10368 * http://jqueryui.com
10369 *
10370 * Copyright jQuery Foundation and other contributors
10371 * Released under the MIT license.
10372 * http://jquery.org/license
10373 */
10374
10375//>>label: Progressbar
10376//>>group: Widgets
10377// jscs:disable maximumLineLength
10378//>>description: Displays a status indicator for loading state, standard percentage, and other progress indicators.
10379// jscs:enable maximumLineLength
10380//>>docs: http://api.jqueryui.com/progressbar/
10381//>>demos: http://jqueryui.com/progressbar/
10382//>>css.structure: ../../themes/base/core.css
10383//>>css.structure: ../../themes/base/progressbar.css
10384//>>css.theme: ../../themes/base/theme.css
10385
10386
10387
10388var widgetsProgressbar = $.widget( "ui.progressbar", {
10389	version: "1.12.1",
10390	options: {
10391		classes: {
10392			"ui-progressbar": "ui-corner-all",
10393			"ui-progressbar-value": "ui-corner-left",
10394			"ui-progressbar-complete": "ui-corner-right"
10395		},
10396		max: 100,
10397		value: 0,
10398
10399		change: null,
10400		complete: null
10401	},
10402
10403	min: 0,
10404
10405	_create: function() {
10406
10407		// Constrain initial value
10408		this.oldValue = this.options.value = this._constrainedValue();
10409
10410		this.element.attr( {
10411
10412			// Only set static values; aria-valuenow and aria-valuemax are
10413			// set inside _refreshValue()
10414			role: "progressbar",
10415			"aria-valuemin": this.min
10416		} );
10417		this._addClass( "ui-progressbar", "ui-widget ui-widget-content" );
10418
10419		this.valueDiv = $( "<div>" ).appendTo( this.element );
10420		this._addClass( this.valueDiv, "ui-progressbar-value", "ui-widget-header" );
10421		this._refreshValue();
10422	},
10423
10424	_destroy: function() {
10425		this.element.removeAttr( "role aria-valuemin aria-valuemax aria-valuenow" );
10426
10427		this.valueDiv.remove();
10428	},
10429
10430	value: function( newValue ) {
10431		if ( newValue === undefined ) {
10432			return this.options.value;
10433		}
10434
10435		this.options.value = this._constrainedValue( newValue );
10436		this._refreshValue();
10437	},
10438
10439	_constrainedValue: function( newValue ) {
10440		if ( newValue === undefined ) {
10441			newValue = this.options.value;
10442		}
10443
10444		this.indeterminate = newValue === false;
10445
10446		// Sanitize value
vendor: 5,900 bytes, lines 10447-10676
10447		if ( typeof newValue !== "number" ) {
10448			newValue = 0;
10449		}
10450
10451		return this.indeterminate ? false :
10452			Math.min( this.options.max, Math.max( this.min, newValue ) );
10453	},
10454
10455	_setOptions: function( options ) {
10456
10457		// Ensure "value" option is set after other values (like max)
10458		var value = options.value;
10459		delete options.value;
10460
10461		this._super( options );
10462
10463		this.options.value = this._constrainedValue( value );
10464		this._refreshValue();
10465	},
10466
10467	_setOption: function( key, value ) {
10468		if ( key === "max" ) {
10469
10470			// Don't allow a max less than min
10471			value = Math.max( this.min, value );
10472		}
10473		this._super( key, value );
10474	},
10475
10476	_setOptionDisabled: function( value ) {
10477		this._super( value );
10478
10479		this.element.attr( "aria-disabled", value );
10480		this._toggleClass( null, "ui-state-disabled", !!value );
10481	},
10482
10483	_percentage: function() {
10484		return this.indeterminate ?
10485			100 :
10486			100 * ( this.options.value - this.min ) / ( this.options.max - this.min );
10487	},
10488
10489	_refreshValue: function() {
10490		var value = this.options.value,
10491			percentage = this._percentage();
10492
10493		this.valueDiv
10494			.toggle( this.indeterminate || value > this.min )
10495			.width( percentage.toFixed( 0 ) + "%" );
10496
10497		this
10498			._toggleClass( this.valueDiv, "ui-progressbar-complete", null,
10499				value === this.options.max )
10500			._toggleClass( "ui-progressbar-indeterminate", null, this.indeterminate );
10501
10502		if ( this.indeterminate ) {
10503			this.element.removeAttr( "aria-valuenow" );
10504			if ( !this.overlayDiv ) {
10505				this.overlayDiv = $( "<div>" ).appendTo( this.valueDiv );
10506				this._addClass( this.overlayDiv, "ui-progressbar-overlay" );
10507			}
10508		} else {
10509			this.element.attr( {
10510				"aria-valuemax": this.options.max,
10511				"aria-valuenow": value
10512			} );
10513			if ( this.overlayDiv ) {
10514				this.overlayDiv.remove();
10515				this.overlayDiv = null;
10516			}
10517		}
10518
10519		if ( this.oldValue !== value ) {
10520			this.oldValue = value;
10521			this._trigger( "change" );
10522		}
10523		if ( value === this.options.max ) {
10524			this._trigger( "complete" );
10525		}
10526	}
10527} );
10528
10529
10530/*!
10531 * jQuery UI Selectmenu 1.12.1
10532 * http://jqueryui.com
10533 *
10534 * Copyright jQuery Foundation and other contributors
10535 * Released under the MIT license.
10536 * http://jquery.org/license
10537 */
10538
10539//>>label: Selectmenu
10540//>>group: Widgets
10541// jscs:disable maximumLineLength
10542//>>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.
10543// jscs:enable maximumLineLength
10544//>>docs: http://api.jqueryui.com/selectmenu/
10545//>>demos: http://jqueryui.com/selectmenu/
10546//>>css.structure: ../../themes/base/core.css
10547//>>css.structure: ../../themes/base/selectmenu.css, ../../themes/base/button.css
10548//>>css.theme: ../../themes/base/theme.css
10549
10550
10551
10552var widgetsSelectmenu = $.widget( "ui.selectmenu", [ $.ui.formResetMixin, {
10553	version: "1.12.1",
10554	defaultElement: "<select>",
10555	options: {
10556		appendTo: null,
10557		classes: {
10558			"ui-selectmenu-button-open": "ui-corner-top",
10559			"ui-selectmenu-button-closed": "ui-corner-all"
10560		},
10561		disabled: null,
10562		icons: {
10563			button: "ui-icon-triangle-1-s"
10564		},
10565		position: {
10566			my: "left top",
10567			at: "left bottom",
10568			collision: "none"
10569		},
10570		width: false,
10571
10572		// Callbacks
10573		change: null,
10574		close: null,
10575		focus: null,
10576		open: null,
10577		select: null
10578	},
10579
10580	_create: function() {
10581		var selectmenuId = this.element.uniqueId().attr( "id" );
10582		this.ids = {
10583			element: selectmenuId,
10584			button: selectmenuId + "-button",
10585			menu: selectmenuId + "-menu"
10586		};
10587
10588		this._drawButton();
10589		this._drawMenu();
10590		this._bindFormResetHandler();
10591
10592		this._rendered = false;
10593		this.menuItems = $();
10594	},
10595
10596	_drawButton: function() {
10597		var icon,
10598			that = this,
10599			item = this._parseOption(
10600				this.element.find( "option:selected" ),
10601				this.element[ 0 ].selectedIndex
10602			);
10603
10604		// Associate existing label with the new button
10605		this.labels = this.element.labels().attr( "for", this.ids.button );
10606		this._on( this.labels, {
10607			click: function( event ) {
10608				this.button.focus();
10609				event.preventDefault();
10610			}
10611		} );
10612
10613		// Hide original select element
10614		this.element.hide();
10615
10616		// Create button
10617		this.button = $( "<span>", {
10618			tabindex: this.options.disabled ? -1 : 0,
10619			id: this.ids.button,
10620			role: "combobox",
10621			"aria-expanded": "false",
10622			"aria-autocomplete": "list",
10623			"aria-owns": this.ids.menu,
10624			"aria-haspopup": "true",
10625			title: this.element.attr( "title" )
10626		} )
10627			.insertAfter( this.element );
10628
10629		this._addClass( this.button, "ui-selectmenu-button ui-selectmenu-button-closed",
10630			"ui-button ui-widget" );
10631
10632		icon = $( "<span>" ).appendTo( this.button );
10633		this._addClass( icon, "ui-selectmenu-icon", "ui-icon " + this.options.icons.button );
10634		this.buttonItem = this._renderButtonItem( item )
10635			.appendTo( this.button );
10636
10637		if ( this.options.width !== false ) {
10638			this._resizeButton();
10639		}
10640
10641		this._on( this.button, this._buttonEvents );
10642		this.button.one( "focusin", function() {
10643
10644			// Delay rendering the menu items until the button receives focus.
10645			// The menu may have already been rendered via a programmatic open.
10646			if ( !that._rendered ) {
10647				that._refreshMenu();
10648			}
10649		} );
10650	},
10651
10652	_drawMenu: function() {
10653		var that = this;
10654
10655		// Create menu
10656		this.menu = $( "<ul>", {
10657			"aria-hidden": "true",
10658			"aria-labelledby": this.ids.button,
10659			id: this.ids.menu
10660		} );
10661
10662		// Wrap menu
10663		this.menuWrap = $( "<div>" ).append( this.menu );
10664		this._addClass( this.menuWrap, "ui-selectmenu-menu", "ui-front" );
10665		this.menuWrap.appendTo( this._appendTo() );
10666
10667		// Initialize menu widget
10668		this.menuInstance = this.menu
10669			.menu( {
10670				classes: {
10671					"ui-menu": "ui-corner-bottom"
10672				},
10673				role: "listbox",
10674				select: function( event, ui ) {
10675					event.preventDefault();
10676
vendor: 11,520 bytes, lines 10677-11147
10677					// Support: IE8
10678					// If the item was selected via a click, the text selection
10679					// will be destroyed in IE
10680					that._setSelection();
10681
10682					that._select( ui.item.data( "ui-selectmenu-item" ), event );
10683				},
10684				focus: function( event, ui ) {
10685					var item = ui.item.data( "ui-selectmenu-item" );
10686
10687					// Prevent inital focus from firing and check if its a newly focused item
10688					if ( that.focusIndex != null && item.index !== that.focusIndex ) {
10689						that._trigger( "focus", event, { item: item } );
10690						if ( !that.isOpen ) {
10691							that._select( item, event );
10692						}
10693					}
10694					that.focusIndex = item.index;
10695
10696					that.button.attr( "aria-activedescendant",
10697						that.menuItems.eq( item.index ).attr( "id" ) );
10698				}
10699			} )
10700			.menu( "instance" );
10701
10702		// Don't close the menu on mouseleave
10703		this.menuInstance._off( this.menu, "mouseleave" );
10704
10705		// Cancel the menu's collapseAll on document click
10706		this.menuInstance._closeOnDocumentClick = function() {
10707			return false;
10708		};
10709
10710		// Selects often contain empty items, but never contain dividers
10711		this.menuInstance._isDivider = function() {
10712			return false;
10713		};
10714	},
10715
10716	refresh: function() {
10717		this._refreshMenu();
10718		this.buttonItem.replaceWith(
10719			this.buttonItem = this._renderButtonItem(
10720
10721				// Fall back to an empty object in case there are no options
10722				this._getSelectedItem().data( "ui-selectmenu-item" ) || {}
10723			)
10724		);
10725		if ( this.options.width === null ) {
10726			this._resizeButton();
10727		}
10728	},
10729
10730	_refreshMenu: function() {
10731		var item,
10732			options = this.element.find( "option" );
10733
10734		this.menu.empty();
10735
10736		this._parseOptions( options );
10737		this._renderMenu( this.menu, this.items );
10738
10739		this.menuInstance.refresh();
10740		this.menuItems = this.menu.find( "li" )
10741			.not( ".ui-selectmenu-optgroup" )
10742				.find( ".ui-menu-item-wrapper" );
10743
10744		this._rendered = true;
10745
10746		if ( !options.length ) {
10747			return;
10748		}
10749
10750		item = this._getSelectedItem();
10751
10752		// Update the menu to have the correct item focused
10753		this.menuInstance.focus( null, item );
10754		this._setAria( item.data( "ui-selectmenu-item" ) );
10755
10756		// Set disabled state
10757		this._setOption( "disabled", this.element.prop( "disabled" ) );
10758	},
10759
10760	open: function( event ) {
10761		if ( this.options.disabled ) {
10762			return;
10763		}
10764
10765		// If this is the first time the menu is being opened, render the items
10766		if ( !this._rendered ) {
10767			this._refreshMenu();
10768		} else {
10769
10770			// Menu clears focus on close, reset focus to selected item
10771			this._removeClass( this.menu.find( ".ui-state-active" ), null, "ui-state-active" );
10772			this.menuInstance.focus( null, this._getSelectedItem() );
10773		}
10774
10775		// If there are no options, don't open the menu
10776		if ( !this.menuItems.length ) {
10777			return;
10778		}
10779
10780		this.isOpen = true;
10781		this._toggleAttr();
10782		this._resizeMenu();
10783		this._position();
10784
10785		this._on( this.document, this._documentClick );
10786
10787		this._trigger( "open", event );
10788	},
10789
10790	_position: function() {
10791		this.menuWrap.position( $.extend( { of: this.button }, this.options.position ) );
10792	},
10793
10794	close: function( event ) {
10795		if ( !this.isOpen ) {
10796			return;
10797		}
10798
10799		this.isOpen = false;
10800		this._toggleAttr();
10801
10802		this.range = null;
10803		this._off( this.document );
10804
10805		this._trigger( "close", event );
10806	},
10807
10808	widget: function() {
10809		return this.button;
10810	},
10811
10812	menuWidget: function() {
10813		return this.menu;
10814	},
10815
10816	_renderButtonItem: function( item ) {
10817		var buttonItem = $( "<span>" );
10818
10819		this._setText( buttonItem, item.label );
10820		this._addClass( buttonItem, "ui-selectmenu-text" );
10821
10822		return buttonItem;
10823	},
10824
10825	_renderMenu: function( ul, items ) {
10826		var that = this,
10827			currentOptgroup = "";
10828
10829		$.each( items, function( index, item ) {
10830			var li;
10831
10832			if ( item.optgroup !== currentOptgroup ) {
10833				li = $( "<li>", {
10834					text: item.optgroup
10835				} );
10836				that._addClass( li, "ui-selectmenu-optgroup", "ui-menu-divider" +
10837					( item.element.parent( "optgroup" ).prop( "disabled" ) ?
10838						" ui-state-disabled" :
10839						"" ) );
10840
10841				li.appendTo( ul );
10842
10843				currentOptgroup = item.optgroup;
10844			}
10845
10846			that._renderItemData( ul, item );
10847		} );
10848	},
10849
10850	_renderItemData: function( ul, item ) {
10851		return this._renderItem( ul, item ).data( "ui-selectmenu-item", item );
10852	},
10853
10854	_renderItem: function( ul, item ) {
10855		var li = $( "<li>" ),
10856			wrapper = $( "<div>", {
10857				title: item.element.attr( "title" )
10858			} );
10859
10860		if ( item.disabled ) {
10861			this._addClass( li, null, "ui-state-disabled" );
10862		}
10863		this._setText( wrapper, item.label );
10864
10865		return li.append( wrapper ).appendTo( ul );
10866	},
10867
10868	_setText: function( element, value ) {
10869		if ( value ) {
10870			element.text( value );
10871		} else {
10872			element.html( "&#160;" );
10873		}
10874	},
10875
10876	_move: function( direction, event ) {
10877		var item, next,
10878			filter = ".ui-menu-item";
10879
10880		if ( this.isOpen ) {
10881			item = this.menuItems.eq( this.focusIndex ).parent( "li" );
10882		} else {
10883			item = this.menuItems.eq( this.element[ 0 ].selectedIndex ).parent( "li" );
10884			filter += ":not(.ui-state-disabled)";
10885		}
10886
10887		if ( direction === "first" || direction === "last" ) {
10888			next = item[ direction === "first" ? "prevAll" : "nextAll" ]( filter ).eq( -1 );
10889		} else {
10890			next = item[ direction + "All" ]( filter ).eq( 0 );
10891		}
10892
10893		if ( next.length ) {
10894			this.menuInstance.focus( event, next );
10895		}
10896	},
10897
10898	_getSelectedItem: function() {
10899		return this.menuItems.eq( this.element[ 0 ].selectedIndex ).parent( "li" );
10900	},
10901
10902	_toggle: function( event ) {
10903		this[ this.isOpen ? "close" : "open" ]( event );
10904	},
10905
10906	_setSelection: function() {
10907		var selection;
10908
10909		if ( !this.range ) {
10910			return;
10911		}
10912
10913		if ( window.getSelection ) {
10914			selection = window.getSelection();
10915			selection.removeAllRanges();
10916			selection.addRange( this.range );
10917
10918		// Support: IE8
10919		} else {
10920			this.range.select();
10921		}
10922
10923		// Support: IE
10924		// Setting the text selection kills the button focus in IE, but
10925		// restoring the focus doesn't kill the selection.
10926		this.button.focus();
10927	},
10928
10929	_documentClick: {
10930		mousedown: function( event ) {
10931			if ( !this.isOpen ) {
10932				return;
10933			}
10934
10935			if ( !$( event.target ).closest( ".ui-selectmenu-menu, #" +
10936					$.ui.escapeSelector( this.ids.button ) ).length ) {
10937				this.close( event );
10938			}
10939		}
10940	},
10941
10942	_buttonEvents: {
10943
10944		// Prevent text selection from being reset when interacting with the selectmenu (#10144)
10945		mousedown: function() {
10946			var selection;
10947
10948			if ( window.getSelection ) {
10949				selection = window.getSelection();
10950				if ( selection.rangeCount ) {
10951					this.range = selection.getRangeAt( 0 );
10952				}
10953
10954			// Support: IE8
10955			} else {
10956				this.range = document.selection.createRange();
10957			}
10958		},
10959
10960		click: function( event ) {
10961			this._setSelection();
10962			this._toggle( event );
10963		},
10964
10965		keydown: function( event ) {
10966			var preventDefault = true;
10967			switch ( event.keyCode ) {
10968			case $.ui.keyCode.TAB:
10969			case $.ui.keyCode.ESCAPE:
10970				this.close( event );
10971				preventDefault = false;
10972				break;
10973			case $.ui.keyCode.ENTER:
10974				if ( this.isOpen ) {
10975					this._selectFocusedItem( event );
10976				}
10977				break;
10978			case $.ui.keyCode.UP:
10979				if ( event.altKey ) {
10980					this._toggle( event );
10981				} else {
10982					this._move( "prev", event );
10983				}
10984				break;
10985			case $.ui.keyCode.DOWN:
10986				if ( event.altKey ) {
10987					this._toggle( event );
10988				} else {
10989					this._move( "next", event );
10990				}
10991				break;
10992			case $.ui.keyCode.SPACE:
10993				if ( this.isOpen ) {
10994					this._selectFocusedItem( event );
10995				} else {
10996					this._toggle( event );
10997				}
10998				break;
10999			case $.ui.keyCode.LEFT:
11000				this._move( "prev", event );
11001				break;
11002			case $.ui.keyCode.RIGHT:
11003				this._move( "next", event );
11004				break;
11005			case $.ui.keyCode.HOME:
11006			case $.ui.keyCode.PAGE_UP:
11007				this._move( "first", event );
11008				break;
11009			case $.ui.keyCode.END:
11010			case $.ui.keyCode.PAGE_DOWN:
11011				this._move( "last", event );
11012				break;
11013			default:
11014				this.menu.trigger( event );
11015				preventDefault = false;
11016			}
11017
11018			if ( preventDefault ) {
11019				event.preventDefault();
11020			}
11021		}
11022	},
11023
11024	_selectFocusedItem: function( event ) {
11025		var item = this.menuItems.eq( this.focusIndex ).parent( "li" );
11026		if ( !item.hasClass( "ui-state-disabled" ) ) {
11027			this._select( item.data( "ui-selectmenu-item" ), event );
11028		}
11029	},
11030
11031	_select: function( item, event ) {
11032		var oldIndex = this.element[ 0 ].selectedIndex;
11033
11034		// Change native select element
11035		this.element[ 0 ].selectedIndex = item.index;
11036		this.buttonItem.replaceWith( this.buttonItem = this._renderButtonItem( item ) );
11037		this._setAria( item );
11038		this._trigger( "select", event, { item: item } );
11039
11040		if ( item.index !== oldIndex ) {
11041			this._trigger( "change", event, { item: item } );
11042		}
11043
11044		this.close( event );
11045	},
11046
11047	_setAria: function( item ) {
11048		var id = this.menuItems.eq( item.index ).attr( "id" );
11049
11050		this.button.attr( {
11051			"aria-labelledby": id,
11052			"aria-activedescendant": id
11053		} );
11054		this.menu.attr( "aria-activedescendant", id );
11055	},
11056
11057	_setOption: function( key, value ) {
11058		if ( key === "icons" ) {
11059			var icon = this.button.find( "span.ui-icon" );
11060			this._removeClass( icon, null, this.options.icons.button )
11061				._addClass( icon, null, value.button );
11062		}
11063
11064		this._super( key, value );
11065
11066		if ( key === "appendTo" ) {
11067			this.menuWrap.appendTo( this._appendTo() );
11068		}
11069
11070		if ( key === "width" ) {
11071			this._resizeButton();
11072		}
11073	},
11074
11075	_setOptionDisabled: function( value ) {
11076		this._super( value );
11077
11078		this.menuInstance.option( "disabled", value );
11079		this.button.attr( "aria-disabled", value );
11080		this._toggleClass( this.button, null, "ui-state-disabled", value );
11081
11082		this.element.prop( "disabled", value );
11083		if ( value ) {
11084			this.button.attr( "tabindex", -1 );
11085			this.close();
11086		} else {
11087			this.button.attr( "tabindex", 0 );
11088		}
11089	},
11090
11091	_appendTo: function() {
11092		var element = this.options.appendTo;
11093
11094		if ( element ) {
11095			element = element.jquery || element.nodeType ?
11096				$( element ) :
11097				this.document.find( element ).eq( 0 );
11098		}
11099
11100		if ( !element || !element[ 0 ] ) {
11101			element = this.element.closest( ".ui-front, dialog" );
11102		}
11103
11104		if ( !element.length ) {
11105			element = this.document[ 0 ].body;
11106		}
11107
11108		return element;
11109	},
11110
11111	_toggleAttr: function() {
11112		this.button.attr( "aria-expanded", this.isOpen );
11113
11114		// We can't use two _toggleClass() calls here, because we need to make sure
11115		// we always remove classes first and add them second, otherwise if both classes have the
11116		// same theme class, it will be removed after we add it.
11117		this._removeClass( this.button, "ui-selectmenu-button-" +
11118			( this.isOpen ? "closed" : "open" ) )
11119			._addClass( this.button, "ui-selectmenu-button-" +
11120				( this.isOpen ? "open" : "closed" ) )
11121			._toggleClass( this.menuWrap, "ui-selectmenu-open", null, this.isOpen );
11122
11123		this.menu.attr( "aria-hidden", !this.isOpen );
11124	},
11125
11126	_resizeButton: function() {
11127		var width = this.options.width;
11128
11129		// For `width: false`, just remove inline style and stop
11130		if ( width === false ) {
11131			this.button.css( "width", "" );
11132			return;
11133		}
11134
11135		// For `width: null`, match the width of the original element
11136		if ( width === null ) {
11137			width = this.element.show().outerWidth();
11138			this.element.hide();
11139		}
11140
11141		this.button.outerWidth( width );
11142	},
11143
11144	_resizeMenu: function() {
11145		this.menu.outerWidth( Math.max(
11146			this.button.outerWidth(),
11147
vendor: 5,390 bytes, lines 11148-11361
11148			// Support: IE10
11149			// IE10 wraps long text (possibly a rounding bug)
11150			// so we add 1px to avoid the wrapping
11151			this.menu.width( "" ).outerWidth() + 1
11152		) );
11153	},
11154
11155	_getCreateOptions: function() {
11156		var options = this._super();
11157
11158		options.disabled = this.element.prop( "disabled" );
11159
11160		return options;
11161	},
11162
11163	_parseOptions: function( options ) {
11164		var that = this,
11165			data = [];
11166		options.each( function( index, item ) {
11167			data.push( that._parseOption( $( item ), index ) );
11168		} );
11169		this.items = data;
11170	},
11171
11172	_parseOption: function( option, index ) {
11173		var optgroup = option.parent( "optgroup" );
11174
11175		return {
11176			element: option,
11177			index: index,
11178			value: option.val(),
11179			label: option.text(),
11180			optgroup: optgroup.attr( "label" ) || "",
11181			disabled: optgroup.prop( "disabled" ) || option.prop( "disabled" )
11182		};
11183	},
11184
11185	_destroy: function() {
11186		this._unbindFormResetHandler();
11187		this.menuWrap.remove();
11188		this.button.remove();
11189		this.element.show();
11190		this.element.removeUniqueId();
11191		this.labels.attr( "for", this.ids.element );
11192	}
11193} ] );
11194
11195
11196/*!
11197 * jQuery UI Slider 1.12.1
11198 * http://jqueryui.com
11199 *
11200 * Copyright jQuery Foundation and other contributors
11201 * Released under the MIT license.
11202 * http://jquery.org/license
11203 */
11204
11205//>>label: Slider
11206//>>group: Widgets
11207//>>description: Displays a flexible slider with ranges and accessibility via keyboard.
11208//>>docs: http://api.jqueryui.com/slider/
11209//>>demos: http://jqueryui.com/slider/
11210//>>css.structure: ../../themes/base/core.css
11211//>>css.structure: ../../themes/base/slider.css
11212//>>css.theme: ../../themes/base/theme.css
11213
11214
11215
11216var widgetsSlider = $.widget( "ui.slider", $.ui.mouse, {
11217	version: "1.12.1",
11218	widgetEventPrefix: "slide",
11219
11220	options: {
11221		animate: false,
11222		classes: {
11223			"ui-slider": "ui-corner-all",
11224			"ui-slider-handle": "ui-corner-all",
11225
11226			// Note: ui-widget-header isn't the most fittingly semantic framework class for this
11227			// element, but worked best visually with a variety of themes
11228			"ui-slider-range": "ui-corner-all ui-widget-header"
11229		},
11230		distance: 0,
11231		max: 100,
11232		min: 0,
11233		orientation: "horizontal",
11234		range: false,
11235		step: 1,
11236		value: 0,
11237		values: null,
11238
11239		// Callbacks
11240		change: null,
11241		slide: null,
11242		start: null,
11243		stop: null
11244	},
11245
11246	// Number of pages in a slider
11247	// (how many times can you page up/down to go through the whole range)
11248	numPages: 5,
11249
11250	_create: function() {
11251		this._keySliding = false;
11252		this._mouseSliding = false;
11253		this._animateOff = true;
11254		this._handleIndex = null;
11255		this._detectOrientation();
11256		this._mouseInit();
11257		this._calculateNewMax();
11258
11259		this._addClass( "ui-slider ui-slider-" + this.orientation,
11260			"ui-widget ui-widget-content" );
11261
11262		this._refresh();
11263
11264		this._animateOff = false;
11265	},
11266
11267	_refresh: function() {
11268		this._createRange();
11269		this._createHandles();
11270		this._setupEvents();
11271		this._refreshValue();
11272	},
11273
11274	_createHandles: function() {
11275		var i, handleCount,
11276			options = this.options,
11277			existingHandles = this.element.find( ".ui-slider-handle" ),
11278			handle = "<span tabindex='0'></span>",
11279			handles = [];
11280
11281		handleCount = ( options.values && options.values.length ) || 1;
11282
11283		if ( existingHandles.length > handleCount ) {
11284			existingHandles.slice( handleCount ).remove();
11285			existingHandles = existingHandles.slice( 0, handleCount );
11286		}
11287
11288		for ( i = existingHandles.length; i < handleCount; i++ ) {
11289			handles.push( handle );
11290		}
11291
11292		this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) );
11293
11294		this._addClass( this.handles, "ui-slider-handle", "ui-state-default" );
11295
11296		this.handle = this.handles.eq( 0 );
11297
11298		this.handles.each( function( i ) {
11299			$( this )
11300				.data( "ui-slider-handle-index", i )
11301				.attr( "tabIndex", 0 );
11302		} );
11303	},
11304
11305	_createRange: function() {
11306		var options = this.options;
11307
11308		if ( options.range ) {
11309			if ( options.range === true ) {
11310				if ( !options.values ) {
11311					options.values = [ this._valueMin(), this._valueMin() ];
11312				} else if ( options.values.length && options.values.length !== 2 ) {
11313					options.values = [ options.values[ 0 ], options.values[ 0 ] ];
11314				} else if ( $.isArray( options.values ) ) {
11315					options.values = options.values.slice( 0 );
11316				}
11317			}
11318
11319			if ( !this.range || !this.range.length ) {
11320				this.range = $( "<div>" )
11321					.appendTo( this.element );
11322
11323				this._addClass( this.range, "ui-slider-range" );
11324			} else {
11325				this._removeClass( this.range, "ui-slider-range-min ui-slider-range-max" );
11326
11327				// Handle range switching from true to min/max
11328				this.range.css( {
11329					"left": "",
11330					"bottom": ""
11331				} );
11332			}
11333			if ( options.range === "min" || options.range === "max" ) {
11334				this._addClass( this.range, "ui-slider-range-" + options.range );
11335			}
11336		} else {
11337			if ( this.range ) {
11338				this.range.remove();
11339			}
11340			this.range = null;
11341		}
11342	},
11343
11344	_setupEvents: function() {
11345		this._off( this.handles );
11346		this._on( this.handles, this._handleEvents );
11347		this._hoverable( this.handles );
11348		this._focusable( this.handles );
11349	},
11350
11351	_destroy: function() {
11352		this.handles.remove();
11353		if ( this.range ) {
11354			this.range.remove();
11355		}
11356
11357		this._mouseDestroy();
11358	},
11359
11360	_mouseCapture: function( event ) {
11361		var position, normValue, distance, closestHandle, index, allowed, offset, mou
vendor: 15,708 bytes, lines 11361-11932
11361seOverHandle,
11362			that = this,
11363			o = this.options;
11364
11365		if ( o.disabled ) {
11366			return false;
11367		}
11368
11369		this.elementSize = {
11370			width: this.element.outerWidth(),
11371			height: this.element.outerHeight()
11372		};
11373		this.elementOffset = this.element.offset();
11374
11375		position = { x: event.pageX, y: event.pageY };
11376		normValue = this._normValueFromMouse( position );
11377		distance = this._valueMax() - this._valueMin() + 1;
11378		this.handles.each( function( i ) {
11379			var thisDistance = Math.abs( normValue - that.values( i ) );
11380			if ( ( distance > thisDistance ) ||
11381				( distance === thisDistance &&
11382					( i === that._lastChangedValue || that.values( i ) === o.min ) ) ) {
11383				distance = thisDistance;
11384				closestHandle = $( this );
11385				index = i;
11386			}
11387		} );
11388
11389		allowed = this._start( event, index );
11390		if ( allowed === false ) {
11391			return false;
11392		}
11393		this._mouseSliding = true;
11394
11395		this._handleIndex = index;
11396
11397		this._addClass( closestHandle, null, "ui-state-active" );
11398		closestHandle.trigger( "focus" );
11399
11400		offset = closestHandle.offset();
11401		mouseOverHandle = !$( event.target ).parents().addBack().is( ".ui-slider-handle" );
11402		this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
11403			left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
11404			top: event.pageY - offset.top -
11405				( closestHandle.height() / 2 ) -
11406				( parseInt( closestHandle.css( "borderTopWidth" ), 10 ) || 0 ) -
11407				( parseInt( closestHandle.css( "borderBottomWidth" ), 10 ) || 0 ) +
11408				( parseInt( closestHandle.css( "marginTop" ), 10 ) || 0 )
11409		};
11410
11411		if ( !this.handles.hasClass( "ui-state-hover" ) ) {
11412			this._slide( event, index, normValue );
11413		}
11414		this._animateOff = true;
11415		return true;
11416	},
11417
11418	_mouseStart: function() {
11419		return true;
11420	},
11421
11422	_mouseDrag: function( event ) {
11423		var position = { x: event.pageX, y: event.pageY },
11424			normValue = this._normValueFromMouse( position );
11425
11426		this._slide( event, this._handleIndex, normValue );
11427
11428		return false;
11429	},
11430
11431	_mouseStop: function( event ) {
11432		this._removeClass( this.handles, null, "ui-state-active" );
11433		this._mouseSliding = false;
11434
11435		this._stop( event, this._handleIndex );
11436		this._change( event, this._handleIndex );
11437
11438		this._handleIndex = null;
11439		this._clickOffset = null;
11440		this._animateOff = false;
11441
11442		return false;
11443	},
11444
11445	_detectOrientation: function() {
11446		this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
11447	},
11448
11449	_normValueFromMouse: function( position ) {
11450		var pixelTotal,
11451			pixelMouse,
11452			percentMouse,
11453			valueTotal,
11454			valueMouse;
11455
11456		if ( this.orientation === "horizontal" ) {
11457			pixelTotal = this.elementSize.width;
11458			pixelMouse = position.x - this.elementOffset.left -
11459				( this._clickOffset ? this._clickOffset.left : 0 );
11460		} else {
11461			pixelTotal = this.elementSize.height;
11462			pixelMouse = position.y - this.elementOffset.top -
11463				( this._clickOffset ? this._clickOffset.top : 0 );
11464		}
11465
11466		percentMouse = ( pixelMouse / pixelTotal );
11467		if ( percentMouse > 1 ) {
11468			percentMouse = 1;
11469		}
11470		if ( percentMouse < 0 ) {
11471			percentMouse = 0;
11472		}
11473		if ( this.orientation === "vertical" ) {
11474			percentMouse = 1 - percentMouse;
11475		}
11476
11477		valueTotal = this._valueMax() - this._valueMin();
11478		valueMouse = this._valueMin() + percentMouse * valueTotal;
11479
11480		return this._trimAlignValue( valueMouse );
11481	},
11482
11483	_uiHash: function( index, value, values ) {
11484		var uiHash = {
11485			handle: this.handles[ index ],
11486			handleIndex: index,
11487			value: value !== undefined ? value : this.value()
11488		};
11489
11490		if ( this._hasMultipleValues() ) {
11491			uiHash.value = value !== undefined ? value : this.values( index );
11492			uiHash.values = values || this.values();
11493		}
11494
11495		return uiHash;
11496	},
11497
11498	_hasMultipleValues: function() {
11499		return this.options.values && this.options.values.length;
11500	},
11501
11502	_start: function( event, index ) {
11503		return this._trigger( "start", event, this._uiHash( index ) );
11504	},
11505
11506	_slide: function( event, index, newVal ) {
11507		var allowed, otherVal,
11508			currentValue = this.value(),
11509			newValues = this.values();
11510
11511		if ( this._hasMultipleValues() ) {
11512			otherVal = this.values( index ? 0 : 1 );
11513			currentValue = this.values( index );
11514
11515			if ( this.options.values.length === 2 && this.options.range === true ) {
11516				newVal =  index === 0 ? Math.min( otherVal, newVal ) : Math.max( otherVal, newVal );
11517			}
11518
11519			newValues[ index ] = newVal;
11520		}
11521
11522		if ( newVal === currentValue ) {
11523			return;
11524		}
11525
11526		allowed = this._trigger( "slide", event, this._uiHash( index, newVal, newValues ) );
11527
11528		// A slide can be canceled by returning false from the slide callback
11529		if ( allowed === false ) {
11530			return;
11531		}
11532
11533		if ( this._hasMultipleValues() ) {
11534			this.values( index, newVal );
11535		} else {
11536			this.value( newVal );
11537		}
11538	},
11539
11540	_stop: function( event, index ) {
11541		this._trigger( "stop", event, this._uiHash( index ) );
11542	},
11543
11544	_change: function( event, index ) {
11545		if ( !this._keySliding && !this._mouseSliding ) {
11546
11547			//store the last changed value index for reference when handles overlap
11548			this._lastChangedValue = index;
11549			this._trigger( "change", event, this._uiHash( index ) );
11550		}
11551	},
11552
11553	value: function( newValue ) {
11554		if ( arguments.length ) {
11555			this.options.value = this._trimAlignValue( newValue );
11556			this._refreshValue();
11557			this._change( null, 0 );
11558			return;
11559		}
11560
11561		return this._value();
11562	},
11563
11564	values: function( index, newValue ) {
11565		var vals,
11566			newValues,
11567			i;
11568
11569		if ( arguments.length > 1 ) {
11570			this.options.values[ index ] = this._trimAlignValue( newValue );
11571			this._refreshValue();
11572			this._change( null, index );
11573			return;
11574		}
11575
11576		if ( arguments.length ) {
11577			if ( $.isArray( arguments[ 0 ] ) ) {
11578				vals = this.options.values;
11579				newValues = arguments[ 0 ];
11580				for ( i = 0; i < vals.length; i += 1 ) {
11581					vals[ i ] = this._trimAlignValue( newValues[ i ] );
11582					this._change( null, i );
11583				}
11584				this._refreshValue();
11585			} else {
11586				if ( this._hasMultipleValues() ) {
11587					return this._values( index );
11588				} else {
11589					return this.value();
11590				}
11591			}
11592		} else {
11593			return this._values();
11594		}
11595	},
11596
11597	_setOption: function( key, value ) {
11598		var i,
11599			valsLength = 0;
11600
11601		if ( key === "range" && this.options.range === true ) {
11602			if ( value === "min" ) {
11603				this.options.value = this._values( 0 );
11604				this.options.values = null;
11605			} else if ( value === "max" ) {
11606				this.options.value = this._values( this.options.values.length - 1 );
11607				this.options.values = null;
11608			}
11609		}
11610
11611		if ( $.isArray( this.options.values ) ) {
11612			valsLength = this.options.values.length;
11613		}
11614
11615		this._super( key, value );
11616
11617		switch ( key ) {
11618			case "orientation":
11619				this._detectOrientation();
11620				this._removeClass( "ui-slider-horizontal ui-slider-vertical" )
11621					._addClass( "ui-slider-" + this.orientation );
11622				this._refreshValue();
11623				if ( this.options.range ) {
11624					this._refreshRange( value );
11625				}
11626
11627				// Reset positioning from previous orientation
11628				this.handles.css( value === "horizontal" ? "bottom" : "left", "" );
11629				break;
11630			case "value":
11631				this._animateOff = true;
11632				this._refreshValue();
11633				this._change( null, 0 );
11634				this._animateOff = false;
11635				break;
11636			case "values":
11637				this._animateOff = true;
11638				this._refreshValue();
11639
11640				// Start from the last handle to prevent unreachable handles (#9046)
11641				for ( i = valsLength - 1; i >= 0; i-- ) {
11642					this._change( null, i );
11643				}
11644				this._animateOff = false;
11645				break;
11646			case "step":
11647			case "min":
11648			case "max":
11649				this._animateOff = true;
11650				this._calculateNewMax();
11651				this._refreshValue();
11652				this._animateOff = false;
11653				break;
11654			case "range":
11655				this._animateOff = true;
11656				this._refresh();
11657				this._animateOff = false;
11658				break;
11659		}
11660	},
11661
11662	_setOptionDisabled: function( value ) {
11663		this._super( value );
11664
11665		this._toggleClass( null, "ui-state-disabled", !!value );
11666	},
11667
11668	//internal value getter
11669	// _value() returns value trimmed by min and max, aligned by step
11670	_value: function() {
11671		var val = this.options.value;
11672		val = this._trimAlignValue( val );
11673
11674		return val;
11675	},
11676
11677	//internal values getter
11678	// _values() returns array of values trimmed by min and max, aligned by step
11679	// _values( index ) returns single value trimmed by min and max, aligned by step
11680	_values: function( index ) {
11681		var val,
11682			vals,
11683			i;
11684
11685		if ( arguments.length ) {
11686			val = this.options.values[ index ];
11687			val = this._trimAlignValue( val );
11688
11689			return val;
11690		} else if ( this._hasMultipleValues() ) {
11691
11692			// .slice() creates a copy of the array
11693			// this copy gets trimmed by min and max and then returned
11694			vals = this.options.values.slice();
11695			for ( i = 0; i < vals.length; i += 1 ) {
11696				vals[ i ] = this._trimAlignValue( vals[ i ] );
11697			}
11698
11699			return vals;
11700		} else {
11701			return [];
11702		}
11703	},
11704
11705	// Returns the step-aligned value that val is closest to, between (inclusive) min and max
11706	_trimAlignValue: function( val ) {
11707		if ( val <= this._valueMin() ) {
11708			return this._valueMin();
11709		}
11710		if ( val >= this._valueMax() ) {
11711			return this._valueMax();
11712		}
11713		var step = ( this.options.step > 0 ) ? this.options.step : 1,
11714			valModStep = ( val - this._valueMin() ) % step,
11715			alignValue = val - valModStep;
11716
11717		if ( Math.abs( valModStep ) * 2 >= step ) {
11718			alignValue += ( valModStep > 0 ) ? step : ( -step );
11719		}
11720
11721		// Since JavaScript has problems with large floats, round
11722		// the final value to 5 digits after the decimal point (see #4124)
11723		return parseFloat( alignValue.toFixed( 5 ) );
11724	},
11725
11726	_calculateNewMax: function() {
11727		var max = this.options.max,
11728			min = this._valueMin(),
11729			step = this.options.step,
11730			aboveMin = Math.round( ( max - min ) / step ) * step;
11731		max = aboveMin + min;
11732		if ( max > this.options.max ) {
11733
11734			//If max is not divisible by step, rounding off may increase its value
11735			max -= step;
11736		}
11737		this.max = parseFloat( max.toFixed( this._precision() ) );
11738	},
11739
11740	_precision: function() {
11741		var precision = this._precisionOf( this.options.step );
11742		if ( this.options.min !== null ) {
11743			precision = Math.max( precision, this._precisionOf( this.options.min ) );
11744		}
11745		return precision;
11746	},
11747
11748	_precisionOf: function( num ) {
11749		var str = num.toString(),
11750			decimal = str.indexOf( "." );
11751		return decimal === -1 ? 0 : str.length - decimal - 1;
11752	},
11753
11754	_valueMin: function() {
11755		return this.options.min;
11756	},
11757
11758	_valueMax: function() {
11759		return this.max;
11760	},
11761
11762	_refreshRange: function( orientation ) {
11763		if ( orientation === "vertical" ) {
11764			this.range.css( { "width": "", "left": "" } );
11765		}
11766		if ( orientation === "horizontal" ) {
11767			this.range.css( { "height": "", "bottom": "" } );
11768		}
11769	},
11770
11771	_refreshValue: function() {
11772		var lastValPercent, valPercent, value, valueMin, valueMax,
11773			oRange = this.options.range,
11774			o = this.options,
11775			that = this,
11776			animate = ( !this._animateOff ) ? o.animate : false,
11777			_set = {};
11778
11779		if ( this._hasMultipleValues() ) {
11780			this.handles.each( function( i ) {
11781				valPercent = ( that.values( i ) - that._valueMin() ) / ( that._valueMax() -
11782					that._valueMin() ) * 100;
11783				_set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
11784				$( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
11785				if ( that.options.range === true ) {
11786					if ( that.orientation === "horizontal" ) {
11787						if ( i === 0 ) {
11788							that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
11789								left: valPercent + "%"
11790							}, o.animate );
11791						}
11792						if ( i === 1 ) {
11793							that.range[ animate ? "animate" : "css" ]( {
11794								width: ( valPercent - lastValPercent ) + "%"
11795							}, {
11796								queue: false,
11797								duration: o.animate
11798							} );
11799						}
11800					} else {
11801						if ( i === 0 ) {
11802							that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
11803								bottom: ( valPercent ) + "%"
11804							}, o.animate );
11805						}
11806						if ( i === 1 ) {
11807							that.range[ animate ? "animate" : "css" ]( {
11808								height: ( valPercent - lastValPercent ) + "%"
11809							}, {
11810								queue: false,
11811								duration: o.animate
11812							} );
11813						}
11814					}
11815				}
11816				lastValPercent = valPercent;
11817			} );
11818		} else {
11819			value = this.value();
11820			valueMin = this._valueMin();
11821			valueMax = this._valueMax();
11822			valPercent = ( valueMax !== valueMin ) ?
11823					( value - valueMin ) / ( valueMax - valueMin ) * 100 :
11824					0;
11825			_set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
11826			this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
11827
11828			if ( oRange === "min" && this.orientation === "horizontal" ) {
11829				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
11830					width: valPercent + "%"
11831				}, o.animate );
11832			}
11833			if ( oRange === "max" && this.orientation === "horizontal" ) {
11834				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
11835					width: ( 100 - valPercent ) + "%"
11836				}, o.animate );
11837			}
11838			if ( oRange === "min" && this.orientation === "vertical" ) {
11839				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
11840					height: valPercent + "%"
11841				}, o.animate );
11842			}
11843			if ( oRange === "max" && this.orientation === "vertical" ) {
11844				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
11845					height: ( 100 - valPercent ) + "%"
11846				}, o.animate );
11847			}
11848		}
11849	},
11850
11851	_handleEvents: {
11852		keydown: function( event ) {
11853			var allowed, curVal, newVal, step,
11854				index = $( event.target ).data( "ui-slider-handle-index" );
11855
11856			switch ( event.keyCode ) {
11857				case $.ui.keyCode.HOME:
11858				case $.ui.keyCode.END:
11859				case $.ui.keyCode.PAGE_UP:
11860				case $.ui.keyCode.PAGE_DOWN:
11861				case $.ui.keyCode.UP:
11862				case $.ui.keyCode.RIGHT:
11863				case $.ui.keyCode.DOWN:
11864				case $.ui.keyCode.LEFT:
11865					event.preventDefault();
11866					if ( !this._keySliding ) {
11867						this._keySliding = true;
11868						this._addClass( $( event.target ), null, "ui-state-active" );
11869						allowed = this._start( event, index );
11870						if ( allowed === false ) {
11871							return;
11872						}
11873					}
11874					break;
11875			}
11876
11877			step = this.options.step;
11878			if ( this._hasMultipleValues() ) {
11879				curVal = newVal = this.values( index );
11880			} else {
11881				curVal = newVal = this.value();
11882			}
11883
11884			switch ( event.keyCode ) {
11885				case $.ui.keyCode.HOME:
11886					newVal = this._valueMin();
11887					break;
11888				case $.ui.keyCode.END:
11889					newVal = this._valueMax();
11890					break;
11891				case $.ui.keyCode.PAGE_UP:
11892					newVal = this._trimAlignValue(
11893						curVal + ( ( this._valueMax() - this._valueMin() ) / this.numPages )
11894					);
11895					break;
11896				case $.ui.keyCode.PAGE_DOWN:
11897					newVal = this._trimAlignValue(
11898						curVal - ( ( this._valueMax() - this._valueMin() ) / this.numPages ) );
11899					break;
11900				case $.ui.keyCode.UP:
11901				case $.ui.keyCode.RIGHT:
11902					if ( curVal === this._valueMax() ) {
11903						return;
11904					}
11905					newVal = this._trimAlignValue( curVal + step );
11906					break;
11907				case $.ui.keyCode.DOWN:
11908				case $.ui.keyCode.LEFT:
11909					if ( curVal === this._valueMin() ) {
11910						return;
11911					}
11912					newVal = this._trimAlignValue( curVal - step );
11913					break;
11914			}
11915
11916			this._slide( event, index, newVal );
11917		},
11918		keyup: function( event ) {
11919			var index = $( event.target ).data( "ui-slider-handle-index" );
11920
11921			if ( this._keySliding ) {
11922				this._keySliding = false;
11923				this._stop( event, index );
11924				this._change( event, index );
11925				this._removeClass( $( event.target ), null, "ui-state-active" );
11926			}
11927		}
11928	}
11929} );
11930
11931
11932/*!
vendor: 4,519 bytes, lines 11933-12099
11933 * jQuery UI Spinner 1.12.1
11934 * http://jqueryui.com
11935 *
11936 * Copyright jQuery Foundation and other contributors
11937 * Released under the MIT license.
11938 * http://jquery.org/license
11939 */
11940
11941//>>label: Spinner
11942//>>group: Widgets
11943//>>description: Displays buttons to easily input numbers via the keyboard or mouse.
11944//>>docs: http://api.jqueryui.com/spinner/
11945//>>demos: http://jqueryui.com/spinner/
11946//>>css.structure: ../../themes/base/core.css
11947//>>css.structure: ../../themes/base/spinner.css
11948//>>css.theme: ../../themes/base/theme.css
11949
11950
11951
11952function spinnerModifer( fn ) {
11953	return function() {
11954		var previous = this.element.val();
11955		fn.apply( this, arguments );
11956		this._refresh();
11957		if ( previous !== this.element.val() ) {
11958			this._trigger( "change" );
11959		}
11960	};
11961}
11962
11963$.widget( "ui.spinner", {
11964	version: "1.12.1",
11965	defaultElement: "<input>",
11966	widgetEventPrefix: "spin",
11967	options: {
11968		classes: {
11969			"ui-spinner": "ui-corner-all",
11970			"ui-spinner-down": "ui-corner-br",
11971			"ui-spinner-up": "ui-corner-tr"
11972		},
11973		culture: null,
11974		icons: {
11975			down: "ui-icon-triangle-1-s",
11976			up: "ui-icon-triangle-1-n"
11977		},
11978		incremental: true,
11979		max: null,
11980		min: null,
11981		numberFormat: null,
11982		page: 10,
11983		step: 1,
11984
11985		change: null,
11986		spin: null,
11987		start: null,
11988		stop: null
11989	},
11990
11991	_create: function() {
11992
11993		// handle string values that need to be parsed
11994		this._setOption( "max", this.options.max );
11995		this._setOption( "min", this.options.min );
11996		this._setOption( "step", this.options.step );
11997
11998		// Only format if there is a value, prevents the field from being marked
11999		// as invalid in Firefox, see #9573.
12000		if ( this.value() !== "" ) {
12001
12002			// Format the value, but don't constrain.
12003			this._value( this.element.val(), true );
12004		}
12005
12006		this._draw();
12007		this._on( this._events );
12008		this._refresh();
12009
12010		// Turning off autocomplete prevents the browser from remembering the
12011		// value when navigating through history, so we re-enable autocomplete
12012		// if the page is unloaded before the widget is destroyed. #7790
12013		this._on( this.window, {
12014			beforeunload: function() {
12015				this.element.removeAttr( "autocomplete" );
12016			}
12017		} );
12018	},
12019
12020	_getCreateOptions: function() {
12021		var options = this._super();
12022		var element = this.element;
12023
12024		$.each( [ "min", "max", "step" ], function( i, option ) {
12025			var value = element.attr( option );
12026			if ( value != null && value.length ) {
12027				options[ option ] = value;
12028			}
12029		} );
12030
12031		return options;
12032	},
12033
12034	_events: {
12035		keydown: function( event ) {
12036			if ( this._start( event ) && this._keydown( event ) ) {
12037				event.preventDefault();
12038			}
12039		},
12040		keyup: "_stop",
12041		focus: function() {
12042			this.previous = this.element.val();
12043		},
12044		blur: function( event ) {
12045			if ( this.cancelBlur ) {
12046				delete this.cancelBlur;
12047				return;
12048			}
12049
12050			this._stop();
12051			this._refresh();
12052			if ( this.previous !== this.element.val() ) {
12053				this._trigger( "change", event );
12054			}
12055		},
12056		mousewheel: function( event, delta ) {
12057			if ( !delta ) {
12058				return;
12059			}
12060			if ( !this.spinning && !this._start( event ) ) {
12061				return false;
12062			}
12063
12064			this._spin( ( delta > 0 ? 1 : -1 ) * this.options.step, event );
12065			clearTimeout( this.mousewheelTimer );
12066			this.mousewheelTimer = this._delay( function() {
12067				if ( this.spinning ) {
12068					this._stop( event );
12069				}
12070			}, 100 );
12071			event.preventDefault();
12072		},
12073		"mousedown .ui-spinner-button": function( event ) {
12074			var previous;
12075
12076			// We never want the buttons to have focus; whenever the user is
12077			// interacting with the spinner, the focus should be on the input.
12078			// If the input is focused then this.previous is properly set from
12079			// when the input first received focus. If the input is not focused
12080			// then we need to set this.previous based on the value before spinning.
12081			previous = this.element[ 0 ] === $.ui.safeActiveElement( this.document[ 0 ] ) ?
12082				this.previous : this.element.val();
12083			function checkFocus() {
12084				var isActive = this.element[ 0 ] === $.ui.safeActiveElement( this.document[ 0 ] );
12085				if ( !isActive ) {
12086					this.element.trigger( "focus" );
12087					this.previous = previous;
12088
12089					// support: IE
12090					// IE sets focus asynchronously, so we need to check if focus
12091					// moved off of the input because the user clicked on the button.
12092					this._delay( function() {
12093						this.previous = previous;
12094					} );
12095				}
12096			}
12097
12098			// Ensure focus is on (or stays on) the text field
12099			event.preventDefault();
vendor: 5,986 bytes, lines 12100-12329
12100			checkFocus.call( this );
12101
12102			// Support: IE
12103			// IE doesn't prevent moving focus even with event.preventDefault()
12104			// so we set a flag to know when we should ignore the blur event
12105			// and check (again) if focus moved off of the input.
12106			this.cancelBlur = true;
12107			this._delay( function() {
12108				delete this.cancelBlur;
12109				checkFocus.call( this );
12110			} );
12111
12112			if ( this._start( event ) === false ) {
12113				return;
12114			}
12115
12116			this._repeat( null, $( event.currentTarget )
12117				.hasClass( "ui-spinner-up" ) ? 1 : -1, event );
12118		},
12119		"mouseup .ui-spinner-button": "_stop",
12120		"mouseenter .ui-spinner-button": function( event ) {
12121
12122			// button will add ui-state-active if mouse was down while mouseleave and kept down
12123			if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) {
12124				return;
12125			}
12126
12127			if ( this._start( event ) === false ) {
12128				return false;
12129			}
12130			this._repeat( null, $( event.currentTarget )
12131				.hasClass( "ui-spinner-up" ) ? 1 : -1, event );
12132		},
12133
12134		// TODO: do we really want to consider this a stop?
12135		// shouldn't we just stop the repeater and wait until mouseup before
12136		// we trigger the stop event?
12137		"mouseleave .ui-spinner-button": "_stop"
12138	},
12139
12140	// Support mobile enhanced option and make backcompat more sane
12141	_enhance: function() {
12142		this.uiSpinner = this.element
12143			.attr( "autocomplete", "off" )
12144			.wrap( "<span>" )
12145			.parent()
12146
12147				// Add buttons
12148				.append(
12149					"<a></a><a></a>"
12150				);
12151	},
12152
12153	_draw: function() {
12154		this._enhance();
12155
12156		this._addClass( this.uiSpinner, "ui-spinner", "ui-widget ui-widget-content" );
12157		this._addClass( "ui-spinner-input" );
12158
12159		this.element.attr( "role", "spinbutton" );
12160
12161		// Button bindings
12162		this.buttons = this.uiSpinner.children( "a" )
12163			.attr( "tabIndex", -1 )
12164			.attr( "aria-hidden", true )
12165			.button( {
12166				classes: {
12167					"ui-button": ""
12168				}
12169			} );
12170
12171		// TODO: Right now button does not support classes this is already updated in button PR
12172		this._removeClass( this.buttons, "ui-corner-all" );
12173
12174		this._addClass( this.buttons.first(), "ui-spinner-button ui-spinner-up" );
12175		this._addClass( this.buttons.last(), "ui-spinner-button ui-spinner-down" );
12176		this.buttons.first().button( {
12177			"icon": this.options.icons.up,
12178			"showLabel": false
12179		} );
12180		this.buttons.last().button( {
12181			"icon": this.options.icons.down,
12182			"showLabel": false
12183		} );
12184
12185		// IE 6 doesn't understand height: 50% for the buttons
12186		// unless the wrapper has an explicit height
12187		if ( this.buttons.height() > Math.ceil( this.uiSpinner.height() * 0.5 ) &&
12188				this.uiSpinner.height() > 0 ) {
12189			this.uiSpinner.height( this.uiSpinner.height() );
12190		}
12191	},
12192
12193	_keydown: function( event ) {
12194		var options = this.options,
12195			keyCode = $.ui.keyCode;
12196
12197		switch ( event.keyCode ) {
12198		case keyCode.UP:
12199			this._repeat( null, 1, event );
12200			return true;
12201		case keyCode.DOWN:
12202			this._repeat( null, -1, event );
12203			return true;
12204		case keyCode.PAGE_UP:
12205			this._repeat( null, options.page, event );
12206			return true;
12207		case keyCode.PAGE_DOWN:
12208			this._repeat( null, -options.page, event );
12209			return true;
12210		}
12211
12212		return false;
12213	},
12214
12215	_start: function( event ) {
12216		if ( !this.spinning && this._trigger( "start", event ) === false ) {
12217			return false;
12218		}
12219
12220		if ( !this.counter ) {
12221			this.counter = 1;
12222		}
12223		this.spinning = true;
12224		return true;
12225	},
12226
12227	_repeat: function( i, steps, event ) {
12228		i = i || 500;
12229
12230		clearTimeout( this.timer );
12231		this.timer = this._delay( function() {
12232			this._repeat( 40, steps, event );
12233		}, i );
12234
12235		this._spin( steps * this.options.step, event );
12236	},
12237
12238	_spin: function( step, event ) {
12239		var value = this.value() || 0;
12240
12241		if ( !this.counter ) {
12242			this.counter = 1;
12243		}
12244
12245		value = this._adjustValue( value + step * this._increment( this.counter ) );
12246
12247		if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false ) {
12248			this._value( value );
12249			this.counter++;
12250		}
12251	},
12252
12253	_increment: function( i ) {
12254		var incremental = this.options.incremental;
12255
12256		if ( incremental ) {
12257			return $.isFunction( incremental ) ?
12258				incremental( i ) :
12259				Math.floor( i * i * i / 50000 - i * i / 500 + 17 * i / 200 + 1 );
12260		}
12261
12262		return 1;
12263	},
12264
12265	_precision: function() {
12266		var precision = this._precisionOf( this.options.step );
12267		if ( this.options.min !== null ) {
12268			precision = Math.max( precision, this._precisionOf( this.options.min ) );
12269		}
12270		return precision;
12271	},
12272
12273	_precisionOf: function( num ) {
12274		var str = num.toString(),
12275			decimal = str.indexOf( "." );
12276		return decimal === -1 ? 0 : str.length - decimal - 1;
12277	},
12278
12279	_adjustValue: function( value ) {
12280		var base, aboveMin,
12281			options = this.options;
12282
12283		// Make sure we're at a valid step
12284		// - find out where we are relative to the base (min or 0)
12285		base = options.min !== null ? options.min : 0;
12286		aboveMin = value - base;
12287
12288		// - round to the nearest step
12289		aboveMin = Math.round( aboveMin / options.step ) * options.step;
12290
12291		// - rounding is based on 0, so adjust back to our base
12292		value = base + aboveMin;
12293
12294		// Fix precision from bad JS floating point math
12295		value = parseFloat( value.toFixed( this._precision() ) );
12296
12297		// Clamp the value
12298		if ( options.max !== null && value > options.max ) {
12299			return options.max;
12300		}
12301		if ( options.min !== null && value < options.min ) {
12302			return options.min;
12303		}
12304
12305		return value;
12306	},
12307
12308	_stop: function( event ) {
12309		if ( !this.spinning ) {
12310			return;
12311		}
12312
12313		clearTimeout( this.timer );
12314		clearTimeout( this.mousewheelTimer );
12315		this.counter = 0;
12316		this.spinning = false;
12317		this._trigger( "stop", event );
12318	},
12319
12320	_setOption: function( key, value ) {
12321		var prevValue, first, last;
12322
12323		if ( key === "culture" || key === "numberFormat" ) {
12324			prevValue = this._parse( this.element.val() );
12325			this.options[ key ] = value;
12326			this.element.val( this._format( prevValue ) );
12327			return;
12328		}
12329
vendor: 12,920 bytes, lines 12330-12826
12330		if ( key === "max" || key === "min" || key === "step" ) {
12331			if ( typeof value === "string" ) {
12332				value = this._parse( value );
12333			}
12334		}
12335		if ( key === "icons" ) {
12336			first = this.buttons.first().find( ".ui-icon" );
12337			this._removeClass( first, null, this.options.icons.up );
12338			this._addClass( first, null, value.up );
12339			last = this.buttons.last().find( ".ui-icon" );
12340			this._removeClass( last, null, this.options.icons.down );
12341			this._addClass( last, null, value.down );
12342		}
12343
12344		this._super( key, value );
12345	},
12346
12347	_setOptionDisabled: function( value ) {
12348		this._super( value );
12349
12350		this._toggleClass( this.uiSpinner, null, "ui-state-disabled", !!value );
12351		this.element.prop( "disabled", !!value );
12352		this.buttons.button( value ? "disable" : "enable" );
12353	},
12354
12355	_setOptions: spinnerModifer( function( options ) {
12356		this._super( options );
12357	} ),
12358
12359	_parse: function( val ) {
12360		if ( typeof val === "string" && val !== "" ) {
12361			val = window.Globalize && this.options.numberFormat ?
12362				Globalize.parseFloat( val, 10, this.options.culture ) : +val;
12363		}
12364		return val === "" || isNaN( val ) ? null : val;
12365	},
12366
12367	_format: function( value ) {
12368		if ( value === "" ) {
12369			return "";
12370		}
12371		return window.Globalize && this.options.numberFormat ?
12372			Globalize.format( value, this.options.numberFormat, this.options.culture ) :
12373			value;
12374	},
12375
12376	_refresh: function() {
12377		this.element.attr( {
12378			"aria-valuemin": this.options.min,
12379			"aria-valuemax": this.options.max,
12380
12381			// TODO: what should we do with values that can't be parsed?
12382			"aria-valuenow": this._parse( this.element.val() )
12383		} );
12384	},
12385
12386	isValid: function() {
12387		var value = this.value();
12388
12389		// Null is invalid
12390		if ( value === null ) {
12391			return false;
12392		}
12393
12394		// If value gets adjusted, it's invalid
12395		return value === this._adjustValue( value );
12396	},
12397
12398	// Update the value without triggering change
12399	_value: function( value, allowAny ) {
12400		var parsed;
12401		if ( value !== "" ) {
12402			parsed = this._parse( value );
12403			if ( parsed !== null ) {
12404				if ( !allowAny ) {
12405					parsed = this._adjustValue( parsed );
12406				}
12407				value = this._format( parsed );
12408			}
12409		}
12410		this.element.val( value );
12411		this._refresh();
12412	},
12413
12414	_destroy: function() {
12415		this.element
12416			.prop( "disabled", false )
12417			.removeAttr( "autocomplete role aria-valuemin aria-valuemax aria-valuenow" );
12418
12419		this.uiSpinner.replaceWith( this.element );
12420	},
12421
12422	stepUp: spinnerModifer( function( steps ) {
12423		this._stepUp( steps );
12424	} ),
12425	_stepUp: function( steps ) {
12426		if ( this._start() ) {
12427			this._spin( ( steps || 1 ) * this.options.step );
12428			this._stop();
12429		}
12430	},
12431
12432	stepDown: spinnerModifer( function( steps ) {
12433		this._stepDown( steps );
12434	} ),
12435	_stepDown: function( steps ) {
12436		if ( this._start() ) {
12437			this._spin( ( steps || 1 ) * -this.options.step );
12438			this._stop();
12439		}
12440	},
12441
12442	pageUp: spinnerModifer( function( pages ) {
12443		this._stepUp( ( pages || 1 ) * this.options.page );
12444	} ),
12445
12446	pageDown: spinnerModifer( function( pages ) {
12447		this._stepDown( ( pages || 1 ) * this.options.page );
12448	} ),
12449
12450	value: function( newVal ) {
12451		if ( !arguments.length ) {
12452			return this._parse( this.element.val() );
12453		}
12454		spinnerModifer( this._value ).call( this, newVal );
12455	},
12456
12457	widget: function() {
12458		return this.uiSpinner;
12459	}
12460} );
12461
12462// DEPRECATED
12463// TODO: switch return back to widget declaration at top of file when this is removed
12464if ( $.uiBackCompat !== false ) {
12465
12466	// Backcompat for spinner html extension points
12467	$.widget( "ui.spinner", $.ui.spinner, {
12468		_enhance: function() {
12469			this.uiSpinner = this.element
12470				.attr( "autocomplete", "off" )
12471				.wrap( this._uiSpinnerHtml() )
12472				.parent()
12473
12474					// Add buttons
12475					.append( this._buttonHtml() );
12476		},
12477		_uiSpinnerHtml: function() {
12478			return "<span>";
12479		},
12480
12481		_buttonHtml: function() {
12482			return "<a></a><a></a>";
12483		}
12484	} );
12485}
12486
12487var widgetsSpinner = $.ui.spinner;
12488
12489
12490/*!
12491 * jQuery UI Tabs 1.12.1
12492 * http://jqueryui.com
12493 *
12494 * Copyright jQuery Foundation and other contributors
12495 * Released under the MIT license.
12496 * http://jquery.org/license
12497 */
12498
12499//>>label: Tabs
12500//>>group: Widgets
12501//>>description: Transforms a set of container elements into a tab structure.
12502//>>docs: http://api.jqueryui.com/tabs/
12503//>>demos: http://jqueryui.com/tabs/
12504//>>css.structure: ../../themes/base/core.css
12505//>>css.structure: ../../themes/base/tabs.css
12506//>>css.theme: ../../themes/base/theme.css
12507
12508
12509
12510$.widget( "ui.tabs", {
12511	version: "1.12.1",
12512	delay: 300,
12513	options: {
12514		active: null,
12515		classes: {
12516			"ui-tabs": "ui-corner-all",
12517			"ui-tabs-nav": "ui-corner-all",
12518			"ui-tabs-panel": "ui-corner-bottom",
12519			"ui-tabs-tab": "ui-corner-top"
12520		},
12521		collapsible: false,
12522		event: "click",
12523		heightStyle: "content",
12524		hide: null,
12525		show: null,
12526
12527		// Callbacks
12528		activate: null,
12529		beforeActivate: null,
12530		beforeLoad: null,
12531		load: null
12532	},
12533
12534	_isLocal: ( function() {
12535		var rhash = /#.*$/;
12536
12537		return function( anchor ) {
12538			var anchorUrl, locationUrl;
12539
12540			anchorUrl = anchor.href.replace( rhash, "" );
12541			locationUrl = location.href.replace( rhash, "" );
12542
12543			// Decoding may throw an error if the URL isn't UTF-8 (#9518)
12544			try {
12545				anchorUrl = decodeURIComponent( anchorUrl );
12546			} catch ( error ) {}
12547			try {
12548				locationUrl = decodeURIComponent( locationUrl );
12549			} catch ( error ) {}
12550
12551			return anchor.hash.length > 1 && anchorUrl === locationUrl;
12552		};
12553	} )(),
12554
12555	_create: function() {
12556		var that = this,
12557			options = this.options;
12558
12559		this.running = false;
12560
12561		this._addClass( "ui-tabs", "ui-widget ui-widget-content" );
12562		this._toggleClass( "ui-tabs-collapsible", null, options.collapsible );
12563
12564		this._processTabs();
12565		options.active = this._initialActive();
12566
12567		// Take disabling tabs via class attribute from HTML
12568		// into account and update option properly.
12569		if ( $.isArray( options.disabled ) ) {
12570			options.disabled = $.unique( options.disabled.concat(
12571				$.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) {
12572					return that.tabs.index( li );
12573				} )
12574			) ).sort();
12575		}
12576
12577		// Check for length avoids error when initializing empty list
12578		if ( this.options.active !== false && this.anchors.length ) {
12579			this.active = this._findActive( options.active );
12580		} else {
12581			this.active = $();
12582		}
12583
12584		this._refresh();
12585
12586		if ( this.active.length ) {
12587			this.load( options.active );
12588		}
12589	},
12590
12591	_initialActive: function() {
12592		var active = this.options.active,
12593			collapsible = this.options.collapsible,
12594			locationHash = location.hash.substring( 1 );
12595
12596		if ( active === null ) {
12597
12598			// check the fragment identifier in the URL
12599			if ( locationHash ) {
12600				this.tabs.each( function( i, tab ) {
12601					if ( $( tab ).attr( "aria-controls" ) === locationHash ) {
12602						active = i;
12603						return false;
12604					}
12605				} );
12606			}
12607
12608			// Check for a tab marked active via a class
12609			if ( active === null ) {
12610				active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) );
12611			}
12612
12613			// No active tab, set to false
12614			if ( active === null || active === -1 ) {
12615				active = this.tabs.length ? 0 : false;
12616			}
12617		}
12618
12619		// Handle numbers: negative, out of range
12620		if ( active !== false ) {
12621			active = this.tabs.index( this.tabs.eq( active ) );
12622			if ( active === -1 ) {
12623				active = collapsible ? false : 0;
12624			}
12625		}
12626
12627		// Don't allow collapsible: false and active: false
12628		if ( !collapsible && active === false && this.anchors.length ) {
12629			active = 0;
12630		}
12631
12632		return active;
12633	},
12634
12635	_getCreateEventData: function() {
12636		return {
12637			tab: this.active,
12638			panel: !this.active.length ? $() : this._getPanelForTab( this.active )
12639		};
12640	},
12641
12642	_tabKeydown: function( event ) {
12643		var focusedTab = $( $.ui.safeActiveElement( this.document[ 0 ] ) ).closest( "li" ),
12644			selectedIndex = this.tabs.index( focusedTab ),
12645			goingForward = true;
12646
12647		if ( this._handlePageNav( event ) ) {
12648			return;
12649		}
12650
12651		switch ( event.keyCode ) {
12652		case $.ui.keyCode.RIGHT:
12653		case $.ui.keyCode.DOWN:
12654			selectedIndex++;
12655			break;
12656		case $.ui.keyCode.UP:
12657		case $.ui.keyCode.LEFT:
12658			goingForward = false;
12659			selectedIndex--;
12660			break;
12661		case $.ui.keyCode.END:
12662			selectedIndex = this.anchors.length - 1;
12663			break;
12664		case $.ui.keyCode.HOME:
12665			selectedIndex = 0;
12666			break;
12667		case $.ui.keyCode.SPACE:
12668
12669			// Activate only, no collapsing
12670			event.preventDefault();
12671			clearTimeout( this.activating );
12672			this._activate( selectedIndex );
12673			return;
12674		case $.ui.keyCode.ENTER:
12675
12676			// Toggle (cancel delayed activation, allow collapsing)
12677			event.preventDefault();
12678			clearTimeout( this.activating );
12679
12680			// Determine if we should collapse or activate
12681			this._activate( selectedIndex === this.options.active ? false : selectedIndex );
12682			return;
12683		default:
12684			return;
12685		}
12686
12687		// Focus the appropriate tab, based on which key was pressed
12688		event.preventDefault();
12689		clearTimeout( this.activating );
12690		selectedIndex = this._focusNextTab( selectedIndex, goingForward );
12691
12692		// Navigating with control/command key will prevent automatic activation
12693		if ( !event.ctrlKey && !event.metaKey ) {
12694
12695			// Update aria-selected immediately so that AT think the tab is already selected.
12696			// Otherwise AT may confuse the user by stating that they need to activate the tab,
12697			// but the tab will already be activated by the time the announcement finishes.
12698			focusedTab.attr( "aria-selected", "false" );
12699			this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" );
12700
12701			this.activating = this._delay( function() {
12702				this.option( "active", selectedIndex );
12703			}, this.delay );
12704		}
12705	},
12706
12707	_panelKeydown: function( event ) {
12708		if ( this._handlePageNav( event ) ) {
12709			return;
12710		}
12711
12712		// Ctrl+up moves focus to the current tab
12713		if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) {
12714			event.preventDefault();
12715			this.active.trigger( "focus" );
12716		}
12717	},
12718
12719	// Alt+page up/down moves focus to the previous/next tab (and activates)
12720	_handlePageNav: function( event ) {
12721		if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) {
12722			this._activate( this._focusNextTab( this.options.active - 1, false ) );
12723			return true;
12724		}
12725		if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) {
12726			this._activate( this._focusNextTab( this.options.active + 1, true ) );
12727			return true;
12728		}
12729	},
12730
12731	_findNextTab: function( index, goingForward ) {
12732		var lastTabIndex = this.tabs.length - 1;
12733
12734		function constrain() {
12735			if ( index > lastTabIndex ) {
12736				index = 0;
12737			}
12738			if ( index < 0 ) {
12739				index = lastTabIndex;
12740			}
12741			return index;
12742		}
12743
12744		while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) {
12745			index = goingForward ? index + 1 : index - 1;
12746		}
12747
12748		return index;
12749	},
12750
12751	_focusNextTab: function( index, goingForward ) {
12752		index = this._findNextTab( index, goingForward );
12753		this.tabs.eq( index ).trigger( "focus" );
12754		return index;
12755	},
12756
12757	_setOption: function( key, value ) {
12758		if ( key === "active" ) {
12759
12760			// _activate() will handle invalid values and update this.options
12761			this._activate( value );
12762			return;
12763		}
12764
12765		this._super( key, value );
12766
12767		if ( key === "collapsible" ) {
12768			this._toggleClass( "ui-tabs-collapsible", null, value );
12769
12770			// Setting collapsible: false while collapsed; open first panel
12771			if ( !value && this.options.active === false ) {
12772				this._activate( 0 );
12773			}
12774		}
12775
12776		if ( key === "event" ) {
12777			this._setupEvents( value );
12778		}
12779
12780		if ( key === "heightStyle" ) {
12781			this._setupHeightStyle( value );
12782		}
12783	},
12784
12785	_sanitizeSelector: function( hash ) {
12786		return hash ? hash.replace( /[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&" ) : "";
12787	},
12788
12789	refresh: function() {
12790		var options = this.options,
12791			lis = this.tablist.children( ":has(a[href])" );
12792
12793		// Get disabled tabs from class attribute from HTML
12794		// this will get converted to a boolean if needed in _refresh()
12795		options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) {
12796			return lis.index( tab );
12797		} );
12798
12799		this._processTabs();
12800
12801		// Was collapsed or no tabs
12802		if ( options.active === false || !this.anchors.length ) {
12803			options.active = false;
12804			this.active = $();
12805
12806		// was active, but active tab is gone
12807		} else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) {
12808
12809			// all remaining tabs are disabled
12810			if ( this.tabs.length === options.disabled.length ) {
12811				options.active = false;
12812				this.active = $();
12813
12814			// activate previous tab
12815			} else {
12816				this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) );
12817			}
12818
12819		// was active, active tab still exists
12820		} else {
12821
12822			// make sure active index is correct
12823			options.active = this.tabs.index( this.active );
12824		}
12825
12826		this._refresh();
vendor: 18,906 bytes, lines 12827-13532
12827	},
12828
12829	_refresh: function() {
12830		this._setOptionDisabled( this.options.disabled );
12831		this._setupEvents( this.options.event );
12832		this._setupHeightStyle( this.options.heightStyle );
12833
12834		this.tabs.not( this.active ).attr( {
12835			"aria-selected": "false",
12836			"aria-expanded": "false",
12837			tabIndex: -1
12838		} );
12839		this.panels.not( this._getPanelForTab( this.active ) )
12840			.hide()
12841			.attr( {
12842				"aria-hidden": "true"
12843			} );
12844
12845		// Make sure one tab is in the tab order
12846		if ( !this.active.length ) {
12847			this.tabs.eq( 0 ).attr( "tabIndex", 0 );
12848		} else {
12849			this.active
12850				.attr( {
12851					"aria-selected": "true",
12852					"aria-expanded": "true",
12853					tabIndex: 0
12854				} );
12855			this._addClass( this.active, "ui-tabs-active", "ui-state-active" );
12856			this._getPanelForTab( this.active )
12857				.show()
12858				.attr( {
12859					"aria-hidden": "false"
12860				} );
12861		}
12862	},
12863
12864	_processTabs: function() {
12865		var that = this,
12866			prevTabs = this.tabs,
12867			prevAnchors = this.anchors,
12868			prevPanels = this.panels;
12869
12870		this.tablist = this._getList().attr( "role", "tablist" );
12871		this._addClass( this.tablist, "ui-tabs-nav",
12872			"ui-helper-reset ui-helper-clearfix ui-widget-header" );
12873
12874		// Prevent users from focusing disabled tabs via click
12875		this.tablist
12876			.on( "mousedown" + this.eventNamespace, "> li", function( event ) {
12877				if ( $( this ).is( ".ui-state-disabled" ) ) {
12878					event.preventDefault();
12879				}
12880			} )
12881
12882			// Support: IE <9
12883			// Preventing the default action in mousedown doesn't prevent IE
12884			// from focusing the element, so if the anchor gets focused, blur.
12885			// We don't have to worry about focusing the previously focused
12886			// element since clicking on a non-focusable element should focus
12887			// the body anyway.
12888			.on( "focus" + this.eventNamespace, ".ui-tabs-anchor", function() {
12889				if ( $( this ).closest( "li" ).is( ".ui-state-disabled" ) ) {
12890					this.blur();
12891				}
12892			} );
12893
12894		this.tabs = this.tablist.find( "> li:has(a[href])" )
12895			.attr( {
12896				role: "tab",
12897				tabIndex: -1
12898			} );
12899		this._addClass( this.tabs, "ui-tabs-tab", "ui-state-default" );
12900
12901		this.anchors = this.tabs.map( function() {
12902			return $( "a", this )[ 0 ];
12903		} )
12904			.attr( {
12905				role: "presentation",
12906				tabIndex: -1
12907			} );
12908		this._addClass( this.anchors, "ui-tabs-anchor" );
12909
12910		this.panels = $();
12911
12912		this.anchors.each( function( i, anchor ) {
12913			var selector, panel, panelId,
12914				anchorId = $( anchor ).uniqueId().attr( "id" ),
12915				tab = $( anchor ).closest( "li" ),
12916				originalAriaControls = tab.attr( "aria-controls" );
12917
12918			// Inline tab
12919			if ( that._isLocal( anchor ) ) {
12920				selector = anchor.hash;
12921				panelId = selector.substring( 1 );
12922				panel = that.element.find( that._sanitizeSelector( selector ) );
12923
12924			// remote tab
12925			} else {
12926
12927				// If the tab doesn't already have aria-controls,
12928				// generate an id by using a throw-away element
12929				panelId = tab.attr( "aria-controls" ) || $( {} ).uniqueId()[ 0 ].id;
12930				selector = "#" + panelId;
12931				panel = that.element.find( selector );
12932				if ( !panel.length ) {
12933					panel = that._createPanel( panelId );
12934					panel.insertAfter( that.panels[ i - 1 ] || that.tablist );
12935				}
12936				panel.attr( "aria-live", "polite" );
12937			}
12938
12939			if ( panel.length ) {
12940				that.panels = that.panels.add( panel );
12941			}
12942			if ( originalAriaControls ) {
12943				tab.data( "ui-tabs-aria-controls", originalAriaControls );
12944			}
12945			tab.attr( {
12946				"aria-controls": panelId,
12947				"aria-labelledby": anchorId
12948			} );
12949			panel.attr( "aria-labelledby", anchorId );
12950		} );
12951
12952		this.panels.attr( "role", "tabpanel" );
12953		this._addClass( this.panels, "ui-tabs-panel", "ui-widget-content" );
12954
12955		// Avoid memory leaks (#10056)
12956		if ( prevTabs ) {
12957			this._off( prevTabs.not( this.tabs ) );
12958			this._off( prevAnchors.not( this.anchors ) );
12959			this._off( prevPanels.not( this.panels ) );
12960		}
12961	},
12962
12963	// Allow overriding how to find the list for rare usage scenarios (#7715)
12964	_getList: function() {
12965		return this.tablist || this.element.find( "ol, ul" ).eq( 0 );
12966	},
12967
12968	_createPanel: function( id ) {
12969		return $( "<div>" )
12970			.attr( "id", id )
12971			.data( "ui-tabs-destroy", true );
12972	},
12973
12974	_setOptionDisabled: function( disabled ) {
12975		var currentItem, li, i;
12976
12977		if ( $.isArray( disabled ) ) {
12978			if ( !disabled.length ) {
12979				disabled = false;
12980			} else if ( disabled.length === this.anchors.length ) {
12981				disabled = true;
12982			}
12983		}
12984
12985		// Disable tabs
12986		for ( i = 0; ( li = this.tabs[ i ] ); i++ ) {
12987			currentItem = $( li );
12988			if ( disabled === true || $.inArray( i, disabled ) !== -1 ) {
12989				currentItem.attr( "aria-disabled", "true" );
12990				this._addClass( currentItem, null, "ui-state-disabled" );
12991			} else {
12992				currentItem.removeAttr( "aria-disabled" );
12993				this._removeClass( currentItem, null, "ui-state-disabled" );
12994			}
12995		}
12996
12997		this.options.disabled = disabled;
12998
12999		this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null,
13000			disabled === true );
13001	},
13002
13003	_setupEvents: function( event ) {
13004		var events = {};
13005		if ( event ) {
13006			$.each( event.split( " " ), function( index, eventName ) {
13007				events[ eventName ] = "_eventHandler";
13008			} );
13009		}
13010
13011		this._off( this.anchors.add( this.tabs ).add( this.panels ) );
13012
13013		// Always prevent the default action, even when disabled
13014		this._on( true, this.anchors, {
13015			click: function( event ) {
13016				event.preventDefault();
13017			}
13018		} );
13019		this._on( this.anchors, events );
13020		this._on( this.tabs, { keydown: "_tabKeydown" } );
13021		this._on( this.panels, { keydown: "_panelKeydown" } );
13022
13023		this._focusable( this.tabs );
13024		this._hoverable( this.tabs );
13025	},
13026
13027	_setupHeightStyle: function( heightStyle ) {
13028		var maxHeight,
13029			parent = this.element.parent();
13030
13031		if ( heightStyle === "fill" ) {
13032			maxHeight = parent.height();
13033			maxHeight -= this.element.outerHeight() - this.element.height();
13034
13035			this.element.siblings( ":visible" ).each( function() {
13036				var elem = $( this ),
13037					position = elem.css( "position" );
13038
13039				if ( position === "absolute" || position === "fixed" ) {
13040					return;
13041				}
13042				maxHeight -= elem.outerHeight( true );
13043			} );
13044
13045			this.element.children().not( this.panels ).each( function() {
13046				maxHeight -= $( this ).outerHeight( true );
13047			} );
13048
13049			this.panels.each( function() {
13050				$( this ).height( Math.max( 0, maxHeight -
13051					$( this ).innerHeight() + $( this ).height() ) );
13052			} )
13053				.css( "overflow", "auto" );
13054		} else if ( heightStyle === "auto" ) {
13055			maxHeight = 0;
13056			this.panels.each( function() {
13057				maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
13058			} ).height( maxHeight );
13059		}
13060	},
13061
13062	_eventHandler: function( event ) {
13063		var options = this.options,
13064			active = this.active,
13065			anchor = $( event.currentTarget ),
13066			tab = anchor.closest( "li" ),
13067			clickedIsActive = tab[ 0 ] === active[ 0 ],
13068			collapsing = clickedIsActive && options.collapsible,
13069			toShow = collapsing ? $() : this._getPanelForTab( tab ),
13070			toHide = !active.length ? $() : this._getPanelForTab( active ),
13071			eventData = {
13072				oldTab: active,
13073				oldPanel: toHide,
13074				newTab: collapsing ? $() : tab,
13075				newPanel: toShow
13076			};
13077
13078		event.preventDefault();
13079
13080		if ( tab.hasClass( "ui-state-disabled" ) ||
13081
13082				// tab is already loading
13083				tab.hasClass( "ui-tabs-loading" ) ||
13084
13085				// can't switch durning an animation
13086				this.running ||
13087
13088				// click on active header, but not collapsible
13089				( clickedIsActive && !options.collapsible ) ||
13090
13091				// allow canceling activation
13092				( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
13093			return;
13094		}
13095
13096		options.active = collapsing ? false : this.tabs.index( tab );
13097
13098		this.active = clickedIsActive ? $() : tab;
13099		if ( this.xhr ) {
13100			this.xhr.abort();
13101		}
13102
13103		if ( !toHide.length && !toShow.length ) {
13104			$.error( "jQuery UI Tabs: Mismatching fragment identifier." );
13105		}
13106
13107		if ( toShow.length ) {
13108			this.load( this.tabs.index( tab ), event );
13109		}
13110		this._toggle( event, eventData );
13111	},
13112
13113	// Handles show/hide for selecting tabs
13114	_toggle: function( event, eventData ) {
13115		var that = this,
13116			toShow = eventData.newPanel,
13117			toHide = eventData.oldPanel;
13118
13119		this.running = true;
13120
13121		function complete() {
13122			that.running = false;
13123			that._trigger( "activate", event, eventData );
13124		}
13125
13126		function show() {
13127			that._addClass( eventData.newTab.closest( "li" ), "ui-tabs-active", "ui-state-active" );
13128
13129			if ( toShow.length && that.options.show ) {
13130				that._show( toShow, that.options.show, complete );
13131			} else {
13132				toShow.show();
13133				complete();
13134			}
13135		}
13136
13137		// Start out by hiding, then showing, then completing
13138		if ( toHide.length && this.options.hide ) {
13139			this._hide( toHide, this.options.hide, function() {
13140				that._removeClass( eventData.oldTab.closest( "li" ),
13141					"ui-tabs-active", "ui-state-active" );
13142				show();
13143			} );
13144		} else {
13145			this._removeClass( eventData.oldTab.closest( "li" ),
13146				"ui-tabs-active", "ui-state-active" );
13147			toHide.hide();
13148			show();
13149		}
13150
13151		toHide.attr( "aria-hidden", "true" );
13152		eventData.oldTab.attr( {
13153			"aria-selected": "false",
13154			"aria-expanded": "false"
13155		} );
13156
13157		// If we're switching tabs, remove the old tab from the tab order.
13158		// If we're opening from collapsed state, remove the previous tab from the tab order.
13159		// If we're collapsing, then keep the collapsing tab in the tab order.
13160		if ( toShow.length && toHide.length ) {
13161			eventData.oldTab.attr( "tabIndex", -1 );
13162		} else if ( toShow.length ) {
13163			this.tabs.filter( function() {
13164				return $( this ).attr( "tabIndex" ) === 0;
13165			} )
13166				.attr( "tabIndex", -1 );
13167		}
13168
13169		toShow.attr( "aria-hidden", "false" );
13170		eventData.newTab.attr( {
13171			"aria-selected": "true",
13172			"aria-expanded": "true",
13173			tabIndex: 0
13174		} );
13175	},
13176
13177	_activate: function( index ) {
13178		var anchor,
13179			active = this._findActive( index );
13180
13181		// Trying to activate the already active panel
13182		if ( active[ 0 ] === this.active[ 0 ] ) {
13183			return;
13184		}
13185
13186		// Trying to collapse, simulate a click on the current active header
13187		if ( !active.length ) {
13188			active = this.active;
13189		}
13190
13191		anchor = active.find( ".ui-tabs-anchor" )[ 0 ];
13192		this._eventHandler( {
13193			target: anchor,
13194			currentTarget: anchor,
13195			preventDefault: $.noop
13196		} );
13197	},
13198
13199	_findActive: function( index ) {
13200		return index === false ? $() : this.tabs.eq( index );
13201	},
13202
13203	_getIndex: function( index ) {
13204
13205		// meta-function to give users option to provide a href string instead of a numerical index.
13206		if ( typeof index === "string" ) {
13207			index = this.anchors.index( this.anchors.filter( "[href$='" +
13208				$.ui.escapeSelector( index ) + "']" ) );
13209		}
13210
13211		return index;
13212	},
13213
13214	_destroy: function() {
13215		if ( this.xhr ) {
13216			this.xhr.abort();
13217		}
13218
13219		this.tablist
13220			.removeAttr( "role" )
13221			.off( this.eventNamespace );
13222
13223		this.anchors
13224			.removeAttr( "role tabIndex" )
13225			.removeUniqueId();
13226
13227		this.tabs.add( this.panels ).each( function() {
13228			if ( $.data( this, "ui-tabs-destroy" ) ) {
13229				$( this ).remove();
13230			} else {
13231				$( this ).removeAttr( "role tabIndex " +
13232					"aria-live aria-busy aria-selected aria-labelledby aria-hidden aria-expanded" );
13233			}
13234		} );
13235
13236		this.tabs.each( function() {
13237			var li = $( this ),
13238				prev = li.data( "ui-tabs-aria-controls" );
13239			if ( prev ) {
13240				li
13241					.attr( "aria-controls", prev )
13242					.removeData( "ui-tabs-aria-controls" );
13243			} else {
13244				li.removeAttr( "aria-controls" );
13245			}
13246		} );
13247
13248		this.panels.show();
13249
13250		if ( this.options.heightStyle !== "content" ) {
13251			this.panels.css( "height", "" );
13252		}
13253	},
13254
13255	enable: function( index ) {
13256		var disabled = this.options.disabled;
13257		if ( disabled === false ) {
13258			return;
13259		}
13260
13261		if ( index === undefined ) {
13262			disabled = false;
13263		} else {
13264			index = this._getIndex( index );
13265			if ( $.isArray( disabled ) ) {
13266				disabled = $.map( disabled, function( num ) {
13267					return num !== index ? num : null;
13268				} );
13269			} else {
13270				disabled = $.map( this.tabs, function( li, num ) {
13271					return num !== index ? num : null;
13272				} );
13273			}
13274		}
13275		this._setOptionDisabled( disabled );
13276	},
13277
13278	disable: function( index ) {
13279		var disabled = this.options.disabled;
13280		if ( disabled === true ) {
13281			return;
13282		}
13283
13284		if ( index === undefined ) {
13285			disabled = true;
13286		} else {
13287			index = this._getIndex( index );
13288			if ( $.inArray( index, disabled ) !== -1 ) {
13289				return;
13290			}
13291			if ( $.isArray( disabled ) ) {
13292				disabled = $.merge( [ index ], disabled ).sort();
13293			} else {
13294				disabled = [ index ];
13295			}
13296		}
13297		this._setOptionDisabled( disabled );
13298	},
13299
13300	load: function( index, event ) {
13301		index = this._getIndex( index );
13302		var that = this,
13303			tab = this.tabs.eq( index ),
13304			anchor = tab.find( ".ui-tabs-anchor" ),
13305			panel = this._getPanelForTab( tab ),
13306			eventData = {
13307				tab: tab,
13308				panel: panel
13309			},
13310			complete = function( jqXHR, status ) {
13311				if ( status === "abort" ) {
13312					that.panels.stop( false, true );
13313				}
13314
13315				that._removeClass( tab, "ui-tabs-loading" );
13316				panel.removeAttr( "aria-busy" );
13317
13318				if ( jqXHR === that.xhr ) {
13319					delete that.xhr;
13320				}
13321			};
13322
13323		// Not remote
13324		if ( this._isLocal( anchor[ 0 ] ) ) {
13325			return;
13326		}
13327
13328		this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) );
13329
13330		// Support: jQuery <1.8
13331		// jQuery <1.8 returns false if the request is canceled in beforeSend,
13332		// but as of 1.8, $.ajax() always returns a jqXHR object.
13333		if ( this.xhr && this.xhr.statusText !== "canceled" ) {
13334			this._addClass( tab, "ui-tabs-loading" );
13335			panel.attr( "aria-busy", "true" );
13336
13337			this.xhr
13338				.done( function( response, status, jqXHR ) {
13339
13340					// support: jQuery <1.8
13341					// http://bugs.jquery.com/ticket/11778
13342					setTimeout( function() {
13343						panel.html( response );
13344						that._trigger( "load", event, eventData );
13345
13346						complete( jqXHR, status );
13347					}, 1 );
13348				} )
13349				.fail( function( jqXHR, status ) {
13350
13351					// support: jQuery <1.8
13352					// http://bugs.jquery.com/ticket/11778
13353					setTimeout( function() {
13354						complete( jqXHR, status );
13355					}, 1 );
13356				} );
13357		}
13358	},
13359
13360	_ajaxSettings: function( anchor, event, eventData ) {
13361		var that = this;
13362		return {
13363
13364			// Support: IE <11 only
13365			// Strip any hash that exists to prevent errors with the Ajax request
13366			url: anchor.attr( "href" ).replace( /#.*$/, "" ),
13367			beforeSend: function( jqXHR, settings ) {
13368				return that._trigger( "beforeLoad", event,
13369					$.extend( { jqXHR: jqXHR, ajaxSettings: settings }, eventData ) );
13370			}
13371		};
13372	},
13373
13374	_getPanelForTab: function( tab ) {
13375		var id = $( tab ).attr( "aria-controls" );
13376		return this.element.find( this._sanitizeSelector( "#" + id ) );
13377	}
13378} );
13379
13380// DEPRECATED
13381// TODO: Switch return back to widget declaration at top of file when this is removed
13382if ( $.uiBackCompat !== false ) {
13383
13384	// Backcompat for ui-tab class (now ui-tabs-tab)
13385	$.widget( "ui.tabs", $.ui.tabs, {
13386		_processTabs: function() {
13387			this._superApply( arguments );
13388			this._addClass( this.tabs, "ui-tab" );
13389		}
13390	} );
13391}
13392
13393var widgetsTabs = $.ui.tabs;
13394
13395
13396/*!
13397 * jQuery UI Tooltip 1.12.1
13398 * http://jqueryui.com
13399 *
13400 * Copyright jQuery Foundation and other contributors
13401 * Released under the MIT license.
13402 * http://jquery.org/license
13403 */
13404
13405//>>label: Tooltip
13406//>>group: Widgets
13407//>>description: Shows additional information for any element on hover or focus.
13408//>>docs: http://api.jqueryui.com/tooltip/
13409//>>demos: http://jqueryui.com/tooltip/
13410//>>css.structure: ../../themes/base/core.css
13411//>>css.structure: ../../themes/base/tooltip.css
13412//>>css.theme: ../../themes/base/theme.css
13413
13414
13415
13416$.widget( "ui.tooltip", {
13417	version: "1.12.1",
13418	options: {
13419		classes: {
13420			"ui-tooltip": "ui-corner-all ui-widget-shadow"
13421		},
13422		content: function() {
13423
13424			// support: IE<9, Opera in jQuery <1.7
13425			// .text() can't accept undefined, so coerce to a string
13426			var title = $( this ).attr( "title" ) || "";
13427
13428			// Escape title, since we're going from an attribute to raw HTML
13429			return $( "<a>" ).text( title ).html();
13430		},
13431		hide: true,
13432
13433		// Disabled elements have inconsistent behavior across browsers (#8661)
13434		items: "[title]:not([disabled])",
13435		position: {
13436			my: "left top+15",
13437			at: "left bottom",
13438			collision: "flipfit flip"
13439		},
13440		show: true,
13441		track: false,
13442
13443		// Callbacks
13444		close: null,
13445		open: null
13446	},
13447
13448	_addDescribedBy: function( elem, id ) {
13449		var describedby = ( elem.attr( "aria-describedby" ) || "" ).split( /\s+/ );
13450		describedby.push( id );
13451		elem
13452			.data( "ui-tooltip-id", id )
13453			.attr( "aria-describedby", $.trim( describedby.join( " " ) ) );
13454	},
13455
13456	_removeDescribedBy: function( elem ) {
13457		var id = elem.data( "ui-tooltip-id" ),
13458			describedby = ( elem.attr( "aria-describedby" ) || "" ).split( /\s+/ ),
13459			index = $.inArray( id, describedby );
13460
13461		if ( index !== -1 ) {
13462			describedby.splice( index, 1 );
13463		}
13464
13465		elem.removeData( "ui-tooltip-id" );
13466		describedby = $.trim( describedby.join( " " ) );
13467		if ( describedby ) {
13468			elem.attr( "aria-describedby", describedby );
13469		} else {
13470			elem.removeAttr( "aria-describedby" );
13471		}
13472	},
13473
13474	_create: function() {
13475		this._on( {
13476			mouseover: "open",
13477			focusin: "open"
13478		} );
13479
13480		// IDs of generated tooltips, needed for destroy
13481		this.tooltips = {};
13482
13483		// IDs of parent tooltips where we removed the title attribute
13484		this.parents = {};
13485
13486		// Append the aria-live region so tooltips announce correctly
13487		this.liveRegion = $( "<div>" )
13488			.attr( {
13489				role: "log",
13490				"aria-live": "assertive",
13491				"aria-relevant": "additions"
13492			} )
13493			.appendTo( this.document[ 0 ].body );
13494		this._addClass( this.liveRegion, null, "ui-helper-hidden-accessible" );
13495
13496		this.disabledTitles = $( [] );
13497	},
13498
13499	_setOption: function( key, value ) {
13500		var that = this;
13501
13502		this._super( key, value );
13503
13504		if ( key === "content" ) {
13505			$.each( this.tooltips, function( id, tooltipData ) {
13506				that._updateContent( tooltipData.element );
13507			} );
13508		}
13509	},
13510
13511	_setOptionDisabled: function( value ) {
13512		this[ value ? "_disable" : "_enable" ]();
13513	},
13514
13515	_disable: function() {
13516		var that = this;
13517
13518		// Close open tooltips
13519		$.each( this.tooltips, function( id, tooltipData ) {
13520			var event = $.Event( "blur" );
13521			event.target = event.currentTarget = tooltipData.element[ 0 ];
13522			that.close( event, true );
13523		} );
13524
13525		// Remove title attributes to prevent native tooltips
13526		this.disabledTitles = this.disabledTitles.add(
13527			this.element.find( this.options.items ).addBack()
13528				.filter( function() {
13529					var element = $( this );
13530					if ( element.is( "[title]" ) ) {
13531						return element
13532							.data( "ui-tooltip-title", element.attr( "title" ) )
vendor: 4,119 bytes, lines 13533-13668
13533							.removeAttr( "title" );
13534					}
13535				} )
13536		);
13537	},
13538
13539	_enable: function() {
13540
13541		// restore title attributes
13542		this.disabledTitles.each( function() {
13543			var element = $( this );
13544			if ( element.data( "ui-tooltip-title" ) ) {
13545				element.attr( "title", element.data( "ui-tooltip-title" ) );
13546			}
13547		} );
13548		this.disabledTitles = $( [] );
13549	},
13550
13551	open: function( event ) {
13552		var that = this,
13553			target = $( event ? event.target : this.element )
13554
13555				// we need closest here due to mouseover bubbling,
13556				// but always pointing at the same event target
13557				.closest( this.options.items );
13558
13559		// No element to show a tooltip for or the tooltip is already open
13560		if ( !target.length || target.data( "ui-tooltip-id" ) ) {
13561			return;
13562		}
13563
13564		if ( target.attr( "title" ) ) {
13565			target.data( "ui-tooltip-title", target.attr( "title" ) );
13566		}
13567
13568		target.data( "ui-tooltip-open", true );
13569
13570		// Kill parent tooltips, custom or native, for hover
13571		if ( event && event.type === "mouseover" ) {
13572			target.parents().each( function() {
13573				var parent = $( this ),
13574					blurEvent;
13575				if ( parent.data( "ui-tooltip-open" ) ) {
13576					blurEvent = $.Event( "blur" );
13577					blurEvent.target = blurEvent.currentTarget = this;
13578					that.close( blurEvent, true );
13579				}
13580				if ( parent.attr( "title" ) ) {
13581					parent.uniqueId();
13582					that.parents[ this.id ] = {
13583						element: this,
13584						title: parent.attr( "title" )
13585					};
13586					parent.attr( "title", "" );
13587				}
13588			} );
13589		}
13590
13591		this._registerCloseHandlers( event, target );
13592		this._updateContent( target, event );
13593	},
13594
13595	_updateContent: function( target, event ) {
13596		var content,
13597			contentOption = this.options.content,
13598			that = this,
13599			eventType = event ? event.type : null;
13600
13601		if ( typeof contentOption === "string" || contentOption.nodeType ||
13602				contentOption.jquery ) {
13603			return this._open( event, target, contentOption );
13604		}
13605
13606		content = contentOption.call( target[ 0 ], function( response ) {
13607
13608			// IE may instantly serve a cached response for ajax requests
13609			// delay this call to _open so the other call to _open runs first
13610			that._delay( function() {
13611
13612				// Ignore async response if tooltip was closed already
13613				if ( !target.data( "ui-tooltip-open" ) ) {
13614					return;
13615				}
13616
13617				// JQuery creates a special event for focusin when it doesn't
13618				// exist natively. To improve performance, the native event
13619				// object is reused and the type is changed. Therefore, we can't
13620				// rely on the type being correct after the event finished
13621				// bubbling, so we set it back to the previous value. (#8740)
13622				if ( event ) {
13623					event.type = eventType;
13624				}
13625				this._open( event, target, response );
13626			} );
13627		} );
13628		if ( content ) {
13629			this._open( event, target, content );
13630		}
13631	},
13632
13633	_open: function( event, target, content ) {
13634		var tooltipData, tooltip, delayedShow, a11yContent,
13635			positionOption = $.extend( {}, this.options.position );
13636
13637		if ( !content ) {
13638			return;
13639		}
13640
13641		// Content can be updated multiple times. If the tooltip already
13642		// exists, then just update the content and bail.
13643		tooltipData = this._find( target );
13644		if ( tooltipData ) {
13645			tooltipData.tooltip.find( ".ui-tooltip-content" ).html( content );
13646			return;
13647		}
13648
13649		// If we have a title, clear it to prevent the native tooltip
13650		// we have to check first to avoid defining a title if none exists
13651		// (we don't want to cause an element to start matching [title])
13652		//
13653		// We use removeAttr only for key events, to allow IE to export the correct
13654		// accessible attributes. For mouse events, set to empty string to avoid
13655		// native tooltip showing up (happens only when removing inside mouseover).
13656		if ( target.is( "[title]" ) ) {
13657			if ( event && event.type === "mouseover" ) {
13658				target.attr( "title", "" );
13659			} else {
13660				target.removeAttr( "title" );
13661			}
13662		}
13663
13664		tooltipData = this._tooltip( target );
13665		tooltip = tooltipData.tooltip;
13666		this._addDescribedBy( target, tooltip.attr( "id" ) );
13667		tooltip.find( ".ui-tooltip-content" ).html( content );
13668
vendor: 6,816 bytes, lines 13669-13904
13669		// Support: Voiceover on OS X, JAWS on IE <= 9
13670		// JAWS announces deletions even when aria-relevant="additions"
13671		// Voiceover will sometimes re-read the entire log region's contents from the beginning
13672		this.liveRegion.children().hide();
13673		a11yContent = $( "<div>" ).html( tooltip.find( ".ui-tooltip-content" ).html() );
13674		a11yContent.removeAttr( "name" ).find( "[name]" ).removeAttr( "name" );
13675		a11yContent.removeAttr( "id" ).find( "[id]" ).removeAttr( "id" );
13676		a11yContent.appendTo( this.liveRegion );
13677
13678		function position( event ) {
13679			positionOption.of = event;
13680			if ( tooltip.is( ":hidden" ) ) {
13681				return;
13682			}
13683			tooltip.position( positionOption );
13684		}
13685		if ( this.options.track && event && /^mouse/.test( event.type ) ) {
13686			this._on( this.document, {
13687				mousemove: position
13688			} );
13689
13690			// trigger once to override element-relative positioning
13691			position( event );
13692		} else {
13693			tooltip.position( $.extend( {
13694				of: target
13695			}, this.options.position ) );
13696		}
13697
13698		tooltip.hide();
13699
13700		this._show( tooltip, this.options.show );
13701
13702		// Handle tracking tooltips that are shown with a delay (#8644). As soon
13703		// as the tooltip is visible, position the tooltip using the most recent
13704		// event.
13705		// Adds the check to add the timers only when both delay and track options are set (#14682)
13706		if ( this.options.track && this.options.show && this.options.show.delay ) {
13707			delayedShow = this.delayedShow = setInterval( function() {
13708				if ( tooltip.is( ":visible" ) ) {
13709					position( positionOption.of );
13710					clearInterval( delayedShow );
13711				}
13712			}, $.fx.interval );
13713		}
13714
13715		this._trigger( "open", event, { tooltip: tooltip } );
13716	},
13717
13718	_registerCloseHandlers: function( event, target ) {
13719		var events = {
13720			keyup: function( event ) {
13721				if ( event.keyCode === $.ui.keyCode.ESCAPE ) {
13722					var fakeEvent = $.Event( event );
13723					fakeEvent.currentTarget = target[ 0 ];
13724					this.close( fakeEvent, true );
13725				}
13726			}
13727		};
13728
13729		// Only bind remove handler for delegated targets. Non-delegated
13730		// tooltips will handle this in destroy.
13731		if ( target[ 0 ] !== this.element[ 0 ] ) {
13732			events.remove = function() {
13733				this._removeTooltip( this._find( target ).tooltip );
13734			};
13735		}
13736
13737		if ( !event || event.type === "mouseover" ) {
13738			events.mouseleave = "close";
13739		}
13740		if ( !event || event.type === "focusin" ) {
13741			events.focusout = "close";
13742		}
13743		this._on( true, target, events );
13744	},
13745
13746	close: function( event ) {
13747		var tooltip,
13748			that = this,
13749			target = $( event ? event.currentTarget : this.element ),
13750			tooltipData = this._find( target );
13751
13752		// The tooltip may already be closed
13753		if ( !tooltipData ) {
13754
13755			// We set ui-tooltip-open immediately upon open (in open()), but only set the
13756			// additional data once there's actually content to show (in _open()). So even if the
13757			// tooltip doesn't have full data, we always remove ui-tooltip-open in case we're in
13758			// the period between open() and _open().
13759			target.removeData( "ui-tooltip-open" );
13760			return;
13761		}
13762
13763		tooltip = tooltipData.tooltip;
13764
13765		// Disabling closes the tooltip, so we need to track when we're closing
13766		// to avoid an infinite loop in case the tooltip becomes disabled on close
13767		if ( tooltipData.closing ) {
13768			return;
13769		}
13770
13771		// Clear the interval for delayed tracking tooltips
13772		clearInterval( this.delayedShow );
13773
13774		// Only set title if we had one before (see comment in _open())
13775		// If the title attribute has changed since open(), don't restore
13776		if ( target.data( "ui-tooltip-title" ) && !target.attr( "title" ) ) {
13777			target.attr( "title", target.data( "ui-tooltip-title" ) );
13778		}
13779
13780		this._removeDescribedBy( target );
13781
13782		tooltipData.hiding = true;
13783		tooltip.stop( true );
13784		this._hide( tooltip, this.options.hide, function() {
13785			that._removeTooltip( $( this ) );
13786		} );
13787
13788		target.removeData( "ui-tooltip-open" );
13789		this._off( target, "mouseleave focusout keyup" );
13790
13791		// Remove 'remove' binding only on delegated targets
13792		if ( target[ 0 ] !== this.element[ 0 ] ) {
13793			this._off( target, "remove" );
13794		}
13795		this._off( this.document, "mousemove" );
13796
13797		if ( event && event.type === "mouseleave" ) {
13798			$.each( this.parents, function( id, parent ) {
13799				$( parent.element ).attr( "title", parent.title );
13800				delete that.parents[ id ];
13801			} );
13802		}
13803
13804		tooltipData.closing = true;
13805		this._trigger( "close", event, { tooltip: tooltip } );
13806		if ( !tooltipData.hiding ) {
13807			tooltipData.closing = false;
13808		}
13809	},
13810
13811	_tooltip: function( element ) {
13812		var tooltip = $( "<div>" ).attr( "role", "tooltip" ),
13813			content = $( "<div>" ).appendTo( tooltip ),
13814			id = tooltip.uniqueId().attr( "id" );
13815
13816		this._addClass( content, "ui-tooltip-content" );
13817		this._addClass( tooltip, "ui-tooltip", "ui-widget ui-widget-content" );
13818
13819		tooltip.appendTo( this._appendTo( element ) );
13820
13821		return this.tooltips[ id ] = {
13822			element: element,
13823			tooltip: tooltip
13824		};
13825	},
13826
13827	_find: function( target ) {
13828		var id = target.data( "ui-tooltip-id" );
13829		return id ? this.tooltips[ id ] : null;
13830	},
13831
13832	_removeTooltip: function( tooltip ) {
13833		tooltip.remove();
13834		delete this.tooltips[ tooltip.attr( "id" ) ];
13835	},
13836
13837	_appendTo: function( target ) {
13838		var element = target.closest( ".ui-front, dialog" );
13839
13840		if ( !element.length ) {
13841			element = this.document[ 0 ].body;
13842		}
13843
13844		return element;
13845	},
13846
13847	_destroy: function() {
13848		var that = this;
13849
13850		// Close open tooltips
13851		$.each( this.tooltips, function( id, tooltipData ) {
13852
13853			// Delegate to close method to handle common cleanup
13854			var event = $.Event( "blur" ),
13855				element = tooltipData.element;
13856			event.target = event.currentTarget = element[ 0 ];
13857			that.close( event, true );
13858
13859			// Remove immediately; destroying an open tooltip doesn't use the
13860			// hide animation
13861			$( "#" + id ).remove();
13862
13863			// Restore the title
13864			if ( element.data( "ui-tooltip-title" ) ) {
13865
13866				// If the title attribute has changed since open(), don't restore
13867				if ( !element.attr( "title" ) ) {
13868					element.attr( "title", element.data( "ui-tooltip-title" ) );
13869				}
13870				element.removeData( "ui-tooltip-title" );
13871			}
13872		} );
13873		this.liveRegion.remove();
13874	}
13875} );
13876
13877// DEPRECATED
13878// TODO: Switch return back to widget declaration at top of file when this is removed
13879if ( $.uiBackCompat !== false ) {
13880
13881	// Backcompat for tooltipClass option
13882	$.widget( "ui.tooltip", $.ui.tooltip, {
13883		options: {
13884			tooltipClass: null
13885		},
13886		_tooltip: function() {
13887			var tooltipData = this._superApply( arguments );
13888			if ( this.options.tooltipClass ) {
13889				tooltipData.tooltip.addClass( this.options.tooltipClass );
13890			}
13891			return tooltipData;
13892		}
13893	} );
13894}
13895
13896var widgetsTooltip = $.ui.tooltip;
13897
13898
13899
13900
13901}));
13902
13903});
13904</script>
13904
13905<style type="text/css">
13906.ui-widget {
13907font-family: inherit;
13908font-size: inherit;
13909}
13910</style>
13911<script>var ms_grabbing_curosr = 'https://steveescoffery.com/wp-content/plugins/master-slider/public/assets/css/common/grabbing.cur', ms_grab_curosr = 'https://steveescoffery.com/wp-content/plugins/master-slider/public/assets/css/common/grab.cur';</script>
13911
13912<meta name="generator" content="MasterSlider 3.5.8 - Responsive Touch Image Slider | avt.li/msf" />
13913<link rel="Shortcut Icon" href="https://steveescoffery.com/wp-content/themes/swank/images/favicon.ico" type="image/x-icon" />
13914<link rel="pingback" href="https://steveescoffery.com/xmlrpc.php" />
13915<script>
vendor: 351 bytes, lines 13915-13921
13915
13916  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
13917  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
13918  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
13919  })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
13920
13921  ga('create', '
13921UA-57243341-1
vendor: 42 bytes, lines 13921-13923
13921', 'auto');
13922  ga('send', 'pageview');
13923
13924</script>
13924<!--[if lt IE 9]>
13924<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
13924<![endif]-->
13925<style type="text/css" id="custom-background-css">
13926body.custom-background { background-image: url("https://steveescoffery.com/Documents/website%20monetization/wp-content/uploads/2014/08/steve-escoffery-november-2009.jpg"); background-position: left top; background-size: auto; background-repeat: repeat; background-attachment: fixed; }
13927</style>
13928	</head>
13929<body data-rsssl=1 class="page-template-default page page-id-8 custom-background _masterslider _ms_version_3.5.8 header-full-width nolayout content-sidebar" itemscope="itemscope" itemtype="http://schema.org/WebPage"><div class="site-container"><div class="top-bar"><div class="wrap"></div></div><header class="site-header" role="banner" itemscope="itemscope" itemtype="http://schema.org/WPHeader"><div class="wrap"><div class="title-area"><p class="site-title" itemprop="headline"><a href="https://steveescoffery.com/">Steve Escoffery</a></p><p class="site-description" itemprop="description">composer • pianist • music teacher</p></div></div></header><nav class="nav-primary" role="navigation" itemscope="itemscope" itemtype="http://schema.org/SiteNavigationElement"><div class="wrap"><ul id="menu-main-navigation-bar" class="menu genesis-nav-menu menu-primary"><li id="menu-item-28" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-home menu-item-28"><a href="https://steveescoffery.com/">Home</a></li>
13930<li id="menu-item-31" class="menu-item menu-item-type-post_type menu-item-object-page current-menu-item page_item page-item-8 current_page_item menu-item-31"><a href="https://steveescoffery.com/about/" aria-current="page">About</a></li>
13931<li id="menu-item-354" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-354"><a href="https://steveescoffery.com/blog/">Blog</a></li>
13932<li id="menu-item-46" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-46"><a href="https://steveescoffery.com/performances-2/">Performances</a></li>
13933<li id="menu-item-32" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-32"><a href="https://steveescoffery.com/audio/">Recordings</a></li>
13934<li id="menu-item-83" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-83"><a href="https://steveescoffery.com/piano-lessons-in-seattle/">Piano Lessons</a></li>
13935<li id="menu-item-84" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-84"><a href="https://steveescoffery.com/contact/">Contact</a></li>
13936</ul></div></nav><div class="site-inner"><div class="content-sidebar-wrap"><main class="content" role="main" itemprop="mainContentOfPage"><article class="post-8 page type-page status-publish entry" itemscope="itemscope" itemtype="http://schema.org/CreativeWork"><header class="entry-header"><h1 class="entry-title" itemprop="headline">About</h1> 
13937</header><div class="entry-content" itemprop="text"><p>&nbsp;</p>
13938<div id="attachment_9" style="width: 544px" class="wp-caption aligncenter"><a href="https://steveescoffery.com/wp-content/uploads/2014/08/10568740_10152597720848659_468870234_n.jpg"><img aria-describedby="caption-attachment-9" class=" wp-image-9" src="https://steveescoffery.com/wp-content/uploads/2014/08/10568740_10152597720848659_468870234_n.jpg" alt="Olympic National Park, 2014" width="534" height="400" srcset="https://steveescoffery.com/wp-content/uploads/2014/08/10568740_10152597720848659_468870234_n.jpg 960w, https://steveescoffery.com/wp-content/uploads/2014/08/10568740_10152597720848659_468870234_n-300x225.jpg 300w" sizes="(max-width: 534px) 100vw, 534px" /></a><p id="caption-attachment-9" class="wp-caption-text">Olympic National Park, 2014</p></div>
13939<p><span class="Apple-style-span" style="color: #000000;">I was born in 1978 in St. Louis, Missouri, and my family had recently moved to the United States from Jamaica (after spending about three years in Canada).</span></p>
13940<p>The first piece of music I ever wrote, probably when I was about 7 years old, was based on the chords – that one of my brothers taught me on the piano – to OMD&#8217;s song, </i>Enola Gay</i>. I always imagine I was one of the only kids listening to music like The Dead Milkmen, OMD, Erasure, XTC, Robyn Hitchcock, The Smiths, Morrissey, U2, R.E.M., Pixies, Depeche Mode, The Clash, etc. Special thanks to my brother, Dave, for getting me into such interesting music from such an early age.</p>
13941<p>I learned to read music and play recorder in Montessori. (Something I realized recently is that I don&#8217;t remember a time when I didn&#8217;t read music.) I played alto saxophone in school bands from fourth through 12th grade, and I played (singer songwriter and guitarist) in a few rock bands in high school; that&#8217;s when I really got into writing music. I ended up getting an B.A. in Music Composition at Columbia College Chicago, where I studied with a number of great composers (including Ilya Levinson, Gustavo Leone, and Patricia Morehead) and pianists (including Josette Behrend and Laura Hoffman). I also got to play for a year in a jazz band conducted by j
13941azz and classical great, William Russo. It was a wonderful experience.</p>
13942<p>While studying with <a class="textLink" href="http://www.ilyalevinsonmusic.com/biography/" target="_blank">Ilya Levinson</a> the last two years I was in Chicago – I&#8217;ve since moved to Seattle – I learned a lot of atonal, experimental, even mathematical compositional techniques; and that&#8217;s when I feel I really became a knowledgeable composer (if I can say that about myself&#8230;). Ilya taught me a number of techniques within the atonal realm, and he encouraged me – and this is the best music advice I&#8217;ve ever received – to invent my own techniques (working organically with the inherent features of the material at hand).</p>
13943<p><a href="https://steveescoffery.com/wp-content/uploads/2014/11/crash-time-motifs-2-steve-escoffery-e1416411288886.jpg"><img class="aligncenter size-full wp-image-118" src="https://steveescoffery.com/wp-content/uploads/2014/11/crash-time-motifs-2-steve-escoffery-e1416411288886.jpg" alt="crash time motifs 2 (steve escoffery)" width="400" height="211" /></a></p>
13944<p>So nowadays, I write fairly mathematically-based, experimental music. I try also to infuse my work with a lot of emotion and listenability. I write initial ideas, like a chord progression or a melody, and I run the ideas through a bunch of mathematical techniques. I end up with a lot of new material that I then sort through. I keep what sounds good (<a class="textLink" title="Duke Ellington quote – at GoodReads.com" href="http://www.goodreads.com/quotes/170996-if-it-sounds-good-it-is-good" target="_blank">thanks, Duke!</a>) and I reorganize it, etc. I was very influenced by the book of Arnold Schoenberg&#8217;s collected essays, Style and Idea. His essay, &#8220;Heart and Brain in Music,&#8221; like many of his essays, has had a lasting impact on my writing. My goal is to create music that is very intense, both intellectually and emotionally. To me, that just seems like a worthwhile thing to do&#8230;</p>
13945<p>I moved to Seattle in 2003, where I continued my studies outside of school – studying with composer/condcutor, Gerhard Samuel, and pianist, Julie Ives.</p>
13946<p>I began teaching in 2004, and my plate is currently (mostly!) full – teaching privately, studying, and working on my own projects. I also still contemplate, at some point, grad school (it&#8217;s not difficult: hmm&#8230;).</p>
13947<p>Some more recent studies include: </p>
13948<p>In 2009, I studied choral arranging and 20th century harmony with <a class="textLink" title="Donald Skirvin's website" href="https://www.donaldmskirvin.com/" target="_blank">Donald Skirvin</a>.  </p>
13949<p>In 2010 and 2011, I studied the <a class="textLink" href="http://supercollider.sourceforge.net/" target="_blank">SuperCollider</a> programming language with <a class="textLink" href="http://modularbrains.net/" target="_blank">Stelios Manousakis</a> (who, at the time, was a PhD student at University of Washington&#8217;s <a class="textLink"  href="http://www.dxarts.washington.edu/" target="_blank">Center for Digital Arts and Experimental Media</a> (DXARTS) – an offshoot of the School of Music); which led me to begin some new music studies at UW – where I&#8217;ve taken just over 20 credits beginning in the 2012-13 school year.  </p>
13950<p>My teachers at UW have been <a class="textLink" href="http://www.realizedsound.net/josh/" target="_blank">Josh Parmenter</a>, <a class="textLink" href="http://www.hbbenard.com/HectorBravoBenard/About.html" target="_blank">Hector Bravo Benard</a>, <a class="textLink" href="http://en.wikipedia.org/wiki/Huck_Hodge" target="_blank">Huck Hodge</a>, <a class="textLink" href="http://www.dxarts.washington.edu/people/13-Juan-Pampin" target="_blank">Juan Pampin</a>, and <a class="textLink" href="https://music.washington.edu/people/robin-mccabe" target="_blank">Robin McCabe</a>.  My recent research has included <a class="textLink" href="http://en.wikipedia.org/wiki/Spectral_music" target="_blank">Spectral Music</a> and the techniques of <a class="textLink" href="http://en.wikipedia.org/wiki/Tristan_Murail" target="_blank">Tristan Murail</a>; as well as <a class="textLink" title="Piano pedagogy – Wikipedia entry" href="https://en.wikipedia.org/wiki/Piano_pedagogy" target="_blank">piano pedagogy</a>.</p>
13951<p>For further information about music lessons (piano/theory/composition) in the Seattle area (or if you have any questions or comments), please feel free to <a class="textLink" href="https://steveescoffery.com/contact/" title="Contact Page" style="text-decoration: none;">contact me here</a>.</p>
13952<div class="box">I send a short email every few months – mentioning the latest, giving links to any new blog posts, etc.</p>
13953<p>You&#8217;ll also get a link to a free download of the digital booklet from my release, Transcendental Object.  It includes nice artwork, and a nine-page paper about how I wrote the music with computer programming.<br />
13954<!-- Begin MailChimp Signup Form -->
13955<link href="//cdn-images.mailchimp.com/embedcode/horizontal-slim-10_7.css" rel="stylesheet" type="text/css">
13956<style type="text/css">
13957	#mc_embed_signup{background:#f5f5f5; clear:left; font:14px Helvetica,Arial,sans-serif; width:100%;}
13958	/* Add your own MailChimp form style overrides in your site stylesheet or in this style block.
13959	   We recommend moving this block and the preceding CSS link to the HEAD of your HTML file. */
13960</style>
13961<div id="mc_embed_signup">
13962<form action="//steveescoffery.us9.list-manage.com/subscribe/post?u=05016b6324c68d39888427ea1&amp;id=b372e8f80c" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate" target="_blank" novalidate>
13963<div id="mc_embed_signup_scroll">
13964	<label for="mce-EMAIL"><strong>Subscribe to the Newsletter</strong></label><br />
13965	<input type="email" value="" name="EMAIL" class="email" id="mce-EMAIL" placeholder="email address" required><br />
13966    <!-- real people should not fill this in and expect good things - do not remove this or risk form bot signups--></p>
13967<div style="position: absolute; left: -5000px;" aria-hidden="true"><input type="text" name="b_05016b6324c68d39888427ea1_b372e8f80c" tabindex="-1" value=""></div>
13968<div class="clear"><input type="submit" value="Subscribe" name="subscribe" id="mc-embedded-subscribe" class="button"></div>
13969</p></div>
13970</form>
13971</div>
13972<p><!--End mc_embed_signup-->
13973</div>
13974</div></article></main><aside class="sidebar sidebar-primary widget-area" role="complementary" itemscope="itemscope" itemtype="http://schema.org/WPSideBar"><section id="enews-ext-3" class="widget enews-widget"><div class="widget-wrap"><div class="enews"><h4 class="widget-title widgettitle">Email List</h4>
13975<p>If you'd like to receive an occasional update about my work, simply include your email address here.</p>
13976			<form id="subscribeenews-ext-3" action="https://steveescoffery.us9.list-manage.com/subscribe/post?u=05016b6324c68d39888427ea1&amp;id=b372e8f80c" method="post"
13977																			target="_blank" onsubmit="if ( subbox1.value == 'First Name') { subbox1.value = ''; } if ( subbox2.value == 'Last Name') { subbox2.value = ''; }" name="enews-ext-3">
13978												<label for="subbox" class="screenread">Email Address</label><input type="email" value="" id="subbox" placeholder="Email Address" name="EMAIL"
13979																														required="required" />
13980								<input type="submit" value="Go" id="subbutton" />
13981			</form>
13982		<p>Thanks for joining!</p>
13983</div></div></section><section id="search-8" class="widget widget_search"><div class="widget-wrap"><h4 class="widget-title widgettitle">Search</h4>
13984<form method="get" class="search-form" action="https://steveescoffery.com/" role="search"><input type="search" name="s" placeholder="Search this website&#x2026;" /><input type="submit" value="Search" /></form></div></section></aside></div><aside class="sidebar sidebar-secondary widget-area" role="complementary" itemscope="itemscope" itemtype="http://schema.org/WPSideBar"></aside></div><div class="footer-widgets"><div class="wrap"><div class="footer-widgets-1 widget-area">		<section id="recent-posts-3" class="widget widget_recent_entries"><div class="widget-wrap">		<h4 class="widget-title widgettitle">Recent posts from the blog:</h4>
13985		<ul>
13986											<li>
13987					<a href="https://steveescoffery.com/digital-piano-buying-guide-from-piano-teacher/">Protected: Digital Piano Buying Guide (A Piano Teacher&#8217;s Perspective)</a>
13988											<span class="post-date">November 29, 2017</span>
13989									</li>
13990											<li>
13991					<a href="https://steveescoffery.com/understanding-chords-part-2-major-chords/">Understanding Chords: Part 2, Major Chords</a>
13992											<span class="post-date">July 31, 2016</span>
13993									</li>
13994											<li>
13995					<a href="https://steveescoffery.com/flood-mix/">Four Songs Produced by Flood (aka Mark Ellis)</a>
13996											<span class="post-date">May 2, 2016</span>
13997									</li>
13998											<li>
13999					<a href="https://steveescoffery.com/understanding-chords-part-1-intervals/">Understanding Chords: Part 1, Intervals</a>
14000											<span class="post-date">April 18, 2016</span>
14001									</li>
14002											<li>
14003					<a href="https://steveescoffery.com/transcendental-object-release/">New Release: Transcendental Object</a>
14004											<span class="post-date">February 28, 2016</span>
14005									</li>
14006					</ul>
14007		</div></section>
14008</div><div class="footer-widgets-2 widget-area"><section id="text-2" class="widget widget_text"><div class="widget-wrap"><h4 class="widget-title widgettitle">Additional info:</h4>
14009			<div class="textwidget"><p style="text-align: right;"><a class="textLink" href="https://steveescoffery.com/privacy-policy/">Privacy Policy</a></p>
14010<p style="text-align: right;"><a class="textLink" href="https://steveescoffery.com/affiliate-disclosure/">Affiliate Disclosure</a></p>
14011</div>
14012		</div></section>
14013</div></div></div><footer class="site-footer" role="contentinfo" itemscope="itemscope" itemtype="http://schema.org/WPFooter"><div class="wrap">	<p>&copy; Copyright 2004-2018 <a href="https://steveescoffery.com/">Steve Escoffery</a> &middot; All Rights Reserved</a></p>
14014	</div></footer></div><div class='code-block code-block-1' style='margin: 8px 0; clear: both;'>
14015<div id="amzn-assoc-ad-c6d7f25e-3580-4fba-b05b-8d8ebc9a41c8"></div>
14015<script async src="//z-na.amazon-adsystem.com/widgets/onejs?MarketPlace=US&adInstanceId=c6d7f25e-3580-4fba-b05b-8d8ebc9a41c8"></script>
14015</div>
14016<link rel='stylesheet' id='style1-css'  href='https://steveescoffery.com/wp-content/plugins/abc-notation/abcjs-midi.css?ver=5.4.23' type='text/css' media='all' />
14017<script type='text/javascript' src='https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.js?ver=1.12.1'></script>
vendor: 1 bytes, line 14017
14017
14018<script type='text/javascript' src='https://cdnjs.cloudflare.com/ajax/libs/jquery.tocify/1.9.0/javascripts/jquery.tocify.min.js?ver=1.9.0'></script>
vendor: 1 bytes, line 14018
14018
14019<script type='text/javascript'>
14020/* <![CDATA[ */
14021var frontend_ajax_object = {"ajax_url":"https:\/\/steveescoffery.com\/wp-admin\/admin-ajax.php","ajax_nonce":"9aa8e4e5a7"};
14022/* ]]> */
14023</script>
vendor: 1 bytes, line 14023
14023
14024<script type='text/javascript' src='https://steveescoffery.com/wp-content/plugins/accesspress-social-share/js/frontend.js?ver=4.5.2'></script>
vendor: 1 bytes, line 14024
14024
14025<script type='text/javascript'>
14026/* <![CDATA[ */
14027var wpcf7 = {"apiSettings":{"root":"https:\/\/steveescoffery.com\/wp-json\/contact-form-7\/v1","namespace":"contact-form-7\/v1"}};
14028/* ]]> */
14029</script>
vendor: 1 bytes, line 14029
14029
14030<script type='text/javascript' src='https://steveescoffery.com/wp-content/plugins/contact-form-7/includes/js/scripts.js?ver=5.1.9'></script>
vendor: 1 bytes, line 14030
14030
14031<script type='text/javascript' src='https://steveescoffery.com/wp-includes/js/jquery/ui/core.min.js?ver=1.11.4'></script>
vendor: 1 bytes, line 14031
14031
14032<script type='text/javascript' src='https://steveescoffery.com/wp-includes/js/jquery/ui/widget.min.js?ver=1.11.4'></script>
vendor: 1 bytes, line 14032
14032
14033<script type='text/javascript' src='https://steveescoffery.com/wp-includes/js/jquery/ui/accordion.min.js?ver=1.11.4'></script>
vendor: 1 bytes, line 14033
14033
14034<script type='text/javascript' src='https://steveescoffery.com/wp-includes/js/jquery/ui/position.min.js?ver=1.11.4'></script>
vendor: 1 bytes, line 14034
14034
14035<script type='text/javascript' src='https://steveescoffery.com/wp-includes/js/jquery/ui/menu.min.js?ver=1.11.4'></script>
vendor: 1 bytes, line 14035
14035
14036<script type='text/javascript' src='https://steveescoffery.com/wp-includes/js/dist/vendor/wp-polyfill.min.js?ver=7.4.4'></script>
vendor: 1 bytes, line 14036
14036
14037<script type='text/javascript'>
14038( 'fetch' in window ) || document.write( '
14038<script src="https://steveescoffery.com/wp-includes/js/dist/vendor/wp-polyfill-fetch.min.js?ver=3.0.0"></scr' + 'ipt>' );( document.contains ) || document.write( '
14038<script src="https://steveescoffery.com/wp-includes/js/dist/vendor/wp-polyfill-node-contains.min.js?ver=3.42.0"></scr' + 'ipt>' );( window.DOMRect ) || document.write( '
14038<script src="https://steveescoffery.com/wp-includes/js/dist/vendor/wp-polyfill-dom-rect.min.js?ver=3.42.0"></scr' + 'ipt>' );( window.URL && window.URL.prototype && window.URLSearchParams ) || document.write( '
14038<script src="https://steveescoffery.com/wp-includes/js/dist/vendor/wp-polyfill-url.min.js?ver=3.6.4"></scr' + 'ipt>' );( window.FormData && window.FormData.prototype.keys ) || document.write( '
14038<script src="https://steveescoffery.com/wp-includes/js/dist/vendor/wp-polyfill-formdata.min.js?ver=3.0.12"></scr' + 'ipt>' );( Element.prototype.matches && Element.prototype.closest ) || document.write( '
14038<script src="https://steveescoffery.com/wp-includes/js/dist/vendor/wp-polyfill-element-closest.min.js?ver=2.0.2"></scr' + 'ipt>' );
14039</script>
vendor: 1 bytes, line 14039
14039
14040<script type='text/javascript' src='https://steveescoffery.com/wp-includes/js/dist/dom-ready.min.js?ver=93db39f6fe07a70cb9217310bec0a531'></script>
vendor: 1 bytes, line 14040
14040
14041<script type='text/javascript' src='https://steveescoffery.com/wp-includes/js/dist/a11y.min.js?ver=8d75be94e0703857a3323c972eb3d7d2'></script>
vendor: 1 bytes, line 14041
14041
14042<script type='text/javascript'>
14043/* <![CDATA[ */
14044var uiAutocompleteL10n = {"noResults":"No results found.","oneResult":"1 result found. Use up and down arrow keys to navigate.","manyResults":"%d results found. Use up and down arrow keys to navigate.","itemSelected":"Item selected."};
14045/* ]]> */
14046</script>
vendor: 1 bytes, line 14046
14046
14047<script type='text/javascript' src='https://steveescoffery.com/wp-includes/js/jquery/ui/autocomplete.min.js?ver=1.11.4'></script>
vendor: 1 bytes, line 14047
14047
14048<script type='text/javascript' src='https://steveescoffery.com/wp-includes/js/jquery/ui/button.min.js?ver=1.11.4'></script>
vendor: 1 bytes, line 14048
14048
14049<script type='text/javascript' src='https://steveescoffery.com/wp-includes/js/jquery/ui/datepicker.min.js?ver=1.11.4'></script>
vendor: 1 bytes, line 14049
14049
14050<script type='text/javascript'>
14051jQuery(document).ready(function(jQuery){jQuery.datepicker.setDefaults({"closeText":"Close","currentText":"Today","monthNames":["January","February","March","April","May","June","July","August","September","October","November","December"],"monthNamesShort":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"nextText":"Next","prevText":"Previous","dayNames":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"dayNamesShort":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"dayNamesMin":["S","M","T","W","T","F","S"],"dateFormat":"MM d, yy","firstDay":0,"isRTL":false});});
14052</script>
vendor: 1 bytes, line 14052
14052
14053<script type='text/javascript' src='https://steveescoffery.com/wp-includes/js/jquery/ui/mouse.min.js?ver=1.11.4'></script>
vendor: 1 bytes, line 14053
14053
14054<script type='text/javascript' src='https://steveescoffery.com/wp-includes/js/jquery/ui/resizable.min.js?ver=1.11.4'></script>
vendor: 1 bytes, line 14054
14054
14055<script type='text/javascript' src='https://steveescoffery.com/wp-includes/js/jquery/ui/draggable.min.js?ver=1.11.4'></script>
vendor: 1 bytes, line 14055
14055
14056<script type='text/javascript' src='https://steveescoffery.com/wp-includes/js/jquery/ui/dialog.min.js?ver=1.11.4'></script>
vendor: 1 bytes, line 14056
14056
14057<script type='text/javascript' src='https://steveescoffery.com/wp-includes/js/jquery/ui/droppable.min.js?ver=1.11.4'></script>
vendor: 1 bytes, line 14057
14057
14058<script type='text/javascript' src='https://steveescoffery.com/wp-includes/js/jquery/ui/progressbar.min.js?ver=1.11.4'></script>
vendor: 1 bytes, line 14058
14058
14059<script type='text/javascript' src='https://steveescoffery.com/wp-includes/js/jquery/ui/selectable.min.js?ver=1.11.4'></script>
vendor: 1 bytes, line 14059
14059
14060<script type='text/javascript' src='https://steveescoffery.com/wp-includes/js/jquery/ui/slider.min.js?ver=1.11.4'></script>
vendor: 1 bytes, line 14060
14060
14061<script type='text/javascript' src='https://steveescoffery.com/wp-includes/js/jquery/ui/spinner.min.js?ver=1.11.4'></script>
vendor: 1 bytes, line 14061
14061
14062<script type='text/javascript' src='https://steveescoffery.com/wp-includes/js/jquery/ui/sortable.min.js?ver=1.11.4'></script>
vendor: 1 bytes, line 14062
14062
14063<script type='text/javascript' src='https://steveescoffery.com/wp-includes/js/jquery/ui/tabs.min.js?ver=1.11.4'></script>
vendor: 1 bytes, line 14063
14063
14064<script type='text/javascript' src='https://steveescoffery.com/wp-includes/js/jquery/ui/tooltip.min.js?ver=1.11.4'></script>
vendor: 1 bytes, line 14064
14064
14065<script type='text/javascript' src='https://steveescoffery.com/wp-includes/js/jquery/ui/effect.min.js?ver=1.11.4'></script>
vendor: 1 bytes, line 14065
14065
14066<script type='text/javascript' src='https://steveescoffery.com/wp-includes/js/jquery/ui/effect-blind.min.js?ver=1.11.4'></script>
vendor: 1 bytes, line 14066
14066
14067<script type='text/javascript' src='https://steveescoffery.com/wp-includes/js/jquery/ui/effect-bounce.min.js?ver=1.11.4'></script>
vendor: 1 bytes, line 14067
14067
14068<script type='text/javascript' src='https://steveescoffery.com/wp-includes/js/jquery/ui/effect-clip.min.js?ver=1.11.4'></script>
vendor: 1 bytes, line 14068
14068
14069<script type='text/javascript' src='https://steveescoffery.com/wp-includes/js/jquery/ui/effect-drop.min.js?ver=1.11.4'></script>
vendor: 1 bytes, line 14069
14069
14070<script type='text/javascript' src='https://steveescoffery.com/wp-includes/js/jquery/ui/effect-explode.min.js?ver=1.11.4'></script>
vendor: 1 bytes, line 14070
14070
14071<script type='text/javascript' src='https://steveescoffery.com/wp-includes/js/jquery/ui/effect-fade.min.js?ver=1.11.4'></script>
vendor: 1 bytes, line 14071
14071
14072<script type='text/javascript' src='https://steveescoffery.com/wp-includes/js/jquery/ui/effect-fold.min.js?ver=1.11.4'></script>
vendor: 1 bytes, line 14072
14072
14073<script type='text/javascript' src='https://steveescoffery.com/wp-includes/js/jquery/ui/effect-highlight.min.js?ver=1.11.4'></script>
vendor: 1 bytes, line 14073
14073
14074<script type='text/javascript' src='https://steveescoffery.com/wp-includes/js/jquery/ui/effect-pulsate.min.js?ver=1.11.4'></script>
vendor: 1 bytes, line 14074
14074
14075<script type='text/javascript' src='https://steveescoffery.com/wp-includes/js/jquery/ui/effect-size.min.js?ver=1.11.4'></script>
vendor: 1 bytes, line 14075
14075
14076<script type='text/javascript' src='https://steveescoffery.com/wp-includes/js/jquery/ui/effect-scale.min.js?ver=1.11.4'></script>
vendor: 1 bytes, line 14076
14076
14077<script type='text/javascript' src='https://steveescoffery.com/wp-includes/js/jquery/ui/effect-shake.min.js?ver=1.11.4'></script>
vendor: 1 bytes, line 14077
14077
14078<script type='text/javascript' src='https://steveescoffery.com/wp-includes/js/jquery/ui/effect-slide.min.js?ver=1.11.4'></script>
vendor: 1 bytes, line 14078
14078
14079<script type='text/javascript' src='https://steveescoffery.com/wp-includes/js/jquery/ui/effect-transfer.min.js?ver=1.11.4'></script>
vendor: 1 bytes, line 14079
14079
14080<script type='text/javascript'>
14081/* <![CDATA[ */
14082var tocplus = {"visibility_show":"show","visibility_hide":"hide","width":"Auto"};
14083/* ]]> */
14084</script>
vendor: 1 bytes, line 14084
14084
14085<script type='text/javascript' src='https://steveescoffery.com/wp-content/plugins/table-of-contents-plus/front.min.js?ver=2002'></script>
vendor: 1 bytes, line 14085
14085
14086<script type='text/javascript' src='https://steveescoffery.com/wp-includes/js/comment-reply.min.js?ver=5.4.23'></script>
vendor: 1 bytes, line 14086
14086
14087<script type='text/javascript' src='https://steveescoffery.com/wp-content/themes/swank/lib/js/responsive-menu.js?ver=1.0.0'></script>
vendor: 1 bytes, line 14087
14087
14088<script type='text/javascript' src='https://steveescoffery.com/wp-includes/js/wp-embed.min.js?ver=5.4.23'></script>
vendor: 1 bytes, line 14088
14088
14089<script type='text/javascript' src='https://use.fontawesome.com/b8d1222982.js?ver=5.4.23'></script>
vendor: 1 bytes, line 14089
14089
14090<script type='text/javascript' src='https://steveescoffery.com/wp-content/plugins/abc-notation/abcjs_midi_5.8.1-min.js?ver=5.4.23'></script>
14090
14091</body>
14092</html>

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