/alps/pcitool

To get this branch, use:
bzr branch http://suren.me/webbzr/alps/pcitool
346.1.37 by Vasilii Chernov
1. Pcipywrap: add persistent locking wrappings
1
/*! jQuery UI - v1.11.4 - 2015-03-11
2
* http://jqueryui.com
3
* Includes: core.js, widget.js, mouse.js, position.js, accordion.js, autocomplete.js, button.js, datepicker.js, dialog.js, draggable.js, droppable.js, effect.js, effect-blind.js, effect-bounce.js, effect-clip.js, effect-drop.js, effect-explode.js, effect-fade.js, effect-fold.js, effect-highlight.js, effect-puff.js, effect-pulsate.js, effect-scale.js, effect-shake.js, effect-size.js, effect-slide.js, effect-transfer.js, menu.js, progressbar.js, resizable.js, selectable.js, selectmenu.js, slider.js, sortable.js, spinner.js, tabs.js, tooltip.js
4
* Copyright 2015 jQuery Foundation and other contributors; Licensed MIT */
5
6
(function( factory ) {
7
	if ( typeof define === "function" && define.amd ) {
8
9
		// AMD. Register as an anonymous module.
10
		define([ "jquery" ], factory );
11
	} else {
12
13
		// Browser globals
14
		factory( jQuery );
15
	}
16
}(function( $ ) {
17
/*!
18
 * jQuery UI Core 1.11.4
19
 * http://jqueryui.com
20
 *
21
 * Copyright jQuery Foundation and other contributors
22
 * Released under the MIT license.
23
 * http://jquery.org/license
24
 *
25
 * http://api.jqueryui.com/category/ui-core/
26
 */
27
28
29
// $.ui might exist from components with no dependencies, e.g., $.ui.position
30
$.ui = $.ui || {};
31
32
$.extend( $.ui, {
33
	version: "1.11.4",
34
35
	keyCode: {
36
		BACKSPACE: 8,
37
		COMMA: 188,
38
		DELETE: 46,
39
		DOWN: 40,
40
		END: 35,
41
		ENTER: 13,
42
		ESCAPE: 27,
43
		HOME: 36,
44
		LEFT: 37,
45
		PAGE_DOWN: 34,
46
		PAGE_UP: 33,
47
		PERIOD: 190,
48
		RIGHT: 39,
49
		SPACE: 32,
50
		TAB: 9,
51
		UP: 38
52
	}
53
});
54
55
// plugins
56
$.fn.extend({
57
	scrollParent: function( includeHidden ) {
58
		var position = this.css( "position" ),
59
			excludeStaticParent = position === "absolute",
60
			overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/,
61
			scrollParent = this.parents().filter( function() {
62
				var parent = $( this );
63
				if ( excludeStaticParent && parent.css( "position" ) === "static" ) {
64
					return false;
65
				}
66
				return overflowRegex.test( parent.css( "overflow" ) + parent.css( "overflow-y" ) + parent.css( "overflow-x" ) );
67
			}).eq( 0 );
68
69
		return position === "fixed" || !scrollParent.length ? $( this[ 0 ].ownerDocument || document ) : scrollParent;
70
	},
71
72
	uniqueId: (function() {
73
		var uuid = 0;
74
75
		return function() {
76
			return this.each(function() {
77
				if ( !this.id ) {
78
					this.id = "ui-id-" + ( ++uuid );
79
				}
80
			});
81
		};
82
	})(),
83
84
	removeUniqueId: function() {
85
		return this.each(function() {
86
			if ( /^ui-id-\d+$/.test( this.id ) ) {
87
				$( this ).removeAttr( "id" );
88
			}
89
		});
90
	}
91
});
92
93
// selectors
94
function focusable( element, isTabIndexNotNaN ) {
95
	var map, mapName, img,
96
		nodeName = element.nodeName.toLowerCase();
97
	if ( "area" === nodeName ) {
98
		map = element.parentNode;
99
		mapName = map.name;
100
		if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
101
			return false;
102
		}
103
		img = $( "img[usemap='#" + mapName + "']" )[ 0 ];
104
		return !!img && visible( img );
105
	}
106
	return ( /^(input|select|textarea|button|object)$/.test( nodeName ) ?
107
		!element.disabled :
108
		"a" === nodeName ?
109
			element.href || isTabIndexNotNaN :
110
			isTabIndexNotNaN) &&
111
		// the element and all of its ancestors must be visible
112
		visible( element );
113
}
114
115
function visible( element ) {
116
	return $.expr.filters.visible( element ) &&
117
		!$( element ).parents().addBack().filter(function() {
118
			return $.css( this, "visibility" ) === "hidden";
119
		}).length;
120
}
121
122
$.extend( $.expr[ ":" ], {
123
	data: $.expr.createPseudo ?
124
		$.expr.createPseudo(function( dataName ) {
125
			return function( elem ) {
126
				return !!$.data( elem, dataName );
127
			};
128
		}) :
129
		// support: jQuery <1.8
130
		function( elem, i, match ) {
131
			return !!$.data( elem, match[ 3 ] );
132
		},
133
134
	focusable: function( element ) {
135
		return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );
136
	},
137
138
	tabbable: function( element ) {
139
		var tabIndex = $.attr( element, "tabindex" ),
140
			isTabIndexNaN = isNaN( tabIndex );
141
		return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );
142
	}
143
});
144
145
// support: jQuery <1.8
146
if ( !$( "<a>" ).outerWidth( 1 ).jquery ) {
147
	$.each( [ "Width", "Height" ], function( i, name ) {
148
		var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
149
			type = name.toLowerCase(),
150
			orig = {
151
				innerWidth: $.fn.innerWidth,
152
				innerHeight: $.fn.innerHeight,
153
				outerWidth: $.fn.outerWidth,
154
				outerHeight: $.fn.outerHeight
155
			};
156
157
		function reduce( elem, size, border, margin ) {
158
			$.each( side, function() {
159
				size -= parseFloat( $.css( elem, "padding" + this ) ) || 0;
160
				if ( border ) {
161
					size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0;
162
				}
163
				if ( margin ) {
164
					size -= parseFloat( $.css( elem, "margin" + this ) ) || 0;
165
				}
166
			});
167
			return size;
168
		}
169
170
		$.fn[ "inner" + name ] = function( size ) {
171
			if ( size === undefined ) {
172
				return orig[ "inner" + name ].call( this );
173
			}
174
175
			return this.each(function() {
176
				$( this ).css( type, reduce( this, size ) + "px" );
177
			});
178
		};
179
180
		$.fn[ "outer" + name] = function( size, margin ) {
181
			if ( typeof size !== "number" ) {
182
				return orig[ "outer" + name ].call( this, size );
183
			}
184
185
			return this.each(function() {
186
				$( this).css( type, reduce( this, size, true, margin ) + "px" );
187
			});
188
		};
189
	});
190
}
191
192
// support: jQuery <1.8
193
if ( !$.fn.addBack ) {
194
	$.fn.addBack = function( selector ) {
195
		return this.add( selector == null ?
196
			this.prevObject : this.prevObject.filter( selector )
197
		);
198
	};
199
}
200
201
// support: jQuery 1.6.1, 1.6.2 (http://bugs.jquery.com/ticket/9413)
202
if ( $( "<a>" ).data( "a-b", "a" ).removeData( "a-b" ).data( "a-b" ) ) {
203
	$.fn.removeData = (function( removeData ) {
204
		return function( key ) {
205
			if ( arguments.length ) {
206
				return removeData.call( this, $.camelCase( key ) );
207
			} else {
208
				return removeData.call( this );
209
			}
210
		};
211
	})( $.fn.removeData );
212
}
213
214
// deprecated
215
$.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() );
216
217
$.fn.extend({
218
	focus: (function( orig ) {
219
		return function( delay, fn ) {
220
			return typeof delay === "number" ?
221
				this.each(function() {
222
					var elem = this;
223
					setTimeout(function() {
224
						$( elem ).focus();
225
						if ( fn ) {
226
							fn.call( elem );
227
						}
228
					}, delay );
229
				}) :
230
				orig.apply( this, arguments );
231
		};
232
	})( $.fn.focus ),
233
234
	disableSelection: (function() {
235
		var eventType = "onselectstart" in document.createElement( "div" ) ?
236
			"selectstart" :
237
			"mousedown";
238
239
		return function() {
240
			return this.bind( eventType + ".ui-disableSelection", function( event ) {
241
				event.preventDefault();
242
			});
243
		};
244
	})(),
245
246
	enableSelection: function() {
247
		return this.unbind( ".ui-disableSelection" );
248
	},
249
250
	zIndex: function( zIndex ) {
251
		if ( zIndex !== undefined ) {
252
			return this.css( "zIndex", zIndex );
253
		}
254
255
		if ( this.length ) {
256
			var elem = $( this[ 0 ] ), position, value;
257
			while ( elem.length && elem[ 0 ] !== document ) {
258
				// Ignore z-index if position is set to a value where z-index is ignored by the browser
259
				// This makes behavior of this function consistent across browsers
260
				// WebKit always returns auto if the element is positioned
261
				position = elem.css( "position" );
262
				if ( position === "absolute" || position === "relative" || position === "fixed" ) {
263
					// IE returns 0 when zIndex is not specified
264
					// other browsers return a string
265
					// we ignore the case of nested elements with an explicit value of 0
266
					// <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
267
					value = parseInt( elem.css( "zIndex" ), 10 );
268
					if ( !isNaN( value ) && value !== 0 ) {
269
						return value;
270
					}
271
				}
272
				elem = elem.parent();
273
			}
274
		}
275
276
		return 0;
277
	}
278
});
279
280
// $.ui.plugin is deprecated. Use $.widget() extensions instead.
281
$.ui.plugin = {
282
	add: function( module, option, set ) {
283
		var i,
284
			proto = $.ui[ module ].prototype;
285
		for ( i in set ) {
286
			proto.plugins[ i ] = proto.plugins[ i ] || [];
287
			proto.plugins[ i ].push( [ option, set[ i ] ] );
288
		}
289
	},
290
	call: function( instance, name, args, allowDisconnected ) {
291
		var i,
292
			set = instance.plugins[ name ];
293
294
		if ( !set ) {
295
			return;
296
		}
297
298
		if ( !allowDisconnected && ( !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) ) {
299
			return;
300
		}
301
302
		for ( i = 0; i < set.length; i++ ) {
303
			if ( instance.options[ set[ i ][ 0 ] ] ) {
304
				set[ i ][ 1 ].apply( instance.element, args );
305
			}
306
		}
307
	}
308
};
309
310
311
/*!
312
 * jQuery UI Widget 1.11.4
313
 * http://jqueryui.com
314
 *
315
 * Copyright jQuery Foundation and other contributors
316
 * Released under the MIT license.
317
 * http://jquery.org/license
318
 *
319
 * http://api.jqueryui.com/jQuery.widget/
320
 */
321
322
323
var widget_uuid = 0,
324
	widget_slice = Array.prototype.slice;
325
326
$.cleanData = (function( orig ) {
327
	return function( elems ) {
328
		var events, elem, i;
329
		for ( i = 0; (elem = elems[i]) != null; i++ ) {
330
			try {
331
332
				// Only trigger remove when necessary to save time
333
				events = $._data( elem, "events" );
334
				if ( events && events.remove ) {
335
					$( elem ).triggerHandler( "remove" );
336
				}
337
338
			// http://bugs.jquery.com/ticket/8235
339
			} catch ( e ) {}
340
		}
341
		orig( elems );
342
	};
343
})( $.cleanData );
344
345
$.widget = function( name, base, prototype ) {
346
	var fullName, existingConstructor, constructor, basePrototype,
347
		// proxiedPrototype allows the provided prototype to remain unmodified
348
		// so that it can be used as a mixin for multiple widgets (#8876)
349
		proxiedPrototype = {},
350
		namespace = name.split( "." )[ 0 ];
351
352
	name = name.split( "." )[ 1 ];
353
	fullName = namespace + "-" + name;
354
355
	if ( !prototype ) {
356
		prototype = base;
357
		base = $.Widget;
358
	}
359
360
	// create selector for plugin
361
	$.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
362
		return !!$.data( elem, fullName );
363
	};
364
365
	$[ namespace ] = $[ namespace ] || {};
366
	existingConstructor = $[ namespace ][ name ];
367
	constructor = $[ namespace ][ name ] = function( options, element ) {
368
		// allow instantiation without "new" keyword
369
		if ( !this._createWidget ) {
370
			return new constructor( options, element );
371
		}
372
373
		// allow instantiation without initializing for simple inheritance
374
		// must use "new" keyword (the code above always passes args)
375
		if ( arguments.length ) {
376
			this._createWidget( options, element );
377
		}
378
	};
379
	// extend with the existing constructor to carry over any static properties
380
	$.extend( constructor, existingConstructor, {
381
		version: prototype.version,
382
		// copy the object used to create the prototype in case we need to
383
		// redefine the widget later
384
		_proto: $.extend( {}, prototype ),
385
		// track widgets that inherit from this widget in case this widget is
386
		// redefined after a widget inherits from it
387
		_childConstructors: []
388
	});
389
390
	basePrototype = new base();
391
	// we need to make the options hash a property directly on the new instance
392
	// otherwise we'll modify the options hash on the prototype that we're
393
	// inheriting from
394
	basePrototype.options = $.widget.extend( {}, basePrototype.options );
395
	$.each( prototype, function( prop, value ) {
396
		if ( !$.isFunction( value ) ) {
397
			proxiedPrototype[ prop ] = value;
398
			return;
399
		}
400
		proxiedPrototype[ prop ] = (function() {
401
			var _super = function() {
402
					return base.prototype[ prop ].apply( this, arguments );
403
				},
404
				_superApply = function( args ) {
405
					return base.prototype[ prop ].apply( this, args );
406
				};
407
			return function() {
408
				var __super = this._super,
409
					__superApply = this._superApply,
410
					returnValue;
411
412
				this._super = _super;
413
				this._superApply = _superApply;
414
415
				returnValue = value.apply( this, arguments );
416
417
				this._super = __super;
418
				this._superApply = __superApply;
419
420
				return returnValue;
421
			};
422
		})();
423
	});
424
	constructor.prototype = $.widget.extend( basePrototype, {
425
		// TODO: remove support for widgetEventPrefix
426
		// always use the name + a colon as the prefix, e.g., draggable:start
427
		// don't prefix for widgets that aren't DOM-based
428
		widgetEventPrefix: existingConstructor ? (basePrototype.widgetEventPrefix || name) : name
429
	}, proxiedPrototype, {
430
		constructor: constructor,
431
		namespace: namespace,
432
		widgetName: name,
433
		widgetFullName: fullName
434
	});
435
436
	// If this widget is being redefined then we need to find all widgets that
437
	// are inheriting from it and redefine all of them so that they inherit from
438
	// the new version of this widget. We're essentially trying to replace one
439
	// level in the prototype chain.
440
	if ( existingConstructor ) {
441
		$.each( existingConstructor._childConstructors, function( i, child ) {
442
			var childPrototype = child.prototype;
443
444
			// redefine the child widget using the same prototype that was
445
			// originally used, but inherit from the new version of the base
446
			$.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto );
447
		});
448
		// remove the list of existing child constructors from the old constructor
449
		// so the old child constructors can be garbage collected
450
		delete existingConstructor._childConstructors;
451
	} else {
452
		base._childConstructors.push( constructor );
453
	}
454
455
	$.widget.bridge( name, constructor );
456
457
	return constructor;
458
};
459
460
$.widget.extend = function( target ) {
461
	var input = widget_slice.call( arguments, 1 ),
462
		inputIndex = 0,
463
		inputLength = input.length,
464
		key,
465
		value;
466
	for ( ; inputIndex < inputLength; inputIndex++ ) {
467
		for ( key in input[ inputIndex ] ) {
468
			value = input[ inputIndex ][ key ];
469
			if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
470
				// Clone objects
471
				if ( $.isPlainObject( value ) ) {
472
					target[ key ] = $.isPlainObject( target[ key ] ) ?
473
						$.widget.extend( {}, target[ key ], value ) :
474
						// Don't extend strings, arrays, etc. with objects
475
						$.widget.extend( {}, value );
476
				// Copy everything else by reference
477
				} else {
478
					target[ key ] = value;
479
				}
480
			}
481
		}
482
	}
483
	return target;
484
};
485
486
$.widget.bridge = function( name, object ) {
487
	var fullName = object.prototype.widgetFullName || name;
488
	$.fn[ name ] = function( options ) {
489
		var isMethodCall = typeof options === "string",
490
			args = widget_slice.call( arguments, 1 ),
491
			returnValue = this;
492
493
		if ( isMethodCall ) {
494
			this.each(function() {
495
				var methodValue,
496
					instance = $.data( this, fullName );
497
				if ( options === "instance" ) {
498
					returnValue = instance;
499
					return false;
500
				}
501
				if ( !instance ) {
502
					return $.error( "cannot call methods on " + name + " prior to initialization; " +
503
						"attempted to call method '" + options + "'" );
504
				}
505
				if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) {
506
					return $.error( "no such method '" + options + "' for " + name + " widget instance" );
507
				}
508
				methodValue = instance[ options ].apply( instance, args );
509
				if ( methodValue !== instance && methodValue !== undefined ) {
510
					returnValue = methodValue && methodValue.jquery ?
511
						returnValue.pushStack( methodValue.get() ) :
512
						methodValue;
513
					return false;
514
				}
515
			});
516
		} else {
517
518
			// Allow multiple hashes to be passed on init
519
			if ( args.length ) {
520
				options = $.widget.extend.apply( null, [ options ].concat(args) );
521
			}
522
523
			this.each(function() {
524
				var instance = $.data( this, fullName );
525
				if ( instance ) {
526
					instance.option( options || {} );
527
					if ( instance._init ) {
528
						instance._init();
529
					}
530
				} else {
531
					$.data( this, fullName, new object( options, this ) );
532
				}
533
			});
534
		}
535
536
		return returnValue;
537
	};
538
};
539
540
$.Widget = function( /* options, element */ ) {};
541
$.Widget._childConstructors = [];
542
543
$.Widget.prototype = {
544
	widgetName: "widget",
545
	widgetEventPrefix: "",
546
	defaultElement: "<div>",
547
	options: {
548
		disabled: false,
549
550
		// callbacks
551
		create: null
552
	},
553
	_createWidget: function( options, element ) {
554
		element = $( element || this.defaultElement || this )[ 0 ];
555
		this.element = $( element );
556
		this.uuid = widget_uuid++;
557
		this.eventNamespace = "." + this.widgetName + this.uuid;
558
559
		this.bindings = $();
560
		this.hoverable = $();
561
		this.focusable = $();
562
563
		if ( element !== this ) {
564
			$.data( element, this.widgetFullName, this );
565
			this._on( true, this.element, {
566
				remove: function( event ) {
567
					if ( event.target === element ) {
568
						this.destroy();
569
					}
570
				}
571
			});
572
			this.document = $( element.style ?
573
				// element within the document
574
				element.ownerDocument :
575
				// element is window or document
576
				element.document || element );
577
			this.window = $( this.document[0].defaultView || this.document[0].parentWindow );
578
		}
579
580
		this.options = $.widget.extend( {},
581
			this.options,
582
			this._getCreateOptions(),
583
			options );
584
585
		this._create();
586
		this._trigger( "create", null, this._getCreateEventData() );
587
		this._init();
588
	},
589
	_getCreateOptions: $.noop,
590
	_getCreateEventData: $.noop,
591
	_create: $.noop,
592
	_init: $.noop,
593
594
	destroy: function() {
595
		this._destroy();
596
		// we can probably remove the unbind calls in 2.0
597
		// all event bindings should go through this._on()
598
		this.element
599
			.unbind( this.eventNamespace )
600
			.removeData( this.widgetFullName )
601
			// support: jquery <1.6.3
602
			// http://bugs.jquery.com/ticket/9413
603
			.removeData( $.camelCase( this.widgetFullName ) );
604
		this.widget()
605
			.unbind( this.eventNamespace )
606
			.removeAttr( "aria-disabled" )
607
			.removeClass(
608
				this.widgetFullName + "-disabled " +
609
				"ui-state-disabled" );
610
611
		// clean up events and states
612
		this.bindings.unbind( this.eventNamespace );
613
		this.hoverable.removeClass( "ui-state-hover" );
614
		this.focusable.removeClass( "ui-state-focus" );
615
	},
616
	_destroy: $.noop,
617
618
	widget: function() {
619
		return this.element;
620
	},
621
622
	option: function( key, value ) {
623
		var options = key,
624
			parts,
625
			curOption,
626
			i;
627
628
		if ( arguments.length === 0 ) {
629
			// don't return a reference to the internal hash
630
			return $.widget.extend( {}, this.options );
631
		}
632
633
		if ( typeof key === "string" ) {
634
			// handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
635
			options = {};
636
			parts = key.split( "." );
637
			key = parts.shift();
638
			if ( parts.length ) {
639
				curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
640
				for ( i = 0; i < parts.length - 1; i++ ) {
641
					curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
642
					curOption = curOption[ parts[ i ] ];
643
				}
644
				key = parts.pop();
645
				if ( arguments.length === 1 ) {
646
					return curOption[ key ] === undefined ? null : curOption[ key ];
647
				}
648
				curOption[ key ] = value;
649
			} else {
650
				if ( arguments.length === 1 ) {
651
					return this.options[ key ] === undefined ? null : this.options[ key ];
652
				}
653
				options[ key ] = value;
654
			}
655
		}
656
657
		this._setOptions( options );
658
659
		return this;
660
	},
661
	_setOptions: function( options ) {
662
		var key;
663
664
		for ( key in options ) {
665
			this._setOption( key, options[ key ] );
666
		}
667
668
		return this;
669
	},
670
	_setOption: function( key, value ) {
671
		this.options[ key ] = value;
672
673
		if ( key === "disabled" ) {
674
			this.widget()
675
				.toggleClass( this.widgetFullName + "-disabled", !!value );
676
677
			// If the widget is becoming disabled, then nothing is interactive
678
			if ( value ) {
679
				this.hoverable.removeClass( "ui-state-hover" );
680
				this.focusable.removeClass( "ui-state-focus" );
681
			}
682
		}
683
684
		return this;
685
	},
686
687
	enable: function() {
688
		return this._setOptions({ disabled: false });
689
	},
690
	disable: function() {
691
		return this._setOptions({ disabled: true });
692
	},
693
694
	_on: function( suppressDisabledCheck, element, handlers ) {
695
		var delegateElement,
696
			instance = this;
697
698
		// no suppressDisabledCheck flag, shuffle arguments
699
		if ( typeof suppressDisabledCheck !== "boolean" ) {
700
			handlers = element;
701
			element = suppressDisabledCheck;
702
			suppressDisabledCheck = false;
703
		}
704
705
		// no element argument, shuffle and use this.element
706
		if ( !handlers ) {
707
			handlers = element;
708
			element = this.element;
709
			delegateElement = this.widget();
710
		} else {
711
			element = delegateElement = $( element );
712
			this.bindings = this.bindings.add( element );
713
		}
714
715
		$.each( handlers, function( event, handler ) {
716
			function handlerProxy() {
717
				// allow widgets to customize the disabled handling
718
				// - disabled as an array instead of boolean
719
				// - disabled class as method for disabling individual parts
720
				if ( !suppressDisabledCheck &&
721
						( instance.options.disabled === true ||
722
							$( this ).hasClass( "ui-state-disabled" ) ) ) {
723
					return;
724
				}
725
				return ( typeof handler === "string" ? instance[ handler ] : handler )
726
					.apply( instance, arguments );
727
			}
728
729
			// copy the guid so direct unbinding works
730
			if ( typeof handler !== "string" ) {
731
				handlerProxy.guid = handler.guid =
732
					handler.guid || handlerProxy.guid || $.guid++;
733
			}
734
735
			var match = event.match( /^([\w:-]*)\s*(.*)$/ ),
736
				eventName = match[1] + instance.eventNamespace,
737
				selector = match[2];
738
			if ( selector ) {
739
				delegateElement.delegate( selector, eventName, handlerProxy );
740
			} else {
741
				element.bind( eventName, handlerProxy );
742
			}
743
		});
744
	},
745
746
	_off: function( element, eventName ) {
747
		eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) +
748
			this.eventNamespace;
749
		element.unbind( eventName ).undelegate( eventName );
750
751
		// Clear the stack to avoid memory leaks (#10056)
752
		this.bindings = $( this.bindings.not( element ).get() );
753
		this.focusable = $( this.focusable.not( element ).get() );
754
		this.hoverable = $( this.hoverable.not( element ).get() );
755
	},
756
757
	_delay: function( handler, delay ) {
758
		function handlerProxy() {
759
			return ( typeof handler === "string" ? instance[ handler ] : handler )
760
				.apply( instance, arguments );
761
		}
762
		var instance = this;
763
		return setTimeout( handlerProxy, delay || 0 );
764
	},
765
766
	_hoverable: function( element ) {
767
		this.hoverable = this.hoverable.add( element );
768
		this._on( element, {
769
			mouseenter: function( event ) {
770
				$( event.currentTarget ).addClass( "ui-state-hover" );
771
			},
772
			mouseleave: function( event ) {
773
				$( event.currentTarget ).removeClass( "ui-state-hover" );
774
			}
775
		});
776
	},
777
778
	_focusable: function( element ) {
779
		this.focusable = this.focusable.add( element );
780
		this._on( element, {
781
			focusin: function( event ) {
782
				$( event.currentTarget ).addClass( "ui-state-focus" );
783
			},
784
			focusout: function( event ) {
785
				$( event.currentTarget ).removeClass( "ui-state-focus" );
786
			}
787
		});
788
	},
789
790
	_trigger: function( type, event, data ) {
791
		var prop, orig,
792
			callback = this.options[ type ];
793
794
		data = data || {};
795
		event = $.Event( event );
796
		event.type = ( type === this.widgetEventPrefix ?
797
			type :
798
			this.widgetEventPrefix + type ).toLowerCase();
799
		// the original event may come from any element
800
		// so we need to reset the target on the new event
801
		event.target = this.element[ 0 ];
802
803
		// copy original event properties over to the new event
804
		orig = event.originalEvent;
805
		if ( orig ) {
806
			for ( prop in orig ) {
807
				if ( !( prop in event ) ) {
808
					event[ prop ] = orig[ prop ];
809
				}
810
			}
811
		}
812
813
		this.element.trigger( event, data );
814
		return !( $.isFunction( callback ) &&
815
			callback.apply( this.element[0], [ event ].concat( data ) ) === false ||
816
			event.isDefaultPrevented() );
817
	}
818
};
819
820
$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
821
	$.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
822
		if ( typeof options === "string" ) {
823
			options = { effect: options };
824
		}
825
		var hasOptions,
826
			effectName = !options ?
827
				method :
828
				options === true || typeof options === "number" ?
829
					defaultEffect :
830
					options.effect || defaultEffect;
831
		options = options || {};
832
		if ( typeof options === "number" ) {
833
			options = { duration: options };
834
		}
835
		hasOptions = !$.isEmptyObject( options );
836
		options.complete = callback;
837
		if ( options.delay ) {
838
			element.delay( options.delay );
839
		}
840
		if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
841
			element[ method ]( options );
842
		} else if ( effectName !== method && element[ effectName ] ) {
843
			element[ effectName ]( options.duration, options.easing, callback );
844
		} else {
845
			element.queue(function( next ) {
846
				$( this )[ method ]();
847
				if ( callback ) {
848
					callback.call( element[ 0 ] );
849
				}
850
				next();
851
			});
852
		}
853
	};
854
});
855
856
var widget = $.widget;
857
858
859
/*!
860
 * jQuery UI Mouse 1.11.4
861
 * http://jqueryui.com
862
 *
863
 * Copyright jQuery Foundation and other contributors
864
 * Released under the MIT license.
865
 * http://jquery.org/license
866
 *
867
 * http://api.jqueryui.com/mouse/
868
 */
869
870
871
var mouseHandled = false;
872
$( document ).mouseup( function() {
873
	mouseHandled = false;
874
});
875
876
var mouse = $.widget("ui.mouse", {
877
	version: "1.11.4",
878
	options: {
879
		cancel: "input,textarea,button,select,option",
880
		distance: 1,
881
		delay: 0
882
	},
883
	_mouseInit: function() {
884
		var that = this;
885
886
		this.element
887
			.bind("mousedown." + this.widgetName, function(event) {
888
				return that._mouseDown(event);
889
			})
890
			.bind("click." + this.widgetName, function(event) {
891
				if (true === $.data(event.target, that.widgetName + ".preventClickEvent")) {
892
					$.removeData(event.target, that.widgetName + ".preventClickEvent");
893
					event.stopImmediatePropagation();
894
					return false;
895
				}
896
			});
897
898
		this.started = false;
899
	},
900
901
	// TODO: make sure destroying one instance of mouse doesn't mess with
902
	// other instances of mouse
903
	_mouseDestroy: function() {
904
		this.element.unbind("." + this.widgetName);
905
		if ( this._mouseMoveDelegate ) {
906
			this.document
907
				.unbind("mousemove." + this.widgetName, this._mouseMoveDelegate)
908
				.unbind("mouseup." + this.widgetName, this._mouseUpDelegate);
909
		}
910
	},
911
912
	_mouseDown: function(event) {
913
		// don't let more than one widget handle mouseStart
914
		if ( mouseHandled ) {
915
			return;
916
		}
917
918
		this._mouseMoved = false;
919
920
		// we may have missed mouseup (out of window)
921
		(this._mouseStarted && this._mouseUp(event));
922
923
		this._mouseDownEvent = event;
924
925
		var that = this,
926
			btnIsLeft = (event.which === 1),
927
			// event.target.nodeName works around a bug in IE 8 with
928
			// disabled inputs (#7620)
929
			elIsCancel = (typeof this.options.cancel === "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false);
930
		if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
931
			return true;
932
		}
933
934
		this.mouseDelayMet = !this.options.delay;
935
		if (!this.mouseDelayMet) {
936
			this._mouseDelayTimer = setTimeout(function() {
937
				that.mouseDelayMet = true;
938
			}, this.options.delay);
939
		}
940
941
		if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
942
			this._mouseStarted = (this._mouseStart(event) !== false);
943
			if (!this._mouseStarted) {
944
				event.preventDefault();
945
				return true;
946
			}
947
		}
948
949
		// Click event may never have fired (Gecko & Opera)
950
		if (true === $.data(event.target, this.widgetName + ".preventClickEvent")) {
951
			$.removeData(event.target, this.widgetName + ".preventClickEvent");
952
		}
953
954
		// these delegates are required to keep context
955
		this._mouseMoveDelegate = function(event) {
956
			return that._mouseMove(event);
957
		};
958
		this._mouseUpDelegate = function(event) {
959
			return that._mouseUp(event);
960
		};
961
962
		this.document
963
			.bind( "mousemove." + this.widgetName, this._mouseMoveDelegate )
964
			.bind( "mouseup." + this.widgetName, this._mouseUpDelegate );
965
966
		event.preventDefault();
967
968
		mouseHandled = true;
969
		return true;
970
	},
971
972
	_mouseMove: function(event) {
973
		// Only check for mouseups outside the document if you've moved inside the document
974
		// at least once. This prevents the firing of mouseup in the case of IE<9, which will
975
		// fire a mousemove event if content is placed under the cursor. See #7778
976
		// Support: IE <9
977
		if ( this._mouseMoved ) {
978
			// IE mouseup check - mouseup happened when mouse was out of window
979
			if ($.ui.ie && ( !document.documentMode || document.documentMode < 9 ) && !event.button) {
980
				return this._mouseUp(event);
981
982
			// Iframe mouseup check - mouseup occurred in another document
983
			} else if ( !event.which ) {
984
				return this._mouseUp( event );
985
			}
986
		}
987
988
		if ( event.which || event.button ) {
989
			this._mouseMoved = true;
990
		}
991
992
		if (this._mouseStarted) {
993
			this._mouseDrag(event);
994
			return event.preventDefault();
995
		}
996
997
		if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
998
			this._mouseStarted =
999
				(this._mouseStart(this._mouseDownEvent, event) !== false);
1000
			(this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
1001
		}
1002
1003
		return !this._mouseStarted;
1004
	},
1005
1006
	_mouseUp: function(event) {
1007
		this.document
1008
			.unbind( "mousemove." + this.widgetName, this._mouseMoveDelegate )
1009
			.unbind( "mouseup." + this.widgetName, this._mouseUpDelegate );
1010
1011
		if (this._mouseStarted) {
1012
			this._mouseStarted = false;
1013
1014
			if (event.target === this._mouseDownEvent.target) {
1015
				$.data(event.target, this.widgetName + ".preventClickEvent", true);
1016
			}
1017
1018
			this._mouseStop(event);
1019
		}
1020
1021
		mouseHandled = false;
1022
		return false;
1023
	},
1024
1025
	_mouseDistanceMet: function(event) {
1026
		return (Math.max(
1027
				Math.abs(this._mouseDownEvent.pageX - event.pageX),
1028
				Math.abs(this._mouseDownEvent.pageY - event.pageY)
1029
			) >= this.options.distance
1030
		);
1031
	},
1032
1033
	_mouseDelayMet: function(/* event */) {
1034
		return this.mouseDelayMet;
1035
	},
1036
1037
	// These are placeholder methods, to be overriden by extending plugin
1038
	_mouseStart: function(/* event */) {},
1039
	_mouseDrag: function(/* event */) {},
1040
	_mouseStop: function(/* event */) {},
1041
	_mouseCapture: function(/* event */) { return true; }
1042
});
1043
1044
1045
/*!
1046
 * jQuery UI Position 1.11.4
1047
 * http://jqueryui.com
1048
 *
1049
 * Copyright jQuery Foundation and other contributors
1050
 * Released under the MIT license.
1051
 * http://jquery.org/license
1052
 *
1053
 * http://api.jqueryui.com/position/
1054
 */
1055
1056
(function() {
1057
1058
$.ui = $.ui || {};
1059
1060
var cachedScrollbarWidth, supportsOffsetFractions,
1061
	max = Math.max,
1062
	abs = Math.abs,
1063
	round = Math.round,
1064
	rhorizontal = /left|center|right/,
1065
	rvertical = /top|center|bottom/,
1066
	roffset = /[\+\-]\d+(\.[\d]+)?%?/,
1067
	rposition = /^\w+/,
1068
	rpercent = /%$/,
1069
	_position = $.fn.position;
1070
1071
function getOffsets( offsets, width, height ) {
1072
	return [
1073
		parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),
1074
		parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )
1075
	];
1076
}
1077
1078
function parseCss( element, property ) {
1079
	return parseInt( $.css( element, property ), 10 ) || 0;
1080
}
1081
1082
function getDimensions( elem ) {
1083
	var raw = elem[0];
1084
	if ( raw.nodeType === 9 ) {
1085
		return {
1086
			width: elem.width(),
1087
			height: elem.height(),
1088
			offset: { top: 0, left: 0 }
1089
		};
1090
	}
1091
	if ( $.isWindow( raw ) ) {
1092
		return {
1093
			width: elem.width(),
1094
			height: elem.height(),
1095
			offset: { top: elem.scrollTop(), left: elem.scrollLeft() }
1096
		};
1097
	}
1098
	if ( raw.preventDefault ) {
1099
		return {
1100
			width: 0,
1101
			height: 0,
1102
			offset: { top: raw.pageY, left: raw.pageX }
1103
		};
1104
	}
1105
	return {
1106
		width: elem.outerWidth(),
1107
		height: elem.outerHeight(),
1108
		offset: elem.offset()
1109
	};
1110
}
1111
1112
$.position = {
1113
	scrollbarWidth: function() {
1114
		if ( cachedScrollbarWidth !== undefined ) {
1115
			return cachedScrollbarWidth;
1116
		}
1117
		var w1, w2,
1118
			div = $( "<div style='display:block;position:absolute;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>" ),
1119
			innerDiv = div.children()[0];
1120
1121
		$( "body" ).append( div );
1122
		w1 = innerDiv.offsetWidth;
1123
		div.css( "overflow", "scroll" );
1124
1125
		w2 = innerDiv.offsetWidth;
1126
1127
		if ( w1 === w2 ) {
1128
			w2 = div[0].clientWidth;
1129
		}
1130
1131
		div.remove();
1132
1133
		return (cachedScrollbarWidth = w1 - w2);
1134
	},
1135
	getScrollInfo: function( within ) {
1136
		var overflowX = within.isWindow || within.isDocument ? "" :
1137
				within.element.css( "overflow-x" ),
1138
			overflowY = within.isWindow || within.isDocument ? "" :
1139
				within.element.css( "overflow-y" ),
1140
			hasOverflowX = overflowX === "scroll" ||
1141
				( overflowX === "auto" && within.width < within.element[0].scrollWidth ),
1142
			hasOverflowY = overflowY === "scroll" ||
1143
				( overflowY === "auto" && within.height < within.element[0].scrollHeight );
1144
		return {
1145
			width: hasOverflowY ? $.position.scrollbarWidth() : 0,
1146
			height: hasOverflowX ? $.position.scrollbarWidth() : 0
1147
		};
1148
	},
1149
	getWithinInfo: function( element ) {
1150
		var withinElement = $( element || window ),
1151
			isWindow = $.isWindow( withinElement[0] ),
1152
			isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9;
1153
		return {
1154
			element: withinElement,
1155
			isWindow: isWindow,
1156
			isDocument: isDocument,
1157
			offset: withinElement.offset() || { left: 0, top: 0 },
1158
			scrollLeft: withinElement.scrollLeft(),
1159
			scrollTop: withinElement.scrollTop(),
1160
1161
			// support: jQuery 1.6.x
1162
			// jQuery 1.6 doesn't support .outerWidth/Height() on documents or windows
1163
			width: isWindow || isDocument ? withinElement.width() : withinElement.outerWidth(),
1164
			height: isWindow || isDocument ? withinElement.height() : withinElement.outerHeight()
1165
		};
1166
	}
1167
};
1168
1169
$.fn.position = function( options ) {
1170
	if ( !options || !options.of ) {
1171
		return _position.apply( this, arguments );
1172
	}
1173
1174
	// make a copy, we don't want to modify arguments
1175
	options = $.extend( {}, options );
1176
1177
	var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,
1178
		target = $( options.of ),
1179
		within = $.position.getWithinInfo( options.within ),
1180
		scrollInfo = $.position.getScrollInfo( within ),
1181
		collision = ( options.collision || "flip" ).split( " " ),
1182
		offsets = {};
1183
1184
	dimensions = getDimensions( target );
1185
	if ( target[0].preventDefault ) {
1186
		// force left top to allow flipping
1187
		options.at = "left top";
1188
	}
1189
	targetWidth = dimensions.width;
1190
	targetHeight = dimensions.height;
1191
	targetOffset = dimensions.offset;
1192
	// clone to reuse original targetOffset later
1193
	basePosition = $.extend( {}, targetOffset );
1194
1195
	// force my and at to have valid horizontal and vertical positions
1196
	// if a value is missing or invalid, it will be converted to center
1197
	$.each( [ "my", "at" ], function() {
1198
		var pos = ( options[ this ] || "" ).split( " " ),
1199
			horizontalOffset,
1200
			verticalOffset;
1201
1202
		if ( pos.length === 1) {
1203
			pos = rhorizontal.test( pos[ 0 ] ) ?
1204
				pos.concat( [ "center" ] ) :
1205
				rvertical.test( pos[ 0 ] ) ?
1206
					[ "center" ].concat( pos ) :
1207
					[ "center", "center" ];
1208
		}
1209
		pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center";
1210
		pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";
1211
1212
		// calculate offsets
1213
		horizontalOffset = roffset.exec( pos[ 0 ] );
1214
		verticalOffset = roffset.exec( pos[ 1 ] );
1215
		offsets[ this ] = [
1216
			horizontalOffset ? horizontalOffset[ 0 ] : 0,
1217
			verticalOffset ? verticalOffset[ 0 ] : 0
1218
		];
1219
1220
		// reduce to just the positions without the offsets
1221
		options[ this ] = [
1222
			rposition.exec( pos[ 0 ] )[ 0 ],
1223
			rposition.exec( pos[ 1 ] )[ 0 ]
1224
		];
1225
	});
1226
1227
	// normalize collision option
1228
	if ( collision.length === 1 ) {
1229
		collision[ 1 ] = collision[ 0 ];
1230
	}
1231
1232
	if ( options.at[ 0 ] === "right" ) {
1233
		basePosition.left += targetWidth;
1234
	} else if ( options.at[ 0 ] === "center" ) {
1235
		basePosition.left += targetWidth / 2;
1236
	}
1237
1238
	if ( options.at[ 1 ] === "bottom" ) {
1239
		basePosition.top += targetHeight;
1240
	} else if ( options.at[ 1 ] === "center" ) {
1241
		basePosition.top += targetHeight / 2;
1242
	}
1243
1244
	atOffset = getOffsets( offsets.at, targetWidth, targetHeight );
1245
	basePosition.left += atOffset[ 0 ];
1246
	basePosition.top += atOffset[ 1 ];
1247
1248
	return this.each(function() {
1249
		var collisionPosition, using,
1250
			elem = $( this ),
1251
			elemWidth = elem.outerWidth(),
1252
			elemHeight = elem.outerHeight(),
1253
			marginLeft = parseCss( this, "marginLeft" ),
1254
			marginTop = parseCss( this, "marginTop" ),
1255
			collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) + scrollInfo.width,
1256
			collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) + scrollInfo.height,
1257
			position = $.extend( {}, basePosition ),
1258
			myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );
1259
1260
		if ( options.my[ 0 ] === "right" ) {
1261
			position.left -= elemWidth;
1262
		} else if ( options.my[ 0 ] === "center" ) {
1263
			position.left -= elemWidth / 2;
1264
		}
1265
1266
		if ( options.my[ 1 ] === "bottom" ) {
1267
			position.top -= elemHeight;
1268
		} else if ( options.my[ 1 ] === "center" ) {
1269
			position.top -= elemHeight / 2;
1270
		}
1271
1272
		position.left += myOffset[ 0 ];
1273
		position.top += myOffset[ 1 ];
1274
1275
		// if the browser doesn't support fractions, then round for consistent results
1276
		if ( !supportsOffsetFractions ) {
1277
			position.left = round( position.left );
1278
			position.top = round( position.top );
1279
		}
1280
1281
		collisionPosition = {
1282
			marginLeft: marginLeft,
1283
			marginTop: marginTop
1284
		};
1285
1286
		$.each( [ "left", "top" ], function( i, dir ) {
1287
			if ( $.ui.position[ collision[ i ] ] ) {
1288
				$.ui.position[ collision[ i ] ][ dir ]( position, {
1289
					targetWidth: targetWidth,
1290
					targetHeight: targetHeight,
1291
					elemWidth: elemWidth,
1292
					elemHeight: elemHeight,
1293
					collisionPosition: collisionPosition,
1294
					collisionWidth: collisionWidth,
1295
					collisionHeight: collisionHeight,
1296
					offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],
1297
					my: options.my,
1298
					at: options.at,
1299
					within: within,
1300
					elem: elem
1301
				});
1302
			}
1303
		});
1304
1305
		if ( options.using ) {
1306
			// adds feedback as second argument to using callback, if present
1307
			using = function( props ) {
1308
				var left = targetOffset.left - position.left,
1309
					right = left + targetWidth - elemWidth,
1310
					top = targetOffset.top - position.top,
1311
					bottom = top + targetHeight - elemHeight,
1312
					feedback = {
1313
						target: {
1314
							element: target,
1315
							left: targetOffset.left,
1316
							top: targetOffset.top,
1317
							width: targetWidth,
1318
							height: targetHeight
1319
						},
1320
						element: {
1321
							element: elem,
1322
							left: position.left,
1323
							top: position.top,
1324
							width: elemWidth,
1325
							height: elemHeight
1326
						},
1327
						horizontal: right < 0 ? "left" : left > 0 ? "right" : "center",
1328
						vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle"
1329
					};
1330
				if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {
1331
					feedback.horizontal = "center";
1332
				}
1333
				if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {
1334
					feedback.vertical = "middle";
1335
				}
1336
				if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {
1337
					feedback.important = "horizontal";
1338
				} else {
1339
					feedback.important = "vertical";
1340
				}
1341
				options.using.call( this, props, feedback );
1342
			};
1343
		}
1344
1345
		elem.offset( $.extend( position, { using: using } ) );
1346
	});
1347
};
1348
1349
$.ui.position = {
1350
	fit: {
1351
		left: function( position, data ) {
1352
			var within = data.within,
1353
				withinOffset = within.isWindow ? within.scrollLeft : within.offset.left,
1354
				outerWidth = within.width,
1355
				collisionPosLeft = position.left - data.collisionPosition.marginLeft,
1356
				overLeft = withinOffset - collisionPosLeft,
1357
				overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
1358
				newOverRight;
1359
1360
			// element is wider than within
1361
			if ( data.collisionWidth > outerWidth ) {
1362
				// element is initially over the left side of within
1363
				if ( overLeft > 0 && overRight <= 0 ) {
1364
					newOverRight = position.left + overLeft + data.collisionWidth - outerWidth - withinOffset;
1365
					position.left += overLeft - newOverRight;
1366
				// element is initially over right side of within
1367
				} else if ( overRight > 0 && overLeft <= 0 ) {
1368
					position.left = withinOffset;
1369
				// element is initially over both left and right sides of within
1370
				} else {
1371
					if ( overLeft > overRight ) {
1372
						position.left = withinOffset + outerWidth - data.collisionWidth;
1373
					} else {
1374
						position.left = withinOffset;
1375
					}
1376
				}
1377
			// too far left -> align with left edge
1378
			} else if ( overLeft > 0 ) {
1379
				position.left += overLeft;
1380
			// too far right -> align with right edge
1381
			} else if ( overRight > 0 ) {
1382
				position.left -= overRight;
1383
			// adjust based on position and margin
1384
			} else {
1385
				position.left = max( position.left - collisionPosLeft, position.left );
1386
			}
1387
		},
1388
		top: function( position, data ) {
1389
			var within = data.within,
1390
				withinOffset = within.isWindow ? within.scrollTop : within.offset.top,
1391
				outerHeight = data.within.height,
1392
				collisionPosTop = position.top - data.collisionPosition.marginTop,
1393
				overTop = withinOffset - collisionPosTop,
1394
				overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
1395
				newOverBottom;
1396
1397
			// element is taller than within
1398
			if ( data.collisionHeight > outerHeight ) {
1399
				// element is initially over the top of within
1400
				if ( overTop > 0 && overBottom <= 0 ) {
1401
					newOverBottom = position.top + overTop + data.collisionHeight - outerHeight - withinOffset;
1402
					position.top += overTop - newOverBottom;
1403
				// element is initially over bottom of within
1404
				} else if ( overBottom > 0 && overTop <= 0 ) {
1405
					position.top = withinOffset;
1406
				// element is initially over both top and bottom of within
1407
				} else {
1408
					if ( overTop > overBottom ) {
1409
						position.top = withinOffset + outerHeight - data.collisionHeight;
1410
					} else {
1411
						position.top = withinOffset;
1412
					}
1413
				}
1414
			// too far up -> align with top
1415
			} else if ( overTop > 0 ) {
1416
				position.top += overTop;
1417
			// too far down -> align with bottom edge
1418
			} else if ( overBottom > 0 ) {
1419
				position.top -= overBottom;
1420
			// adjust based on position and margin
1421
			} else {
1422
				position.top = max( position.top - collisionPosTop, position.top );
1423
			}
1424
		}
1425
	},
1426
	flip: {
1427
		left: function( position, data ) {
1428
			var within = data.within,
1429
				withinOffset = within.offset.left + within.scrollLeft,
1430
				outerWidth = within.width,
1431
				offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,
1432
				collisionPosLeft = position.left - data.collisionPosition.marginLeft,
1433
				overLeft = collisionPosLeft - offsetLeft,
1434
				overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,
1435
				myOffset = data.my[ 0 ] === "left" ?
1436
					-data.elemWidth :
1437
					data.my[ 0 ] === "right" ?
1438
						data.elemWidth :
1439
						0,
1440
				atOffset = data.at[ 0 ] === "left" ?
1441
					data.targetWidth :
1442
					data.at[ 0 ] === "right" ?
1443
						-data.targetWidth :
1444
						0,
1445
				offset = -2 * data.offset[ 0 ],
1446
				newOverRight,
1447
				newOverLeft;
1448
1449
			if ( overLeft < 0 ) {
1450
				newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - outerWidth - withinOffset;
1451
				if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {
1452
					position.left += myOffset + atOffset + offset;
1453
				}
1454
			} else if ( overRight > 0 ) {
1455
				newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + atOffset + offset - offsetLeft;
1456
				if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {
1457
					position.left += myOffset + atOffset + offset;
1458
				}
1459
			}
1460
		},
1461
		top: function( position, data ) {
1462
			var within = data.within,
1463
				withinOffset = within.offset.top + within.scrollTop,
1464
				outerHeight = within.height,
1465
				offsetTop = within.isWindow ? within.scrollTop : within.offset.top,
1466
				collisionPosTop = position.top - data.collisionPosition.marginTop,
1467
				overTop = collisionPosTop - offsetTop,
1468
				overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,
1469
				top = data.my[ 1 ] === "top",
1470
				myOffset = top ?
1471
					-data.elemHeight :
1472
					data.my[ 1 ] === "bottom" ?
1473
						data.elemHeight :
1474
						0,
1475
				atOffset = data.at[ 1 ] === "top" ?
1476
					data.targetHeight :
1477
					data.at[ 1 ] === "bottom" ?
1478
						-data.targetHeight :
1479
						0,
1480
				offset = -2 * data.offset[ 1 ],
1481
				newOverTop,
1482
				newOverBottom;
1483
			if ( overTop < 0 ) {
1484
				newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - outerHeight - withinOffset;
1485
				if ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) {
1486
					position.top += myOffset + atOffset + offset;
1487
				}
1488
			} else if ( overBottom > 0 ) {
1489
				newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset + offset - offsetTop;
1490
				if ( newOverTop > 0 || abs( newOverTop ) < overBottom ) {
1491
					position.top += myOffset + atOffset + offset;
1492
				}
1493
			}
1494
		}
1495
	},
1496
	flipfit: {
1497
		left: function() {
1498
			$.ui.position.flip.left.apply( this, arguments );
1499
			$.ui.position.fit.left.apply( this, arguments );
1500
		},
1501
		top: function() {
1502
			$.ui.position.flip.top.apply( this, arguments );
1503
			$.ui.position.fit.top.apply( this, arguments );
1504
		}
1505
	}
1506
};
1507
1508
// fraction support test
1509
(function() {
1510
	var testElement, testElementParent, testElementStyle, offsetLeft, i,
1511
		body = document.getElementsByTagName( "body" )[ 0 ],
1512
		div = document.createElement( "div" );
1513
1514
	//Create a "fake body" for testing based on method used in jQuery.support
1515
	testElement = document.createElement( body ? "div" : "body" );
1516
	testElementStyle = {
1517
		visibility: "hidden",
1518
		width: 0,
1519
		height: 0,
1520
		border: 0,
1521
		margin: 0,
1522
		background: "none"
1523
	};
1524
	if ( body ) {
1525
		$.extend( testElementStyle, {
1526
			position: "absolute",
1527
			left: "-1000px",
1528
			top: "-1000px"
1529
		});
1530
	}
1531
	for ( i in testElementStyle ) {
1532
		testElement.style[ i ] = testElementStyle[ i ];
1533
	}
1534
	testElement.appendChild( div );
1535
	testElementParent = body || document.documentElement;
1536
	testElementParent.insertBefore( testElement, testElementParent.firstChild );
1537
1538
	div.style.cssText = "position: absolute; left: 10.7432222px;";
1539
1540
	offsetLeft = $( div ).offset().left;
1541
	supportsOffsetFractions = offsetLeft > 10 && offsetLeft < 11;
1542
1543
	testElement.innerHTML = "";
1544
	testElementParent.removeChild( testElement );
1545
})();
1546
1547
})();
1548
1549
var position = $.ui.position;
1550
1551
1552
/*!
1553
 * jQuery UI Accordion 1.11.4
1554
 * http://jqueryui.com
1555
 *
1556
 * Copyright jQuery Foundation and other contributors
1557
 * Released under the MIT license.
1558
 * http://jquery.org/license
1559
 *
1560
 * http://api.jqueryui.com/accordion/
1561
 */
1562
1563
1564
var accordion = $.widget( "ui.accordion", {
1565
	version: "1.11.4",
1566
	options: {
1567
		active: 0,
1568
		animate: {},
1569
		collapsible: false,
1570
		event: "click",
1571
		header: "> li > :first-child,> :not(li):even",
1572
		heightStyle: "auto",
1573
		icons: {
1574
			activeHeader: "ui-icon-triangle-1-s",
1575
			header: "ui-icon-triangle-1-e"
1576
		},
1577
1578
		// callbacks
1579
		activate: null,
1580
		beforeActivate: null
1581
	},
1582
1583
	hideProps: {
1584
		borderTopWidth: "hide",
1585
		borderBottomWidth: "hide",
1586
		paddingTop: "hide",
1587
		paddingBottom: "hide",
1588
		height: "hide"
1589
	},
1590
1591
	showProps: {
1592
		borderTopWidth: "show",
1593
		borderBottomWidth: "show",
1594
		paddingTop: "show",
1595
		paddingBottom: "show",
1596
		height: "show"
1597
	},
1598
1599
	_create: function() {
1600
		var options = this.options;
1601
		this.prevShow = this.prevHide = $();
1602
		this.element.addClass( "ui-accordion ui-widget ui-helper-reset" )
1603
			// ARIA
1604
			.attr( "role", "tablist" );
1605
1606
		// don't allow collapsible: false and active: false / null
1607
		if ( !options.collapsible && (options.active === false || options.active == null) ) {
1608
			options.active = 0;
1609
		}
1610
1611
		this._processPanels();
1612
		// handle negative values
1613
		if ( options.active < 0 ) {
1614
			options.active += this.headers.length;
1615
		}
1616
		this._refresh();
1617
	},
1618
1619
	_getCreateEventData: function() {
1620
		return {
1621
			header: this.active,
1622
			panel: !this.active.length ? $() : this.active.next()
1623
		};
1624
	},
1625
1626
	_createIcons: function() {
1627
		var icons = this.options.icons;
1628
		if ( icons ) {
1629
			$( "<span>" )
1630
				.addClass( "ui-accordion-header-icon ui-icon " + icons.header )
1631
				.prependTo( this.headers );
1632
			this.active.children( ".ui-accordion-header-icon" )
1633
				.removeClass( icons.header )
1634
				.addClass( icons.activeHeader );
1635
			this.headers.addClass( "ui-accordion-icons" );
1636
		}
1637
	},
1638
1639
	_destroyIcons: function() {
1640
		this.headers
1641
			.removeClass( "ui-accordion-icons" )
1642
			.children( ".ui-accordion-header-icon" )
1643
				.remove();
1644
	},
1645
1646
	_destroy: function() {
1647
		var contents;
1648
1649
		// clean up main element
1650
		this.element
1651
			.removeClass( "ui-accordion ui-widget ui-helper-reset" )
1652
			.removeAttr( "role" );
1653
1654
		// clean up headers
1655
		this.headers
1656
			.removeClass( "ui-accordion-header ui-accordion-header-active ui-state-default " +
1657
				"ui-corner-all ui-state-active ui-state-disabled ui-corner-top" )
1658
			.removeAttr( "role" )
1659
			.removeAttr( "aria-expanded" )
1660
			.removeAttr( "aria-selected" )
1661
			.removeAttr( "aria-controls" )
1662
			.removeAttr( "tabIndex" )
1663
			.removeUniqueId();
1664
1665
		this._destroyIcons();
1666
1667
		// clean up content panels
1668
		contents = this.headers.next()
1669
			.removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom " +
1670
				"ui-accordion-content ui-accordion-content-active ui-state-disabled" )
1671
			.css( "display", "" )
1672
			.removeAttr( "role" )
1673
			.removeAttr( "aria-hidden" )
1674
			.removeAttr( "aria-labelledby" )
1675
			.removeUniqueId();
1676
1677
		if ( this.options.heightStyle !== "content" ) {
1678
			contents.css( "height", "" );
1679
		}
1680
	},
1681
1682
	_setOption: function( key, value ) {
1683
		if ( key === "active" ) {
1684
			// _activate() will handle invalid values and update this.options
1685
			this._activate( value );
1686
			return;
1687
		}
1688
1689
		if ( key === "event" ) {
1690
			if ( this.options.event ) {
1691
				this._off( this.headers, this.options.event );
1692
			}
1693
			this._setupEvents( value );
1694
		}
1695
1696
		this._super( key, value );
1697
1698
		// setting collapsible: false while collapsed; open first panel
1699
		if ( key === "collapsible" && !value && this.options.active === false ) {
1700
			this._activate( 0 );
1701
		}
1702
1703
		if ( key === "icons" ) {
1704
			this._destroyIcons();
1705
			if ( value ) {
1706
				this._createIcons();
1707
			}
1708
		}
1709
1710
		// #5332 - opacity doesn't cascade to positioned elements in IE
1711
		// so we need to add the disabled class to the headers and panels
1712
		if ( key === "disabled" ) {
1713
			this.element
1714
				.toggleClass( "ui-state-disabled", !!value )
1715
				.attr( "aria-disabled", value );
1716
			this.headers.add( this.headers.next() )
1717
				.toggleClass( "ui-state-disabled", !!value );
1718
		}
1719
	},
1720
1721
	_keydown: function( event ) {
1722
		if ( event.altKey || event.ctrlKey ) {
1723
			return;
1724
		}
1725
1726
		var keyCode = $.ui.keyCode,
1727
			length = this.headers.length,
1728
			currentIndex = this.headers.index( event.target ),
1729
			toFocus = false;
1730
1731
		switch ( event.keyCode ) {
1732
			case keyCode.RIGHT:
1733
			case keyCode.DOWN:
1734
				toFocus = this.headers[ ( currentIndex + 1 ) % length ];
1735
				break;
1736
			case keyCode.LEFT:
1737
			case keyCode.UP:
1738
				toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
1739
				break;
1740
			case keyCode.SPACE:
1741
			case keyCode.ENTER:
1742
				this._eventHandler( event );
1743
				break;
1744
			case keyCode.HOME:
1745
				toFocus = this.headers[ 0 ];
1746
				break;
1747
			case keyCode.END:
1748
				toFocus = this.headers[ length - 1 ];
1749
				break;
1750
		}
1751
1752
		if ( toFocus ) {
1753
			$( event.target ).attr( "tabIndex", -1 );
1754
			$( toFocus ).attr( "tabIndex", 0 );
1755
			toFocus.focus();
1756
			event.preventDefault();
1757
		}
1758
	},
1759
1760
	_panelKeyDown: function( event ) {
1761
		if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) {
1762
			$( event.currentTarget ).prev().focus();
1763
		}
1764
	},
1765
1766
	refresh: function() {
1767
		var options = this.options;
1768
		this._processPanels();
1769
1770
		// was collapsed or no panel
1771
		if ( ( options.active === false && options.collapsible === true ) || !this.headers.length ) {
1772
			options.active = false;
1773
			this.active = $();
1774
		// active false only when collapsible is true
1775
		} else if ( options.active === false ) {
1776
			this._activate( 0 );
1777
		// was active, but active panel is gone
1778
		} else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
1779
			// all remaining panel are disabled
1780
			if ( this.headers.length === this.headers.find(".ui-state-disabled").length ) {
1781
				options.active = false;
1782
				this.active = $();
1783
			// activate previous panel
1784
			} else {
1785
				this._activate( Math.max( 0, options.active - 1 ) );
1786
			}
1787
		// was active, active panel still exists
1788
		} else {
1789
			// make sure active index is correct
1790
			options.active = this.headers.index( this.active );
1791
		}
1792
1793
		this._destroyIcons();
1794
1795
		this._refresh();
1796
	},
1797
1798
	_processPanels: function() {
1799
		var prevHeaders = this.headers,
1800
			prevPanels = this.panels;
1801
1802
		this.headers = this.element.find( this.options.header )
1803
			.addClass( "ui-accordion-header ui-state-default ui-corner-all" );
1804
1805
		this.panels = this.headers.next()
1806
			.addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" )
1807
			.filter( ":not(.ui-accordion-content-active)" )
1808
			.hide();
1809
1810
		// Avoid memory leaks (#10056)
1811
		if ( prevPanels ) {
1812
			this._off( prevHeaders.not( this.headers ) );
1813
			this._off( prevPanels.not( this.panels ) );
1814
		}
1815
	},
1816
1817
	_refresh: function() {
1818
		var maxHeight,
1819
			options = this.options,
1820
			heightStyle = options.heightStyle,
1821
			parent = this.element.parent();
1822
1823
		this.active = this._findActive( options.active )
1824
			.addClass( "ui-accordion-header-active ui-state-active ui-corner-top" )
1825
			.removeClass( "ui-corner-all" );
1826
		this.active.next()
1827
			.addClass( "ui-accordion-content-active" )
1828
			.show();
1829
1830
		this.headers
1831
			.attr( "role", "tab" )
1832
			.each(function() {
1833
				var header = $( this ),
1834
					headerId = header.uniqueId().attr( "id" ),
1835
					panel = header.next(),
1836
					panelId = panel.uniqueId().attr( "id" );
1837
				header.attr( "aria-controls", panelId );
1838
				panel.attr( "aria-labelledby", headerId );
1839
			})
1840
			.next()
1841
				.attr( "role", "tabpanel" );
1842
1843
		this.headers
1844
			.not( this.active )
1845
			.attr({
1846
				"aria-selected": "false",
1847
				"aria-expanded": "false",
1848
				tabIndex: -1
1849
			})
1850
			.next()
1851
				.attr({
1852
					"aria-hidden": "true"
1853
				})
1854
				.hide();
1855
1856
		// make sure at least one header is in the tab order
1857
		if ( !this.active.length ) {
1858
			this.headers.eq( 0 ).attr( "tabIndex", 0 );
1859
		} else {
1860
			this.active.attr({
1861
				"aria-selected": "true",
1862
				"aria-expanded": "true",
1863
				tabIndex: 0
1864
			})
1865
			.next()
1866
				.attr({
1867
					"aria-hidden": "false"
1868
				});
1869
		}
1870
1871
		this._createIcons();
1872
1873
		this._setupEvents( options.event );
1874
1875
		if ( heightStyle === "fill" ) {
1876
			maxHeight = parent.height();
1877
			this.element.siblings( ":visible" ).each(function() {
1878
				var elem = $( this ),
1879
					position = elem.css( "position" );
1880
1881
				if ( position === "absolute" || position === "fixed" ) {
1882
					return;
1883
				}
1884
				maxHeight -= elem.outerHeight( true );
1885
			});
1886
1887
			this.headers.each(function() {
1888
				maxHeight -= $( this ).outerHeight( true );
1889
			});
1890
1891
			this.headers.next()
1892
				.each(function() {
1893
					$( this ).height( Math.max( 0, maxHeight -
1894
						$( this ).innerHeight() + $( this ).height() ) );
1895
				})
1896
				.css( "overflow", "auto" );
1897
		} else if ( heightStyle === "auto" ) {
1898
			maxHeight = 0;
1899
			this.headers.next()
1900
				.each(function() {
1901
					maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() );
1902
				})
1903
				.height( maxHeight );
1904
		}
1905
	},
1906
1907
	_activate: function( index ) {
1908
		var active = this._findActive( index )[ 0 ];
1909
1910
		// trying to activate the already active panel
1911
		if ( active === this.active[ 0 ] ) {
1912
			return;
1913
		}
1914
1915
		// trying to collapse, simulate a click on the currently active header
1916
		active = active || this.active[ 0 ];
1917
1918
		this._eventHandler({
1919
			target: active,
1920
			currentTarget: active,
1921
			preventDefault: $.noop
1922
		});
1923
	},
1924
1925
	_findActive: function( selector ) {
1926
		return typeof selector === "number" ? this.headers.eq( selector ) : $();
1927
	},
1928
1929
	_setupEvents: function( event ) {
1930
		var events = {
1931
			keydown: "_keydown"
1932
		};
1933
		if ( event ) {
1934
			$.each( event.split( " " ), function( index, eventName ) {
1935
				events[ eventName ] = "_eventHandler";
1936
			});
1937
		}
1938
1939
		this._off( this.headers.add( this.headers.next() ) );
1940
		this._on( this.headers, events );
1941
		this._on( this.headers.next(), { keydown: "_panelKeyDown" });
1942
		this._hoverable( this.headers );
1943
		this._focusable( this.headers );
1944
	},
1945
1946
	_eventHandler: function( event ) {
1947
		var options = this.options,
1948
			active = this.active,
1949
			clicked = $( event.currentTarget ),
1950
			clickedIsActive = clicked[ 0 ] === active[ 0 ],
1951
			collapsing = clickedIsActive && options.collapsible,
1952
			toShow = collapsing ? $() : clicked.next(),
1953
			toHide = active.next(),
1954
			eventData = {
1955
				oldHeader: active,
1956
				oldPanel: toHide,
1957
				newHeader: collapsing ? $() : clicked,
1958
				newPanel: toShow
1959
			};
1960
1961
		event.preventDefault();
1962
1963
		if (
1964
				// click on active header, but not collapsible
1965
				( clickedIsActive && !options.collapsible ) ||
1966
				// allow canceling activation
1967
				( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
1968
			return;
1969
		}
1970
1971
		options.active = collapsing ? false : this.headers.index( clicked );
1972
1973
		// when the call to ._toggle() comes after the class changes
1974
		// it causes a very odd bug in IE 8 (see #6720)
1975
		this.active = clickedIsActive ? $() : clicked;
1976
		this._toggle( eventData );
1977
1978
		// switch classes
1979
		// corner classes on the previously active header stay after the animation
1980
		active.removeClass( "ui-accordion-header-active ui-state-active" );
1981
		if ( options.icons ) {
1982
			active.children( ".ui-accordion-header-icon" )
1983
				.removeClass( options.icons.activeHeader )
1984
				.addClass( options.icons.header );
1985
		}
1986
1987
		if ( !clickedIsActive ) {
1988
			clicked
1989
				.removeClass( "ui-corner-all" )
1990
				.addClass( "ui-accordion-header-active ui-state-active ui-corner-top" );
1991
			if ( options.icons ) {
1992
				clicked.children( ".ui-accordion-header-icon" )
1993
					.removeClass( options.icons.header )
1994
					.addClass( options.icons.activeHeader );
1995
			}
1996
1997
			clicked
1998
				.next()
1999
				.addClass( "ui-accordion-content-active" );
2000
		}
2001
	},
2002
2003
	_toggle: function( data ) {
2004
		var toShow = data.newPanel,
2005
			toHide = this.prevShow.length ? this.prevShow : data.oldPanel;
2006
2007
		// handle activating a panel during the animation for another activation
2008
		this.prevShow.add( this.prevHide ).stop( true, true );
2009
		this.prevShow = toShow;
2010
		this.prevHide = toHide;
2011
2012
		if ( this.options.animate ) {
2013
			this._animate( toShow, toHide, data );
2014
		} else {
2015
			toHide.hide();
2016
			toShow.show();
2017
			this._toggleComplete( data );
2018
		}
2019
2020
		toHide.attr({
2021
			"aria-hidden": "true"
2022
		});
2023
		toHide.prev().attr({
2024
			"aria-selected": "false",
2025
			"aria-expanded": "false"
2026
		});
2027
		// if we're switching panels, remove the old header from the tab order
2028
		// if we're opening from collapsed state, remove the previous header from the tab order
2029
		// if we're collapsing, then keep the collapsing header in the tab order
2030
		if ( toShow.length && toHide.length ) {
2031
			toHide.prev().attr({
2032
				"tabIndex": -1,
2033
				"aria-expanded": "false"
2034
			});
2035
		} else if ( toShow.length ) {
2036
			this.headers.filter(function() {
2037
				return parseInt( $( this ).attr( "tabIndex" ), 10 ) === 0;
2038
			})
2039
			.attr( "tabIndex", -1 );
2040
		}
2041
2042
		toShow
2043
			.attr( "aria-hidden", "false" )
2044
			.prev()
2045
				.attr({
2046
					"aria-selected": "true",
2047
					"aria-expanded": "true",
2048
					tabIndex: 0
2049
				});
2050
	},
2051
2052
	_animate: function( toShow, toHide, data ) {
2053
		var total, easing, duration,
2054
			that = this,
2055
			adjust = 0,
2056
			boxSizing = toShow.css( "box-sizing" ),
2057
			down = toShow.length &&
2058
				( !toHide.length || ( toShow.index() < toHide.index() ) ),
2059
			animate = this.options.animate || {},
2060
			options = down && animate.down || animate,
2061
			complete = function() {
2062
				that._toggleComplete( data );
2063
			};
2064
2065
		if ( typeof options === "number" ) {
2066
			duration = options;
2067
		}
2068
		if ( typeof options === "string" ) {
2069
			easing = options;
2070
		}
2071
		// fall back from options to animation in case of partial down settings
2072
		easing = easing || options.easing || animate.easing;
2073
		duration = duration || options.duration || animate.duration;
2074
2075
		if ( !toHide.length ) {
2076
			return toShow.animate( this.showProps, duration, easing, complete );
2077
		}
2078
		if ( !toShow.length ) {
2079
			return toHide.animate( this.hideProps, duration, easing, complete );
2080
		}
2081
2082
		total = toShow.show().outerHeight();
2083
		toHide.animate( this.hideProps, {
2084
			duration: duration,
2085
			easing: easing,
2086
			step: function( now, fx ) {
2087
				fx.now = Math.round( now );
2088
			}
2089
		});
2090
		toShow
2091
			.hide()
2092
			.animate( this.showProps, {
2093
				duration: duration,
2094
				easing: easing,
2095
				complete: complete,
2096
				step: function( now, fx ) {
2097
					fx.now = Math.round( now );
2098
					if ( fx.prop !== "height" ) {
2099
						if ( boxSizing === "content-box" ) {
2100
							adjust += fx.now;
2101
						}
2102
					} else if ( that.options.heightStyle !== "content" ) {
2103
						fx.now = Math.round( total - toHide.outerHeight() - adjust );
2104
						adjust = 0;
2105
					}
2106
				}
2107
			});
2108
	},
2109
2110
	_toggleComplete: function( data ) {
2111
		var toHide = data.oldPanel;
2112
2113
		toHide
2114
			.removeClass( "ui-accordion-content-active" )
2115
			.prev()
2116
				.removeClass( "ui-corner-top" )
2117
				.addClass( "ui-corner-all" );
2118
2119
		// Work around for rendering bug in IE (#5421)
2120
		if ( toHide.length ) {
2121
			toHide.parent()[ 0 ].className = toHide.parent()[ 0 ].className;
2122
		}
2123
		this._trigger( "activate", null, data );
2124
	}
2125
});
2126
2127
2128
/*!
2129
 * jQuery UI Menu 1.11.4
2130
 * http://jqueryui.com
2131
 *
2132
 * Copyright jQuery Foundation and other contributors
2133
 * Released under the MIT license.
2134
 * http://jquery.org/license
2135
 *
2136
 * http://api.jqueryui.com/menu/
2137
 */
2138
2139
2140
var menu = $.widget( "ui.menu", {
2141
	version: "1.11.4",
2142
	defaultElement: "<ul>",
2143
	delay: 300,
2144
	options: {
2145
		icons: {
2146
			submenu: "ui-icon-carat-1-e"
2147
		},
2148
		items: "> *",
2149
		menus: "ul",
2150
		position: {
2151
			my: "left-1 top",
2152
			at: "right top"
2153
		},
2154
		role: "menu",
2155
2156
		// callbacks
2157
		blur: null,
2158
		focus: null,
2159
		select: null
2160
	},
2161
2162
	_create: function() {
2163
		this.activeMenu = this.element;
2164
2165
		// Flag used to prevent firing of the click handler
2166
		// as the event bubbles up through nested menus
2167
		this.mouseHandled = false;
2168
		this.element
2169
			.uniqueId()
2170
			.addClass( "ui-menu ui-widget ui-widget-content" )
2171
			.toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length )
2172
			.attr({
2173
				role: this.options.role,
2174
				tabIndex: 0
2175
			});
2176
2177
		if ( this.options.disabled ) {
2178
			this.element
2179
				.addClass( "ui-state-disabled" )
2180
				.attr( "aria-disabled", "true" );
2181
		}
2182
2183
		this._on({
2184
			// Prevent focus from sticking to links inside menu after clicking
2185
			// them (focus should always stay on UL during navigation).
2186
			"mousedown .ui-menu-item": function( event ) {
2187
				event.preventDefault();
2188
			},
2189
			"click .ui-menu-item": function( event ) {
2190
				var target = $( event.target );
2191
				if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) {
2192
					this.select( event );
2193
2194
					// Only set the mouseHandled flag if the event will bubble, see #9469.
2195
					if ( !event.isPropagationStopped() ) {
2196
						this.mouseHandled = true;
2197
					}
2198
2199
					// Open submenu on click
2200
					if ( target.has( ".ui-menu" ).length ) {
2201
						this.expand( event );
2202
					} else if ( !this.element.is( ":focus" ) && $( this.document[ 0 ].activeElement ).closest( ".ui-menu" ).length ) {
2203
2204
						// Redirect focus to the menu
2205
						this.element.trigger( "focus", [ true ] );
2206
2207
						// If the active item is on the top level, let it stay active.
2208
						// Otherwise, blur the active item since it is no longer visible.
2209
						if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) {
2210
							clearTimeout( this.timer );
2211
						}
2212
					}
2213
				}
2214
			},
2215
			"mouseenter .ui-menu-item": function( event ) {
2216
				// Ignore mouse events while typeahead is active, see #10458.
2217
				// Prevents focusing the wrong item when typeahead causes a scroll while the mouse
2218
				// is over an item in the menu
2219
				if ( this.previousFilter ) {
2220
					return;
2221
				}
2222
				var target = $( event.currentTarget );
2223
				// Remove ui-state-active class from siblings of the newly focused menu item
2224
				// to avoid a jump caused by adjacent elements both having a class with a border
2225
				target.siblings( ".ui-state-active" ).removeClass( "ui-state-active" );
2226
				this.focus( event, target );
2227
			},
2228
			mouseleave: "collapseAll",
2229
			"mouseleave .ui-menu": "collapseAll",
2230
			focus: function( event, keepActiveItem ) {
2231
				// If there's already an active item, keep it active
2232
				// If not, activate the first item
2233
				var item = this.active || this.element.find( this.options.items ).eq( 0 );
2234
2235
				if ( !keepActiveItem ) {
2236
					this.focus( event, item );
2237
				}
2238
			},
2239
			blur: function( event ) {
2240
				this._delay(function() {
2241
					if ( !$.contains( this.element[0], this.document[0].activeElement ) ) {
2242
						this.collapseAll( event );
2243
					}
2244
				});
2245
			},
2246
			keydown: "_keydown"
2247
		});
2248
2249
		this.refresh();
2250
2251
		// Clicks outside of a menu collapse any open menus
2252
		this._on( this.document, {
2253
			click: function( event ) {
2254
				if ( this._closeOnDocumentClick( event ) ) {
2255
					this.collapseAll( event );
2256
				}
2257
2258
				// Reset the mouseHandled flag
2259
				this.mouseHandled = false;
2260
			}
2261
		});
2262
	},
2263
2264
	_destroy: function() {
2265
		// Destroy (sub)menus
2266
		this.element
2267
			.removeAttr( "aria-activedescendant" )
2268
			.find( ".ui-menu" ).addBack()
2269
				.removeClass( "ui-menu ui-widget ui-widget-content ui-menu-icons ui-front" )
2270
				.removeAttr( "role" )
2271
				.removeAttr( "tabIndex" )
2272
				.removeAttr( "aria-labelledby" )
2273
				.removeAttr( "aria-expanded" )
2274
				.removeAttr( "aria-hidden" )
2275
				.removeAttr( "aria-disabled" )
2276
				.removeUniqueId()
2277
				.show();
2278
2279
		// Destroy menu items
2280
		this.element.find( ".ui-menu-item" )
2281
			.removeClass( "ui-menu-item" )
2282
			.removeAttr( "role" )
2283
			.removeAttr( "aria-disabled" )
2284
			.removeUniqueId()
2285
			.removeClass( "ui-state-hover" )
2286
			.removeAttr( "tabIndex" )
2287
			.removeAttr( "role" )
2288
			.removeAttr( "aria-haspopup" )
2289
			.children().each( function() {
2290
				var elem = $( this );
2291
				if ( elem.data( "ui-menu-submenu-carat" ) ) {
2292
					elem.remove();
2293
				}
2294
			});
2295
2296
		// Destroy menu dividers
2297
		this.element.find( ".ui-menu-divider" ).removeClass( "ui-menu-divider ui-widget-content" );
2298
	},
2299
2300
	_keydown: function( event ) {
2301
		var match, prev, character, skip,
2302
			preventDefault = true;
2303
2304
		switch ( event.keyCode ) {
2305
		case $.ui.keyCode.PAGE_UP:
2306
			this.previousPage( event );
2307
			break;
2308
		case $.ui.keyCode.PAGE_DOWN:
2309
			this.nextPage( event );
2310
			break;
2311
		case $.ui.keyCode.HOME:
2312
			this._move( "first", "first", event );
2313
			break;
2314
		case $.ui.keyCode.END:
2315
			this._move( "last", "last", event );
2316
			break;
2317
		case $.ui.keyCode.UP:
2318
			this.previous( event );
2319
			break;
2320
		case $.ui.keyCode.DOWN:
2321
			this.next( event );
2322
			break;
2323
		case $.ui.keyCode.LEFT:
2324
			this.collapse( event );
2325
			break;
2326
		case $.ui.keyCode.RIGHT:
2327
			if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
2328
				this.expand( event );
2329
			}
2330
			break;
2331
		case $.ui.keyCode.ENTER:
2332
		case $.ui.keyCode.SPACE:
2333
			this._activate( event );
2334
			break;
2335
		case $.ui.keyCode.ESCAPE:
2336
			this.collapse( event );
2337
			break;
2338
		default:
2339
			preventDefault = false;
2340
			prev = this.previousFilter || "";
2341
			character = String.fromCharCode( event.keyCode );
2342
			skip = false;
2343
2344
			clearTimeout( this.filterTimer );
2345
2346
			if ( character === prev ) {
2347
				skip = true;
2348
			} else {
2349
				character = prev + character;
2350
			}
2351
2352
			match = this._filterMenuItems( character );
2353
			match = skip && match.index( this.active.next() ) !== -1 ?
2354
				this.active.nextAll( ".ui-menu-item" ) :
2355
				match;
2356
2357
			// If no matches on the current filter, reset to the last character pressed
2358
			// to move down the menu to the first item that starts with that character
2359
			if ( !match.length ) {
2360
				character = String.fromCharCode( event.keyCode );
2361
				match = this._filterMenuItems( character );
2362
			}
2363
2364
			if ( match.length ) {
2365
				this.focus( event, match );
2366
				this.previousFilter = character;
2367
				this.filterTimer = this._delay(function() {
2368
					delete this.previousFilter;
2369
				}, 1000 );
2370
			} else {
2371
				delete this.previousFilter;
2372
			}
2373
		}
2374
2375
		if ( preventDefault ) {
2376
			event.preventDefault();
2377
		}
2378
	},
2379
2380
	_activate: function( event ) {
2381
		if ( !this.active.is( ".ui-state-disabled" ) ) {
2382
			if ( this.active.is( "[aria-haspopup='true']" ) ) {
2383
				this.expand( event );
2384
			} else {
2385
				this.select( event );
2386
			}
2387
		}
2388
	},
2389
2390
	refresh: function() {
2391
		var menus, items,
2392
			that = this,
2393
			icon = this.options.icons.submenu,
2394
			submenus = this.element.find( this.options.menus );
2395
2396
		this.element.toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length );
2397
2398
		// Initialize nested menus
2399
		submenus.filter( ":not(.ui-menu)" )
2400
			.addClass( "ui-menu ui-widget ui-widget-content ui-front" )
2401
			.hide()
2402
			.attr({
2403
				role: this.options.role,
2404
				"aria-hidden": "true",
2405
				"aria-expanded": "false"
2406
			})
2407
			.each(function() {
2408
				var menu = $( this ),
2409
					item = menu.parent(),
2410
					submenuCarat = $( "<span>" )
2411
						.addClass( "ui-menu-icon ui-icon " + icon )
2412
						.data( "ui-menu-submenu-carat", true );
2413
2414
				item
2415
					.attr( "aria-haspopup", "true" )
2416
					.prepend( submenuCarat );
2417
				menu.attr( "aria-labelledby", item.attr( "id" ) );
2418
			});
2419
2420
		menus = submenus.add( this.element );
2421
		items = menus.find( this.options.items );
2422
2423
		// Initialize menu-items containing spaces and/or dashes only as dividers
2424
		items.not( ".ui-menu-item" ).each(function() {
2425
			var item = $( this );
2426
			if ( that._isDivider( item ) ) {
2427
				item.addClass( "ui-widget-content ui-menu-divider" );
2428
			}
2429
		});
2430
2431
		// Don't refresh list items that are already adapted
2432
		items.not( ".ui-menu-item, .ui-menu-divider" )
2433
			.addClass( "ui-menu-item" )
2434
			.uniqueId()
2435
			.attr({
2436
				tabIndex: -1,
2437
				role: this._itemRole()
2438
			});
2439
2440
		// Add aria-disabled attribute to any disabled menu item
2441
		items.filter( ".ui-state-disabled" ).attr( "aria-disabled", "true" );
2442
2443
		// If the active item has been removed, blur the menu
2444
		if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
2445
			this.blur();
2446
		}
2447
	},
2448
2449
	_itemRole: function() {
2450
		return {
2451
			menu: "menuitem",
2452
			listbox: "option"
2453
		}[ this.options.role ];
2454
	},
2455
2456
	_setOption: function( key, value ) {
2457
		if ( key === "icons" ) {
2458
			this.element.find( ".ui-menu-icon" )
2459
				.removeClass( this.options.icons.submenu )
2460
				.addClass( value.submenu );
2461
		}
2462
		if ( key === "disabled" ) {
2463
			this.element
2464
				.toggleClass( "ui-state-disabled", !!value )
2465
				.attr( "aria-disabled", value );
2466
		}
2467
		this._super( key, value );
2468
	},
2469
2470
	focus: function( event, item ) {
2471
		var nested, focused;
2472
		this.blur( event, event && event.type === "focus" );
2473
2474
		this._scrollIntoView( item );
2475
2476
		this.active = item.first();
2477
		focused = this.active.addClass( "ui-state-focus" ).removeClass( "ui-state-active" );
2478
		// Only update aria-activedescendant if there's a role
2479
		// otherwise we assume focus is managed elsewhere
2480
		if ( this.options.role ) {
2481
			this.element.attr( "aria-activedescendant", focused.attr( "id" ) );
2482
		}
2483
2484
		// Highlight active parent menu item, if any
2485
		this.active
2486
			.parent()
2487
			.closest( ".ui-menu-item" )
2488
			.addClass( "ui-state-active" );
2489
2490
		if ( event && event.type === "keydown" ) {
2491
			this._close();
2492
		} else {
2493
			this.timer = this._delay(function() {
2494
				this._close();
2495
			}, this.delay );
2496
		}
2497
2498
		nested = item.children( ".ui-menu" );
2499
		if ( nested.length && event && ( /^mouse/.test( event.type ) ) ) {
2500
			this._startOpening(nested);
2501
		}
2502
		this.activeMenu = item.parent();
2503
2504
		this._trigger( "focus", event, { item: item } );
2505
	},
2506
2507
	_scrollIntoView: function( item ) {
2508
		var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight;
2509
		if ( this._hasScroll() ) {
2510
			borderTop = parseFloat( $.css( this.activeMenu[0], "borderTopWidth" ) ) || 0;
2511
			paddingTop = parseFloat( $.css( this.activeMenu[0], "paddingTop" ) ) || 0;
2512
			offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop;
2513
			scroll = this.activeMenu.scrollTop();
2514
			elementHeight = this.activeMenu.height();
2515
			itemHeight = item.outerHeight();
2516
2517
			if ( offset < 0 ) {
2518
				this.activeMenu.scrollTop( scroll + offset );
2519
			} else if ( offset + itemHeight > elementHeight ) {
2520
				this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight );
2521
			}
2522
		}
2523
	},
2524
2525
	blur: function( event, fromFocus ) {
2526
		if ( !fromFocus ) {
2527
			clearTimeout( this.timer );
2528
		}
2529
2530
		if ( !this.active ) {
2531
			return;
2532
		}
2533
2534
		this.active.removeClass( "ui-state-focus" );
2535
		this.active = null;
2536
2537
		this._trigger( "blur", event, { item: this.active } );
2538
	},
2539
2540
	_startOpening: function( submenu ) {
2541
		clearTimeout( this.timer );
2542
2543
		// Don't open if already open fixes a Firefox bug that caused a .5 pixel
2544
		// shift in the submenu position when mousing over the carat icon
2545
		if ( submenu.attr( "aria-hidden" ) !== "true" ) {
2546
			return;
2547
		}
2548
2549
		this.timer = this._delay(function() {
2550
			this._close();
2551
			this._open( submenu );
2552
		}, this.delay );
2553
	},
2554
2555
	_open: function( submenu ) {
2556
		var position = $.extend({
2557
			of: this.active
2558
		}, this.options.position );
2559
2560
		clearTimeout( this.timer );
2561
		this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) )
2562
			.hide()
2563
			.attr( "aria-hidden", "true" );
2564
2565
		submenu
2566
			.show()
2567
			.removeAttr( "aria-hidden" )
2568
			.attr( "aria-expanded", "true" )
2569
			.position( position );
2570
	},
2571
2572
	collapseAll: function( event, all ) {
2573
		clearTimeout( this.timer );
2574
		this.timer = this._delay(function() {
2575
			// If we were passed an event, look for the submenu that contains the event
2576
			var currentMenu = all ? this.element :
2577
				$( event && event.target ).closest( this.element.find( ".ui-menu" ) );
2578
2579
			// If we found no valid submenu ancestor, use the main menu to close all sub menus anyway
2580
			if ( !currentMenu.length ) {
2581
				currentMenu = this.element;
2582
			}
2583
2584
			this._close( currentMenu );
2585
2586
			this.blur( event );
2587
			this.activeMenu = currentMenu;
2588
		}, this.delay );
2589
	},
2590
2591
	// With no arguments, closes the currently active menu - if nothing is active
2592
	// it closes all menus.  If passed an argument, it will search for menus BELOW
2593
	_close: function( startMenu ) {
2594
		if ( !startMenu ) {
2595
			startMenu = this.active ? this.active.parent() : this.element;
2596
		}
2597
2598
		startMenu
2599
			.find( ".ui-menu" )
2600
				.hide()
2601
				.attr( "aria-hidden", "true" )
2602
				.attr( "aria-expanded", "false" )
2603
			.end()
2604
			.find( ".ui-state-active" ).not( ".ui-state-focus" )
2605
				.removeClass( "ui-state-active" );
2606
	},
2607
2608
	_closeOnDocumentClick: function( event ) {
2609
		return !$( event.target ).closest( ".ui-menu" ).length;
2610
	},
2611
2612
	_isDivider: function( item ) {
2613
2614
		// Match hyphen, em dash, en dash
2615
		return !/[^\-\u2014\u2013\s]/.test( item.text() );
2616
	},
2617
2618
	collapse: function( event ) {
2619
		var newItem = this.active &&
2620
			this.active.parent().closest( ".ui-menu-item", this.element );
2621
		if ( newItem && newItem.length ) {
2622
			this._close();
2623
			this.focus( event, newItem );
2624
		}
2625
	},
2626
2627
	expand: function( event ) {
2628
		var newItem = this.active &&
2629
			this.active
2630
				.children( ".ui-menu " )
2631
				.find( this.options.items )
2632
				.first();
2633
2634
		if ( newItem && newItem.length ) {
2635
			this._open( newItem.parent() );
2636
2637
			// Delay so Firefox will not hide activedescendant change in expanding submenu from AT
2638
			this._delay(function() {
2639
				this.focus( event, newItem );
2640
			});
2641
		}
2642
	},
2643
2644
	next: function( event ) {
2645
		this._move( "next", "first", event );
2646
	},
2647
2648
	previous: function( event ) {
2649
		this._move( "prev", "last", event );
2650
	},
2651
2652
	isFirstItem: function() {
2653
		return this.active && !this.active.prevAll( ".ui-menu-item" ).length;
2654
	},
2655
2656
	isLastItem: function() {
2657
		return this.active && !this.active.nextAll( ".ui-menu-item" ).length;
2658
	},
2659
2660
	_move: function( direction, filter, event ) {
2661
		var next;
2662
		if ( this.active ) {
2663
			if ( direction === "first" || direction === "last" ) {
2664
				next = this.active
2665
					[ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" )
2666
					.eq( -1 );
2667
			} else {
2668
				next = this.active
2669
					[ direction + "All" ]( ".ui-menu-item" )
2670
					.eq( 0 );
2671
			}
2672
		}
2673
		if ( !next || !next.length || !this.active ) {
2674
			next = this.activeMenu.find( this.options.items )[ filter ]();
2675
		}
2676
2677
		this.focus( event, next );
2678
	},
2679
2680
	nextPage: function( event ) {
2681
		var item, base, height;
2682
2683
		if ( !this.active ) {
2684
			this.next( event );
2685
			return;
2686
		}
2687
		if ( this.isLastItem() ) {
2688
			return;
2689
		}
2690
		if ( this._hasScroll() ) {
2691
			base = this.active.offset().top;
2692
			height = this.element.height();
2693
			this.active.nextAll( ".ui-menu-item" ).each(function() {
2694
				item = $( this );
2695
				return item.offset().top - base - height < 0;
2696
			});
2697
2698
			this.focus( event, item );
2699
		} else {
2700
			this.focus( event, this.activeMenu.find( this.options.items )
2701
				[ !this.active ? "first" : "last" ]() );
2702
		}
2703
	},
2704
2705
	previousPage: function( event ) {
2706
		var item, base, height;
2707
		if ( !this.active ) {
2708
			this.next( event );
2709
			return;
2710
		}
2711
		if ( this.isFirstItem() ) {
2712
			return;
2713
		}
2714
		if ( this._hasScroll() ) {
2715
			base = this.active.offset().top;
2716
			height = this.element.height();
2717
			this.active.prevAll( ".ui-menu-item" ).each(function() {
2718
				item = $( this );
2719
				return item.offset().top - base + height > 0;
2720
			});
2721
2722
			this.focus( event, item );
2723
		} else {
2724
			this.focus( event, this.activeMenu.find( this.options.items ).first() );
2725
		}
2726
	},
2727
2728
	_hasScroll: function() {
2729
		return this.element.outerHeight() < this.element.prop( "scrollHeight" );
2730
	},
2731
2732
	select: function( event ) {
2733
		// TODO: It should never be possible to not have an active item at this
2734
		// point, but the tests don't trigger mouseenter before click.
2735
		this.active = this.active || $( event.target ).closest( ".ui-menu-item" );
2736
		var ui = { item: this.active };
2737
		if ( !this.active.has( ".ui-menu" ).length ) {
2738
			this.collapseAll( event, true );
2739
		}
2740
		this._trigger( "select", event, ui );
2741
	},
2742
2743
	_filterMenuItems: function(character) {
2744
		var escapedCharacter = character.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ),
2745
			regex = new RegExp( "^" + escapedCharacter, "i" );
2746
2747
		return this.activeMenu
2748
			.find( this.options.items )
2749
2750
			// Only match on items, not dividers or other content (#10571)
2751
			.filter( ".ui-menu-item" )
2752
			.filter(function() {
2753
				return regex.test( $.trim( $( this ).text() ) );
2754
			});
2755
	}
2756
});
2757
2758
2759
/*!
2760
 * jQuery UI Autocomplete 1.11.4
2761
 * http://jqueryui.com
2762
 *
2763
 * Copyright jQuery Foundation and other contributors
2764
 * Released under the MIT license.
2765
 * http://jquery.org/license
2766
 *
2767
 * http://api.jqueryui.com/autocomplete/
2768
 */
2769
2770
2771
$.widget( "ui.autocomplete", {
2772
	version: "1.11.4",
2773
	defaultElement: "<input>",
2774
	options: {
2775
		appendTo: null,
2776
		autoFocus: false,
2777
		delay: 300,
2778
		minLength: 1,
2779
		position: {
2780
			my: "left top",
2781
			at: "left bottom",
2782
			collision: "none"
2783
		},
2784
		source: null,
2785
2786
		// callbacks
2787
		change: null,
2788
		close: null,
2789
		focus: null,
2790
		open: null,
2791
		response: null,
2792
		search: null,
2793
		select: null
2794
	},
2795
2796
	requestIndex: 0,
2797
	pending: 0,
2798
2799
	_create: function() {
2800
		// Some browsers only repeat keydown events, not keypress events,
2801
		// so we use the suppressKeyPress flag to determine if we've already
2802
		// handled the keydown event. #7269
2803
		// Unfortunately the code for & in keypress is the same as the up arrow,
2804
		// so we use the suppressKeyPressRepeat flag to avoid handling keypress
2805
		// events when we know the keydown event was used to modify the
2806
		// search term. #7799
2807
		var suppressKeyPress, suppressKeyPressRepeat, suppressInput,
2808
			nodeName = this.element[ 0 ].nodeName.toLowerCase(),
2809
			isTextarea = nodeName === "textarea",
2810
			isInput = nodeName === "input";
2811
2812
		this.isMultiLine =
2813
			// Textareas are always multi-line
2814
			isTextarea ? true :
2815
			// Inputs are always single-line, even if inside a contentEditable element
2816
			// IE also treats inputs as contentEditable
2817
			isInput ? false :
2818
			// All other element types are determined by whether or not they're contentEditable
2819
			this.element.prop( "isContentEditable" );
2820
2821
		this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ];
2822
		this.isNewMenu = true;
2823
2824
		this.element
2825
			.addClass( "ui-autocomplete-input" )
2826
			.attr( "autocomplete", "off" );
2827
2828
		this._on( this.element, {
2829
			keydown: function( event ) {
2830
				if ( this.element.prop( "readOnly" ) ) {
2831
					suppressKeyPress = true;
2832
					suppressInput = true;
2833
					suppressKeyPressRepeat = true;
2834
					return;
2835
				}
2836
2837
				suppressKeyPress = false;
2838
				suppressInput = false;
2839
				suppressKeyPressRepeat = false;
2840
				var keyCode = $.ui.keyCode;
2841
				switch ( event.keyCode ) {
2842
				case keyCode.PAGE_UP:
2843
					suppressKeyPress = true;
2844
					this._move( "previousPage", event );
2845
					break;
2846
				case keyCode.PAGE_DOWN:
2847
					suppressKeyPress = true;
2848
					this._move( "nextPage", event );
2849
					break;
2850
				case keyCode.UP:
2851
					suppressKeyPress = true;
2852
					this._keyEvent( "previous", event );
2853
					break;
2854
				case keyCode.DOWN:
2855
					suppressKeyPress = true;
2856
					this._keyEvent( "next", event );
2857
					break;
2858
				case keyCode.ENTER:
2859
					// when menu is open and has focus
2860
					if ( this.menu.active ) {
2861
						// #6055 - Opera still allows the keypress to occur
2862
						// which causes forms to submit
2863
						suppressKeyPress = true;
2864
						event.preventDefault();
2865
						this.menu.select( event );
2866
					}
2867
					break;
2868
				case keyCode.TAB:
2869
					if ( this.menu.active ) {
2870
						this.menu.select( event );
2871
					}
2872
					break;
2873
				case keyCode.ESCAPE:
2874
					if ( this.menu.element.is( ":visible" ) ) {
2875
						if ( !this.isMultiLine ) {
2876
							this._value( this.term );
2877
						}
2878
						this.close( event );
2879
						// Different browsers have different default behavior for escape
2880
						// Single press can mean undo or clear
2881
						// Double press in IE means clear the whole form
2882
						event.preventDefault();
2883
					}
2884
					break;
2885
				default:
2886
					suppressKeyPressRepeat = true;
2887
					// search timeout should be triggered before the input value is changed
2888
					this._searchTimeout( event );
2889
					break;
2890
				}
2891
			},
2892
			keypress: function( event ) {
2893
				if ( suppressKeyPress ) {
2894
					suppressKeyPress = false;
2895
					if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
2896
						event.preventDefault();
2897
					}
2898
					return;
2899
				}
2900
				if ( suppressKeyPressRepeat ) {
2901
					return;
2902
				}
2903
2904
				// replicate some key handlers to allow them to repeat in Firefox and Opera
2905
				var keyCode = $.ui.keyCode;
2906
				switch ( event.keyCode ) {
2907
				case keyCode.PAGE_UP:
2908
					this._move( "previousPage", event );
2909
					break;
2910
				case keyCode.PAGE_DOWN:
2911
					this._move( "nextPage", event );
2912
					break;
2913
				case keyCode.UP:
2914
					this._keyEvent( "previous", event );
2915
					break;
2916
				case keyCode.DOWN:
2917
					this._keyEvent( "next", event );
2918
					break;
2919
				}
2920
			},
2921
			input: function( event ) {
2922
				if ( suppressInput ) {
2923
					suppressInput = false;
2924
					event.preventDefault();
2925
					return;
2926
				}
2927
				this._searchTimeout( event );
2928
			},
2929
			focus: function() {
2930
				this.selectedItem = null;
2931
				this.previous = this._value();
2932
			},
2933
			blur: function( event ) {
2934
				if ( this.cancelBlur ) {
2935
					delete this.cancelBlur;
2936
					return;
2937
				}
2938
2939
				clearTimeout( this.searching );
2940
				this.close( event );
2941
				this._change( event );
2942
			}
2943
		});
2944
2945
		this._initSource();
2946
		this.menu = $( "<ul>" )
2947
			.addClass( "ui-autocomplete ui-front" )
2948
			.appendTo( this._appendTo() )
2949
			.menu({
2950
				// disable ARIA support, the live region takes care of that
2951
				role: null
2952
			})
2953
			.hide()
2954
			.menu( "instance" );
2955
2956
		this._on( this.menu.element, {
2957
			mousedown: function( event ) {
2958
				// prevent moving focus out of the text field
2959
				event.preventDefault();
2960
2961
				// IE doesn't prevent moving focus even with event.preventDefault()
2962
				// so we set a flag to know when we should ignore the blur event
2963
				this.cancelBlur = true;
2964
				this._delay(function() {
2965
					delete this.cancelBlur;
2966
				});
2967
2968
				// clicking on the scrollbar causes focus to shift to the body
2969
				// but we can't detect a mouseup or a click immediately afterward
2970
				// so we have to track the next mousedown and close the menu if
2971
				// the user clicks somewhere outside of the autocomplete
2972
				var menuElement = this.menu.element[ 0 ];
2973
				if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
2974
					this._delay(function() {
2975
						var that = this;
2976
						this.document.one( "mousedown", function( event ) {
2977
							if ( event.target !== that.element[ 0 ] &&
2978
									event.target !== menuElement &&
2979
									!$.contains( menuElement, event.target ) ) {
2980
								that.close();
2981
							}
2982
						});
2983
					});
2984
				}
2985
			},
2986
			menufocus: function( event, ui ) {
2987
				var label, item;
2988
				// support: Firefox
2989
				// Prevent accidental activation of menu items in Firefox (#7024 #9118)
2990
				if ( this.isNewMenu ) {
2991
					this.isNewMenu = false;
2992
					if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) {
2993
						this.menu.blur();
2994
2995
						this.document.one( "mousemove", function() {
2996
							$( event.target ).trigger( event.originalEvent );
2997
						});
2998
2999
						return;
3000
					}
3001
				}
3002
3003
				item = ui.item.data( "ui-autocomplete-item" );
3004
				if ( false !== this._trigger( "focus", event, { item: item } ) ) {
3005
					// use value to match what will end up in the input, if it was a key event
3006
					if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) {
3007
						this._value( item.value );
3008
					}
3009
				}
3010
3011
				// Announce the value in the liveRegion
3012
				label = ui.item.attr( "aria-label" ) || item.value;
3013
				if ( label && $.trim( label ).length ) {
3014
					this.liveRegion.children().hide();
3015
					$( "<div>" ).text( label ).appendTo( this.liveRegion );
3016
				}
3017
			},
3018
			menuselect: function( event, ui ) {
3019
				var item = ui.item.data( "ui-autocomplete-item" ),
3020
					previous = this.previous;
3021
3022
				// only trigger when focus was lost (click on menu)
3023
				if ( this.element[ 0 ] !== this.document[ 0 ].activeElement ) {
3024
					this.element.focus();
3025
					this.previous = previous;
3026
					// #6109 - IE triggers two focus events and the second
3027
					// is asynchronous, so we need to reset the previous
3028
					// term synchronously and asynchronously :-(
3029
					this._delay(function() {
3030
						this.previous = previous;
3031
						this.selectedItem = item;
3032
					});
3033
				}
3034
3035
				if ( false !== this._trigger( "select", event, { item: item } ) ) {
3036
					this._value( item.value );
3037
				}
3038
				// reset the term after the select event
3039
				// this allows custom select handling to work properly
3040
				this.term = this._value();
3041
3042
				this.close( event );
3043
				this.selectedItem = item;
3044
			}
3045
		});
3046
3047
		this.liveRegion = $( "<span>", {
3048
				role: "status",
3049
				"aria-live": "assertive",
3050
				"aria-relevant": "additions"
3051
			})
3052
			.addClass( "ui-helper-hidden-accessible" )
3053
			.appendTo( this.document[ 0 ].body );
3054
3055
		// turning off autocomplete prevents the browser from remembering the
3056
		// value when navigating through history, so we re-enable autocomplete
3057
		// if the page is unloaded before the widget is destroyed. #7790
3058
		this._on( this.window, {
3059
			beforeunload: function() {
3060
				this.element.removeAttr( "autocomplete" );
3061
			}
3062
		});
3063
	},
3064
3065
	_destroy: function() {
3066
		clearTimeout( this.searching );
3067
		this.element
3068
			.removeClass( "ui-autocomplete-input" )
3069
			.removeAttr( "autocomplete" );
3070
		this.menu.element.remove();
3071
		this.liveRegion.remove();
3072
	},
3073
3074
	_setOption: function( key, value ) {
3075
		this._super( key, value );
3076
		if ( key === "source" ) {
3077
			this._initSource();
3078
		}
3079
		if ( key === "appendTo" ) {
3080
			this.menu.element.appendTo( this._appendTo() );
3081
		}
3082
		if ( key === "disabled" && value && this.xhr ) {
3083
			this.xhr.abort();
3084
		}
3085
	},
3086
3087
	_appendTo: function() {
3088
		var element = this.options.appendTo;
3089
3090
		if ( element ) {
3091
			element = element.jquery || element.nodeType ?
3092
				$( element ) :
3093
				this.document.find( element ).eq( 0 );
3094
		}
3095
3096
		if ( !element || !element[ 0 ] ) {
3097
			element = this.element.closest( ".ui-front" );
3098
		}
3099
3100
		if ( !element.length ) {
3101
			element = this.document[ 0 ].body;
3102
		}
3103
3104
		return element;
3105
	},
3106
3107
	_initSource: function() {
3108
		var array, url,
3109
			that = this;
3110
		if ( $.isArray( this.options.source ) ) {
3111
			array = this.options.source;
3112
			this.source = function( request, response ) {
3113
				response( $.ui.autocomplete.filter( array, request.term ) );
3114
			};
3115
		} else if ( typeof this.options.source === "string" ) {
3116
			url = this.options.source;
3117
			this.source = function( request, response ) {
3118
				if ( that.xhr ) {
3119
					that.xhr.abort();
3120
				}
3121
				that.xhr = $.ajax({
3122
					url: url,
3123
					data: request,
3124
					dataType: "json",
3125
					success: function( data ) {
3126
						response( data );
3127
					},
3128
					error: function() {
3129
						response([]);
3130
					}
3131
				});
3132
			};
3133
		} else {
3134
			this.source = this.options.source;
3135
		}
3136
	},
3137
3138
	_searchTimeout: function( event ) {
3139
		clearTimeout( this.searching );
3140
		this.searching = this._delay(function() {
3141
3142
			// Search if the value has changed, or if the user retypes the same value (see #7434)
3143
			var equalValues = this.term === this._value(),
3144
				menuVisible = this.menu.element.is( ":visible" ),
3145
				modifierKey = event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;
3146
3147
			if ( !equalValues || ( equalValues && !menuVisible && !modifierKey ) ) {
3148
				this.selectedItem = null;
3149
				this.search( null, event );
3150
			}
3151
		}, this.options.delay );
3152
	},
3153
3154
	search: function( value, event ) {
3155
		value = value != null ? value : this._value();
3156
3157
		// always save the actual value, not the one passed as an argument
3158
		this.term = this._value();
3159
3160
		if ( value.length < this.options.minLength ) {
3161
			return this.close( event );
3162
		}
3163
3164
		if ( this._trigger( "search", event ) === false ) {
3165
			return;
3166
		}
3167
3168
		return this._search( value );
3169
	},
3170
3171
	_search: function( value ) {
3172
		this.pending++;
3173
		this.element.addClass( "ui-autocomplete-loading" );
3174
		this.cancelSearch = false;
3175
3176
		this.source( { term: value }, this._response() );
3177
	},
3178
3179
	_response: function() {
3180
		var index = ++this.requestIndex;
3181
3182
		return $.proxy(function( content ) {
3183
			if ( index === this.requestIndex ) {
3184
				this.__response( content );
3185
			}
3186
3187
			this.pending--;
3188
			if ( !this.pending ) {
3189
				this.element.removeClass( "ui-autocomplete-loading" );
3190
			}
3191
		}, this );
3192
	},
3193
3194
	__response: function( content ) {
3195
		if ( content ) {
3196
			content = this._normalize( content );
3197
		}
3198
		this._trigger( "response", null, { content: content } );
3199
		if ( !this.options.disabled && content && content.length && !this.cancelSearch ) {
3200
			this._suggest( content );
3201
			this._trigger( "open" );
3202
		} else {
3203
			// use ._close() instead of .close() so we don't cancel future searches
3204
			this._close();
3205
		}
3206
	},
3207
3208
	close: function( event ) {
3209
		this.cancelSearch = true;
3210
		this._close( event );
3211
	},
3212
3213
	_close: function( event ) {
3214
		if ( this.menu.element.is( ":visible" ) ) {
3215
			this.menu.element.hide();
3216
			this.menu.blur();
3217
			this.isNewMenu = true;
3218
			this._trigger( "close", event );
3219
		}
3220
	},
3221
3222
	_change: function( event ) {
3223
		if ( this.previous !== this._value() ) {
3224
			this._trigger( "change", event, { item: this.selectedItem } );
3225
		}
3226
	},
3227
3228
	_normalize: function( items ) {
3229
		// assume all items have the right format when the first item is complete
3230
		if ( items.length && items[ 0 ].label && items[ 0 ].value ) {
3231
			return items;
3232
		}
3233
		return $.map( items, function( item ) {
3234
			if ( typeof item === "string" ) {
3235
				return {
3236
					label: item,
3237
					value: item
3238
				};
3239
			}
3240
			return $.extend( {}, item, {
3241
				label: item.label || item.value,
3242
				value: item.value || item.label
3243
			});
3244
		});
3245
	},
3246
3247
	_suggest: function( items ) {
3248
		var ul = this.menu.element.empty();
3249
		this._renderMenu( ul, items );
3250
		this.isNewMenu = true;
3251
		this.menu.refresh();
3252
3253
		// size and position menu
3254
		ul.show();
3255
		this._resizeMenu();
3256
		ul.position( $.extend({
3257
			of: this.element
3258
		}, this.options.position ) );
3259
3260
		if ( this.options.autoFocus ) {
3261
			this.menu.next();
3262
		}
3263
	},
3264
3265
	_resizeMenu: function() {
3266
		var ul = this.menu.element;
3267
		ul.outerWidth( Math.max(
3268
			// Firefox wraps long text (possibly a rounding bug)
3269
			// so we add 1px to avoid the wrapping (#7513)
3270
			ul.width( "" ).outerWidth() + 1,
3271
			this.element.outerWidth()
3272
		) );
3273
	},
3274
3275
	_renderMenu: function( ul, items ) {
3276
		var that = this;
3277
		$.each( items, function( index, item ) {
3278
			that._renderItemData( ul, item );
3279
		});
3280
	},
3281
3282
	_renderItemData: function( ul, item ) {
3283
		return this._renderItem( ul, item ).data( "ui-autocomplete-item", item );
3284
	},
3285
3286
	_renderItem: function( ul, item ) {
3287
		return $( "<li>" ).text( item.label ).appendTo( ul );
3288
	},
3289
3290
	_move: function( direction, event ) {
3291
		if ( !this.menu.element.is( ":visible" ) ) {
3292
			this.search( null, event );
3293
			return;
3294
		}
3295
		if ( this.menu.isFirstItem() && /^previous/.test( direction ) ||
3296
				this.menu.isLastItem() && /^next/.test( direction ) ) {
3297
3298
			if ( !this.isMultiLine ) {
3299
				this._value( this.term );
3300
			}
3301
3302
			this.menu.blur();
3303
			return;
3304
		}
3305
		this.menu[ direction ]( event );
3306
	},
3307
3308
	widget: function() {
3309
		return this.menu.element;
3310
	},
3311
3312
	_value: function() {
3313
		return this.valueMethod.apply( this.element, arguments );
3314
	},
3315
3316
	_keyEvent: function( keyEvent, event ) {
3317
		if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
3318
			this._move( keyEvent, event );
3319
3320
			// prevents moving cursor to beginning/end of the text field in some browsers
3321
			event.preventDefault();
3322
		}
3323
	}
3324
});
3325
3326
$.extend( $.ui.autocomplete, {
3327
	escapeRegex: function( value ) {
3328
		return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" );
3329
	},
3330
	filter: function( array, term ) {
3331
		var matcher = new RegExp( $.ui.autocomplete.escapeRegex( term ), "i" );
3332
		return $.grep( array, function( value ) {
3333
			return matcher.test( value.label || value.value || value );
3334
		});
3335
	}
3336
});
3337
3338
// live region extension, adding a `messages` option
3339
// NOTE: This is an experimental API. We are still investigating
3340
// a full solution for string manipulation and internationalization.
3341
$.widget( "ui.autocomplete", $.ui.autocomplete, {
3342
	options: {
3343
		messages: {
3344
			noResults: "No search results.",
3345
			results: function( amount ) {
3346
				return amount + ( amount > 1 ? " results are" : " result is" ) +
3347
					" available, use up and down arrow keys to navigate.";
3348
			}
3349
		}
3350
	},
3351
3352
	__response: function( content ) {
3353
		var message;
3354
		this._superApply( arguments );
3355
		if ( this.options.disabled || this.cancelSearch ) {
3356
			return;
3357
		}
3358
		if ( content && content.length ) {
3359
			message = this.options.messages.results( content.length );
3360
		} else {
3361
			message = this.options.messages.noResults;
3362
		}
3363
		this.liveRegion.children().hide();
3364
		$( "<div>" ).text( message ).appendTo( this.liveRegion );
3365
	}
3366
});
3367
3368
var autocomplete = $.ui.autocomplete;
3369
3370
3371
/*!
3372
 * jQuery UI Button 1.11.4
3373
 * http://jqueryui.com
3374
 *
3375
 * Copyright jQuery Foundation and other contributors
3376
 * Released under the MIT license.
3377
 * http://jquery.org/license
3378
 *
3379
 * http://api.jqueryui.com/button/
3380
 */
3381
3382
3383
var lastActive,
3384
	baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
3385
	typeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",
3386
	formResetHandler = function() {
3387
		var form = $( this );
3388
		setTimeout(function() {
3389
			form.find( ":ui-button" ).button( "refresh" );
3390
		}, 1 );
3391
	},
3392
	radioGroup = function( radio ) {
3393
		var name = radio.name,
3394
			form = radio.form,
3395
			radios = $( [] );
3396
		if ( name ) {
3397
			name = name.replace( /'/g, "\\'" );
3398
			if ( form ) {
3399
				radios = $( form ).find( "[name='" + name + "'][type=radio]" );
3400
			} else {
3401
				radios = $( "[name='" + name + "'][type=radio]", radio.ownerDocument )
3402
					.filter(function() {
3403
						return !this.form;
3404
					});
3405
			}
3406
		}
3407
		return radios;
3408
	};
3409
3410
$.widget( "ui.button", {
3411
	version: "1.11.4",
3412
	defaultElement: "<button>",
3413
	options: {
3414
		disabled: null,
3415
		text: true,
3416
		label: null,
3417
		icons: {
3418
			primary: null,
3419
			secondary: null
3420
		}
3421
	},
3422
	_create: function() {
3423
		this.element.closest( "form" )
3424
			.unbind( "reset" + this.eventNamespace )
3425
			.bind( "reset" + this.eventNamespace, formResetHandler );
3426
3427
		if ( typeof this.options.disabled !== "boolean" ) {
3428
			this.options.disabled = !!this.element.prop( "disabled" );
3429
		} else {
3430
			this.element.prop( "disabled", this.options.disabled );
3431
		}
3432
3433
		this._determineButtonType();
3434
		this.hasTitle = !!this.buttonElement.attr( "title" );
3435
3436
		var that = this,
3437
			options = this.options,
3438
			toggleButton = this.type === "checkbox" || this.type === "radio",
3439
			activeClass = !toggleButton ? "ui-state-active" : "";
3440
3441
		if ( options.label === null ) {
3442
			options.label = (this.type === "input" ? this.buttonElement.val() : this.buttonElement.html());
3443
		}
3444
3445
		this._hoverable( this.buttonElement );
3446
3447
		this.buttonElement
3448
			.addClass( baseClasses )
3449
			.attr( "role", "button" )
3450
			.bind( "mouseenter" + this.eventNamespace, function() {
3451
				if ( options.disabled ) {
3452
					return;
3453
				}
3454
				if ( this === lastActive ) {
3455
					$( this ).addClass( "ui-state-active" );
3456
				}
3457
			})
3458
			.bind( "mouseleave" + this.eventNamespace, function() {
3459
				if ( options.disabled ) {
3460
					return;
3461
				}
3462
				$( this ).removeClass( activeClass );
3463
			})
3464
			.bind( "click" + this.eventNamespace, function( event ) {
3465
				if ( options.disabled ) {
3466
					event.preventDefault();
3467
					event.stopImmediatePropagation();
3468
				}
3469
			});
3470
3471
		// Can't use _focusable() because the element that receives focus
3472
		// and the element that gets the ui-state-focus class are different
3473
		this._on({
3474
			focus: function() {
3475
				this.buttonElement.addClass( "ui-state-focus" );
3476
			},
3477
			blur: function() {
3478
				this.buttonElement.removeClass( "ui-state-focus" );
3479
			}
3480
		});
3481
3482
		if ( toggleButton ) {
3483
			this.element.bind( "change" + this.eventNamespace, function() {
3484
				that.refresh();
3485
			});
3486
		}
3487
3488
		if ( this.type === "checkbox" ) {
3489
			this.buttonElement.bind( "click" + this.eventNamespace, function() {
3490
				if ( options.disabled ) {
3491
					return false;
3492
				}
3493
			});
3494
		} else if ( this.type === "radio" ) {
3495
			this.buttonElement.bind( "click" + this.eventNamespace, function() {
3496
				if ( options.disabled ) {
3497
					return false;
3498
				}
3499
				$( this ).addClass( "ui-state-active" );
3500
				that.buttonElement.attr( "aria-pressed", "true" );
3501
3502
				var radio = that.element[ 0 ];
3503
				radioGroup( radio )
3504
					.not( radio )
3505
					.map(function() {
3506
						return $( this ).button( "widget" )[ 0 ];
3507
					})
3508
					.removeClass( "ui-state-active" )
3509
					.attr( "aria-pressed", "false" );
3510
			});
3511
		} else {
3512
			this.buttonElement
3513
				.bind( "mousedown" + this.eventNamespace, function() {
3514
					if ( options.disabled ) {
3515
						return false;
3516
					}
3517
					$( this ).addClass( "ui-state-active" );
3518
					lastActive = this;
3519
					that.document.one( "mouseup", function() {
3520
						lastActive = null;
3521
					});
3522
				})
3523
				.bind( "mouseup" + this.eventNamespace, function() {
3524
					if ( options.disabled ) {
3525
						return false;
3526
					}
3527
					$( this ).removeClass( "ui-state-active" );
3528
				})
3529
				.bind( "keydown" + this.eventNamespace, function(event) {
3530
					if ( options.disabled ) {
3531
						return false;
3532
					}
3533
					if ( event.keyCode === $.ui.keyCode.SPACE || event.keyCode === $.ui.keyCode.ENTER ) {
3534
						$( this ).addClass( "ui-state-active" );
3535
					}
3536
				})
3537
				// see #8559, we bind to blur here in case the button element loses
3538
				// focus between keydown and keyup, it would be left in an "active" state
3539
				.bind( "keyup" + this.eventNamespace + " blur" + this.eventNamespace, function() {
3540
					$( this ).removeClass( "ui-state-active" );
3541
				});
3542
3543
			if ( this.buttonElement.is("a") ) {
3544
				this.buttonElement.keyup(function(event) {
3545
					if ( event.keyCode === $.ui.keyCode.SPACE ) {
3546
						// TODO pass through original event correctly (just as 2nd argument doesn't work)
3547
						$( this ).click();
3548
					}
3549
				});
3550
			}
3551
		}
3552
3553
		this._setOption( "disabled", options.disabled );
3554
		this._resetButton();
3555
	},
3556
3557
	_determineButtonType: function() {
3558
		var ancestor, labelSelector, checked;
3559
3560
		if ( this.element.is("[type=checkbox]") ) {
3561
			this.type = "checkbox";
3562
		} else if ( this.element.is("[type=radio]") ) {
3563
			this.type = "radio";
3564
		} else if ( this.element.is("input") ) {
3565
			this.type = "input";
3566
		} else {
3567
			this.type = "button";
3568
		}
3569
3570
		if ( this.type === "checkbox" || this.type === "radio" ) {
3571
			// we don't search against the document in case the element
3572
			// is disconnected from the DOM
3573
			ancestor = this.element.parents().last();
3574
			labelSelector = "label[for='" + this.element.attr("id") + "']";
3575
			this.buttonElement = ancestor.find( labelSelector );
3576
			if ( !this.buttonElement.length ) {
3577
				ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings();
3578
				this.buttonElement = ancestor.filter( labelSelector );
3579
				if ( !this.buttonElement.length ) {
3580
					this.buttonElement = ancestor.find( labelSelector );
3581
				}
3582
			}
3583
			this.element.addClass( "ui-helper-hidden-accessible" );
3584
3585
			checked = this.element.is( ":checked" );
3586
			if ( checked ) {
3587
				this.buttonElement.addClass( "ui-state-active" );
3588
			}
3589
			this.buttonElement.prop( "aria-pressed", checked );
3590
		} else {
3591
			this.buttonElement = this.element;
3592
		}
3593
	},
3594
3595
	widget: function() {
3596
		return this.buttonElement;
3597
	},
3598
3599
	_destroy: function() {
3600
		this.element
3601
			.removeClass( "ui-helper-hidden-accessible" );
3602
		this.buttonElement
3603
			.removeClass( baseClasses + " ui-state-active " + typeClasses )
3604
			.removeAttr( "role" )
3605
			.removeAttr( "aria-pressed" )
3606
			.html( this.buttonElement.find(".ui-button-text").html() );
3607
3608
		if ( !this.hasTitle ) {
3609
			this.buttonElement.removeAttr( "title" );
3610
		}
3611
	},
3612
3613
	_setOption: function( key, value ) {
3614
		this._super( key, value );
3615
		if ( key === "disabled" ) {
3616
			this.widget().toggleClass( "ui-state-disabled", !!value );
3617
			this.element.prop( "disabled", !!value );
3618
			if ( value ) {
3619
				if ( this.type === "checkbox" || this.type === "radio" ) {
3620
					this.buttonElement.removeClass( "ui-state-focus" );
3621
				} else {
3622
					this.buttonElement.removeClass( "ui-state-focus ui-state-active" );
3623
				}
3624
			}
3625
			return;
3626
		}
3627
		this._resetButton();
3628
	},
3629
3630
	refresh: function() {
3631
		//See #8237 & #8828
3632
		var isDisabled = this.element.is( "input, button" ) ? this.element.is( ":disabled" ) : this.element.hasClass( "ui-button-disabled" );
3633
3634
		if ( isDisabled !== this.options.disabled ) {
3635
			this._setOption( "disabled", isDisabled );
3636
		}
3637
		if ( this.type === "radio" ) {
3638
			radioGroup( this.element[0] ).each(function() {
3639
				if ( $( this ).is( ":checked" ) ) {
3640
					$( this ).button( "widget" )
3641
						.addClass( "ui-state-active" )
3642
						.attr( "aria-pressed", "true" );
3643
				} else {
3644
					$( this ).button( "widget" )
3645
						.removeClass( "ui-state-active" )
3646
						.attr( "aria-pressed", "false" );
3647
				}
3648
			});
3649
		} else if ( this.type === "checkbox" ) {
3650
			if ( this.element.is( ":checked" ) ) {
3651
				this.buttonElement
3652
					.addClass( "ui-state-active" )
3653
					.attr( "aria-pressed", "true" );
3654
			} else {
3655
				this.buttonElement
3656
					.removeClass( "ui-state-active" )
3657
					.attr( "aria-pressed", "false" );
3658
			}
3659
		}
3660
	},
3661
3662
	_resetButton: function() {
3663
		if ( this.type === "input" ) {
3664
			if ( this.options.label ) {
3665
				this.element.val( this.options.label );
3666
			}
3667
			return;
3668
		}
3669
		var buttonElement = this.buttonElement.removeClass( typeClasses ),
3670
			buttonText = $( "<span></span>", this.document[0] )
3671
				.addClass( "ui-button-text" )
3672
				.html( this.options.label )
3673
				.appendTo( buttonElement.empty() )
3674
				.text(),
3675
			icons = this.options.icons,
3676
			multipleIcons = icons.primary && icons.secondary,
3677
			buttonClasses = [];
3678
3679
		if ( icons.primary || icons.secondary ) {
3680
			if ( this.options.text ) {
3681
				buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
3682
			}
3683
3684
			if ( icons.primary ) {
3685
				buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
3686
			}
3687
3688
			if ( icons.secondary ) {
3689
				buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
3690
			}
3691
3692
			if ( !this.options.text ) {
3693
				buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" );
3694
3695
				if ( !this.hasTitle ) {
3696
					buttonElement.attr( "title", $.trim( buttonText ) );
3697
				}
3698
			}
3699
		} else {
3700
			buttonClasses.push( "ui-button-text-only" );
3701
		}
3702
		buttonElement.addClass( buttonClasses.join( " " ) );
3703
	}
3704
});
3705
3706
$.widget( "ui.buttonset", {
3707
	version: "1.11.4",
3708
	options: {
3709
		items: "button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(ui-button)"
3710
	},
3711
3712
	_create: function() {
3713
		this.element.addClass( "ui-buttonset" );
3714
	},
3715
3716
	_init: function() {
3717
		this.refresh();
3718
	},
3719
3720
	_setOption: function( key, value ) {
3721
		if ( key === "disabled" ) {
3722
			this.buttons.button( "option", key, value );
3723
		}
3724
3725
		this._super( key, value );
3726
	},
3727
3728
	refresh: function() {
3729
		var rtl = this.element.css( "direction" ) === "rtl",
3730
			allButtons = this.element.find( this.options.items ),
3731
			existingButtons = allButtons.filter( ":ui-button" );
3732
3733
		// Initialize new buttons
3734
		allButtons.not( ":ui-button" ).button();
3735
3736
		// Refresh existing buttons
3737
		existingButtons.button( "refresh" );
3738
3739
		this.buttons = allButtons
3740
			.map(function() {
3741
				return $( this ).button( "widget" )[ 0 ];
3742
			})
3743
				.removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
3744
				.filter( ":first" )
3745
					.addClass( rtl ? "ui-corner-right" : "ui-corner-left" )
3746
				.end()
3747
				.filter( ":last" )
3748
					.addClass( rtl ? "ui-corner-left" : "ui-corner-right" )
3749
				.end()
3750
			.end();
3751
	},
3752
3753
	_destroy: function() {
3754
		this.element.removeClass( "ui-buttonset" );
3755
		this.buttons
3756
			.map(function() {
3757
				return $( this ).button( "widget" )[ 0 ];
3758
			})
3759
				.removeClass( "ui-corner-left ui-corner-right" )
3760
			.end()
3761
			.button( "destroy" );
3762
	}
3763
});
3764
3765
var button = $.ui.button;
3766
3767
3768
/*!
3769
 * jQuery UI Datepicker 1.11.4
3770
 * http://jqueryui.com
3771
 *
3772
 * Copyright jQuery Foundation and other contributors
3773
 * Released under the MIT license.
3774
 * http://jquery.org/license
3775
 *
3776
 * http://api.jqueryui.com/datepicker/
3777
 */
3778
3779
3780
$.extend($.ui, { datepicker: { version: "1.11.4" } });
3781
3782
var datepicker_instActive;
3783
3784
function datepicker_getZindex( elem ) {
3785
	var position, value;
3786
	while ( elem.length && elem[ 0 ] !== document ) {
3787
		// Ignore z-index if position is set to a value where z-index is ignored by the browser
3788
		// This makes behavior of this function consistent across browsers
3789
		// WebKit always returns auto if the element is positioned
3790
		position = elem.css( "position" );
3791
		if ( position === "absolute" || position === "relative" || position === "fixed" ) {
3792
			// IE returns 0 when zIndex is not specified
3793
			// other browsers return a string
3794
			// we ignore the case of nested elements with an explicit value of 0
3795
			// <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
3796
			value = parseInt( elem.css( "zIndex" ), 10 );
3797
			if ( !isNaN( value ) && value !== 0 ) {
3798
				return value;
3799
			}
3800
		}
3801
		elem = elem.parent();
3802
	}
3803
3804
	return 0;
3805
}
3806
/* Date picker manager.
3807
   Use the singleton instance of this class, $.datepicker, to interact with the date picker.
3808
   Settings for (groups of) date pickers are maintained in an instance object,
3809
   allowing multiple different settings on the same page. */
3810
3811
function Datepicker() {
3812
	this._curInst = null; // The current instance in use
3813
	this._keyEvent = false; // If the last event was a key event
3814
	this._disabledInputs = []; // List of date picker inputs that have been disabled
3815
	this._datepickerShowing = false; // True if the popup picker is showing , false if not
3816
	this._inDialog = false; // True if showing within a "dialog", false if not
3817
	this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division
3818
	this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class
3819
	this._appendClass = "ui-datepicker-append"; // The name of the append marker class
3820
	this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class
3821
	this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class
3822
	this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class
3823
	this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class
3824
	this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class
3825
	this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class
3826
	this.regional = []; // Available regional settings, indexed by language code
3827
	this.regional[""] = { // Default regional settings
3828
		closeText: "Done", // Display text for close link
3829
		prevText: "Prev", // Display text for previous month link
3830
		nextText: "Next", // Display text for next month link
3831
		currentText: "Today", // Display text for current month link
3832
		monthNames: ["January","February","March","April","May","June",
3833
			"July","August","September","October","November","December"], // Names of months for drop-down and formatting
3834
		monthNamesShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], // For formatting
3835
		dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], // For formatting
3836
		dayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], // For formatting
3837
		dayNamesMin: ["Su","Mo","Tu","We","Th","Fr","Sa"], // Column headings for days starting at Sunday
3838
		weekHeader: "Wk", // Column header for week of the year
3839
		dateFormat: "mm/dd/yy", // See format options on parseDate
3840
		firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
3841
		isRTL: false, // True if right-to-left language, false if left-to-right
3842
		showMonthAfterYear: false, // True if the year select precedes month, false for month then year
3843
		yearSuffix: "" // Additional text to append to the year in the month headers
3844
	};
3845
	this._defaults = { // Global defaults for all the date picker instances
3846
		showOn: "focus", // "focus" for popup on focus,
3847
			// "button" for trigger button, or "both" for either
3848
		showAnim: "fadeIn", // Name of jQuery animation for popup
3849
		showOptions: {}, // Options for enhanced animations
3850
		defaultDate: null, // Used when field is blank: actual date,
3851
			// +/-number for offset from today, null for today
3852
		appendText: "", // Display text following the input box, e.g. showing the format
3853
		buttonText: "...", // Text for trigger button
3854
		buttonImage: "", // URL for trigger button image
3855
		buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
3856
		hideIfNoPrevNext: false, // True to hide next/previous month links
3857
			// if not applicable, false to just disable them
3858
		navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
3859
		gotoCurrent: false, // True if today link goes back to current selection instead
3860
		changeMonth: false, // True if month can be selected directly, false if only prev/next
3861
		changeYear: false, // True if year can be selected directly, false if only prev/next
3862
		yearRange: "c-10:c+10", // Range of years to display in drop-down,
3863
			// either relative to today's year (-nn:+nn), relative to currently displayed year
3864
			// (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
3865
		showOtherMonths: false, // True to show dates in other months, false to leave blank
3866
		selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
3867
		showWeek: false, // True to show week of the year, false to not show it
3868
		calculateWeek: this.iso8601Week, // How to calculate the week of the year,
3869
			// takes a Date and returns the number of the week for it
3870
		shortYearCutoff: "+10", // Short year values < this are in the current century,
3871
			// > this are in the previous century,
3872
			// string value starting with "+" for current year + value
3873
		minDate: null, // The earliest selectable date, or null for no limit
3874
		maxDate: null, // The latest selectable date, or null for no limit
3875
		duration: "fast", // Duration of display/closure
3876
		beforeShowDay: null, // Function that takes a date and returns an array with
3877
			// [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "",
3878
			// [2] = cell title (optional), e.g. $.datepicker.noWeekends
3879
		beforeShow: null, // Function that takes an input field and
3880
			// returns a set of custom settings for the date picker
3881
		onSelect: null, // Define a callback function when a date is selected
3882
		onChangeMonthYear: null, // Define a callback function when the month or year is changed
3883
		onClose: null, // Define a callback function when the datepicker is closed
3884
		numberOfMonths: 1, // Number of months to show at a time
3885
		showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
3886
		stepMonths: 1, // Number of months to step back/forward
3887
		stepBigMonths: 12, // Number of months to step back/forward for the big links
3888
		altField: "", // Selector for an alternate field to store selected dates into
3889
		altFormat: "", // The date format to use for the alternate field
3890
		constrainInput: true, // The input is constrained by the current date format
3891
		showButtonPanel: false, // True to show button panel, false to not show it
3892
		autoSize: false, // True to size the input for the date format, false to leave as is
3893
		disabled: false // The initial disabled state
3894
	};
3895
	$.extend(this._defaults, this.regional[""]);
3896
	this.regional.en = $.extend( true, {}, this.regional[ "" ]);
3897
	this.regional[ "en-US" ] = $.extend( true, {}, this.regional.en );
3898
	this.dpDiv = datepicker_bindHover($("<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>"));
3899
}
3900
3901
$.extend(Datepicker.prototype, {
3902
	/* Class name added to elements to indicate already configured with a date picker. */
3903
	markerClassName: "hasDatepicker",
3904
3905
	//Keep track of the maximum number of rows displayed (see #7043)
3906
	maxRows: 4,
3907
3908
	// TODO rename to "widget" when switching to widget factory
3909
	_widgetDatepicker: function() {
3910
		return this.dpDiv;
3911
	},
3912
3913
	/* Override the default settings for all instances of the date picker.
3914
	 * @param  settings  object - the new settings to use as defaults (anonymous object)
3915
	 * @return the manager object
3916
	 */
3917
	setDefaults: function(settings) {
3918
		datepicker_extendRemove(this._defaults, settings || {});
3919
		return this;
3920
	},
3921
3922
	/* Attach the date picker to a jQuery selection.
3923
	 * @param  target	element - the target input field or division or span
3924
	 * @param  settings  object - the new settings to use for this date picker instance (anonymous)
3925
	 */
3926
	_attachDatepicker: function(target, settings) {
3927
		var nodeName, inline, inst;
3928
		nodeName = target.nodeName.toLowerCase();
3929
		inline = (nodeName === "div" || nodeName === "span");
3930
		if (!target.id) {
3931
			this.uuid += 1;
3932
			target.id = "dp" + this.uuid;
3933
		}
3934
		inst = this._newInst($(target), inline);
3935
		inst.settings = $.extend({}, settings || {});
3936
		if (nodeName === "input") {
3937
			this._connectDatepicker(target, inst);
3938
		} else if (inline) {
3939
			this._inlineDatepicker(target, inst);
3940
		}
3941
	},
3942
3943
	/* Create a new instance object. */
3944
	_newInst: function(target, inline) {
3945
		var id = target[0].id.replace(/([^A-Za-z0-9_\-])/g, "\\\\$1"); // escape jQuery meta chars
3946
		return {id: id, input: target, // associated target
3947
			selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
3948
			drawMonth: 0, drawYear: 0, // month being drawn
3949
			inline: inline, // is datepicker inline or not
3950
			dpDiv: (!inline ? this.dpDiv : // presentation div
3951
			datepicker_bindHover($("<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")))};
3952
	},
3953
3954
	/* Attach the date picker to an input field. */
3955
	_connectDatepicker: function(target, inst) {
3956
		var input = $(target);
3957
		inst.append = $([]);
3958
		inst.trigger = $([]);
3959
		if (input.hasClass(this.markerClassName)) {
3960
			return;
3961
		}
3962
		this._attachments(input, inst);
3963
		input.addClass(this.markerClassName).keydown(this._doKeyDown).
3964
			keypress(this._doKeyPress).keyup(this._doKeyUp);
3965
		this._autoSize(inst);
3966
		$.data(target, "datepicker", inst);
3967
		//If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
3968
		if( inst.settings.disabled ) {
3969
			this._disableDatepicker( target );
3970
		}
3971
	},
3972
3973
	/* Make attachments based on settings. */
3974
	_attachments: function(input, inst) {
3975
		var showOn, buttonText, buttonImage,
3976
			appendText = this._get(inst, "appendText"),
3977
			isRTL = this._get(inst, "isRTL");
3978
3979
		if (inst.append) {
3980
			inst.append.remove();
3981
		}
3982
		if (appendText) {
3983
			inst.append = $("<span class='" + this._appendClass + "'>" + appendText + "</span>");
3984
			input[isRTL ? "before" : "after"](inst.append);
3985
		}
3986
3987
		input.unbind("focus", this._showDatepicker);
3988
3989
		if (inst.trigger) {
3990
			inst.trigger.remove();
3991
		}
3992
3993
		showOn = this._get(inst, "showOn");
3994
		if (showOn === "focus" || showOn === "both") { // pop-up date picker when in the marked field
3995
			input.focus(this._showDatepicker);
3996
		}
3997
		if (showOn === "button" || showOn === "both") { // pop-up date picker when button clicked
3998
			buttonText = this._get(inst, "buttonText");
3999
			buttonImage = this._get(inst, "buttonImage");
4000
			inst.trigger = $(this._get(inst, "buttonImageOnly") ?
4001
				$("<img/>").addClass(this._triggerClass).
4002
					attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
4003
				$("<button type='button'></button>").addClass(this._triggerClass).
4004
					html(!buttonImage ? buttonText : $("<img/>").attr(
4005
					{ src:buttonImage, alt:buttonText, title:buttonText })));
4006
			input[isRTL ? "before" : "after"](inst.trigger);
4007
			inst.trigger.click(function() {
4008
				if ($.datepicker._datepickerShowing && $.datepicker._lastInput === input[0]) {
4009
					$.datepicker._hideDatepicker();
4010
				} else if ($.datepicker._datepickerShowing && $.datepicker._lastInput !== input[0]) {
4011
					$.datepicker._hideDatepicker();
4012
					$.datepicker._showDatepicker(input[0]);
4013
				} else {
4014
					$.datepicker._showDatepicker(input[0]);
4015
				}
4016
				return false;
4017
			});
4018
		}
4019
	},
4020
4021
	/* Apply the maximum length for the date format. */
4022
	_autoSize: function(inst) {
4023
		if (this._get(inst, "autoSize") && !inst.inline) {
4024
			var findMax, max, maxI, i,
4025
				date = new Date(2009, 12 - 1, 20), // Ensure double digits
4026
				dateFormat = this._get(inst, "dateFormat");
4027
4028
			if (dateFormat.match(/[DM]/)) {
4029
				findMax = function(names) {
4030
					max = 0;
4031
					maxI = 0;
4032
					for (i = 0; i < names.length; i++) {
4033
						if (names[i].length > max) {
4034
							max = names[i].length;
4035
							maxI = i;
4036
						}
4037
					}
4038
					return maxI;
4039
				};
4040
				date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
4041
					"monthNames" : "monthNamesShort"))));
4042
				date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
4043
					"dayNames" : "dayNamesShort"))) + 20 - date.getDay());
4044
			}
4045
			inst.input.attr("size", this._formatDate(inst, date).length);
4046
		}
4047
	},
4048
4049
	/* Attach an inline date picker to a div. */
4050
	_inlineDatepicker: function(target, inst) {
4051
		var divSpan = $(target);
4052
		if (divSpan.hasClass(this.markerClassName)) {
4053
			return;
4054
		}
4055
		divSpan.addClass(this.markerClassName).append(inst.dpDiv);
4056
		$.data(target, "datepicker", inst);
4057
		this._setDate(inst, this._getDefaultDate(inst), true);
4058
		this._updateDatepicker(inst);
4059
		this._updateAlternate(inst);
4060
		//If disabled option is true, disable the datepicker before showing it (see ticket #5665)
4061
		if( inst.settings.disabled ) {
4062
			this._disableDatepicker( target );
4063
		}
4064
		// Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
4065
		// http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
4066
		inst.dpDiv.css( "display", "block" );
4067
	},
4068
4069
	/* Pop-up the date picker in a "dialog" box.
4070
	 * @param  input element - ignored
4071
	 * @param  date	string or Date - the initial date to display
4072
	 * @param  onSelect  function - the function to call when a date is selected
4073
	 * @param  settings  object - update the dialog date picker instance's settings (anonymous object)
4074
	 * @param  pos int[2] - coordinates for the dialog's position within the screen or
4075
	 *					event - with x/y coordinates or
4076
	 *					leave empty for default (screen centre)
4077
	 * @return the manager object
4078
	 */
4079
	_dialogDatepicker: function(input, date, onSelect, settings, pos) {
4080
		var id, browserWidth, browserHeight, scrollX, scrollY,
4081
			inst = this._dialogInst; // internal instance
4082
4083
		if (!inst) {
4084
			this.uuid += 1;
4085
			id = "dp" + this.uuid;
4086
			this._dialogInput = $("<input type='text' id='" + id +
4087
				"' style='position: absolute; top: -100px; width: 0px;'/>");
4088
			this._dialogInput.keydown(this._doKeyDown);
4089
			$("body").append(this._dialogInput);
4090
			inst = this._dialogInst = this._newInst(this._dialogInput, false);
4091
			inst.settings = {};
4092
			$.data(this._dialogInput[0], "datepicker", inst);
4093
		}
4094
		datepicker_extendRemove(inst.settings, settings || {});
4095
		date = (date && date.constructor === Date ? this._formatDate(inst, date) : date);
4096
		this._dialogInput.val(date);
4097
4098
		this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
4099
		if (!this._pos) {
4100
			browserWidth = document.documentElement.clientWidth;
4101
			browserHeight = document.documentElement.clientHeight;
4102
			scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
4103
			scrollY = document.documentElement.scrollTop || document.body.scrollTop;
4104
			this._pos = // should use actual width/height below
4105
				[(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
4106
		}
4107
4108
		// move input on screen for focus, but hidden behind dialog
4109
		this._dialogInput.css("left", (this._pos[0] + 20) + "px").css("top", this._pos[1] + "px");
4110
		inst.settings.onSelect = onSelect;
4111
		this._inDialog = true;
4112
		this.dpDiv.addClass(this._dialogClass);
4113
		this._showDatepicker(this._dialogInput[0]);
4114
		if ($.blockUI) {
4115
			$.blockUI(this.dpDiv);
4116
		}
4117
		$.data(this._dialogInput[0], "datepicker", inst);
4118
		return this;
4119
	},
4120
4121
	/* Detach a datepicker from its control.
4122
	 * @param  target	element - the target input field or division or span
4123
	 */
4124
	_destroyDatepicker: function(target) {
4125
		var nodeName,
4126
			$target = $(target),
4127
			inst = $.data(target, "datepicker");
4128
4129
		if (!$target.hasClass(this.markerClassName)) {
4130
			return;
4131
		}
4132
4133
		nodeName = target.nodeName.toLowerCase();
4134
		$.removeData(target, "datepicker");
4135
		if (nodeName === "input") {
4136
			inst.append.remove();
4137
			inst.trigger.remove();
4138
			$target.removeClass(this.markerClassName).
4139
				unbind("focus", this._showDatepicker).
4140
				unbind("keydown", this._doKeyDown).
4141
				unbind("keypress", this._doKeyPress).
4142
				unbind("keyup", this._doKeyUp);
4143
		} else if (nodeName === "div" || nodeName === "span") {
4144
			$target.removeClass(this.markerClassName).empty();
4145
		}
4146
4147
		if ( datepicker_instActive === inst ) {
4148
			datepicker_instActive = null;
4149
		}
4150
	},
4151
4152
	/* Enable the date picker to a jQuery selection.
4153
	 * @param  target	element - the target input field or division or span
4154
	 */
4155
	_enableDatepicker: function(target) {
4156
		var nodeName, inline,
4157
			$target = $(target),
4158
			inst = $.data(target, "datepicker");
4159
4160
		if (!$target.hasClass(this.markerClassName)) {
4161
			return;
4162
		}
4163
4164
		nodeName = target.nodeName.toLowerCase();
4165
		if (nodeName === "input") {
4166
			target.disabled = false;
4167
			inst.trigger.filter("button").
4168
				each(function() { this.disabled = false; }).end().
4169
				filter("img").css({opacity: "1.0", cursor: ""});
4170
		} else if (nodeName === "div" || nodeName === "span") {
4171
			inline = $target.children("." + this._inlineClass);
4172
			inline.children().removeClass("ui-state-disabled");
4173
			inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
4174
				prop("disabled", false);
4175
		}
4176
		this._disabledInputs = $.map(this._disabledInputs,
4177
			function(value) { return (value === target ? null : value); }); // delete entry
4178
	},
4179
4180
	/* Disable the date picker to a jQuery selection.
4181
	 * @param  target	element - the target input field or division or span
4182
	 */
4183
	_disableDatepicker: function(target) {
4184
		var nodeName, inline,
4185
			$target = $(target),
4186
			inst = $.data(target, "datepicker");
4187
4188
		if (!$target.hasClass(this.markerClassName)) {
4189
			return;
4190
		}
4191
4192
		nodeName = target.nodeName.toLowerCase();
4193
		if (nodeName === "input") {
4194
			target.disabled = true;
4195
			inst.trigger.filter("button").
4196
				each(function() { this.disabled = true; }).end().
4197
				filter("img").css({opacity: "0.5", cursor: "default"});
4198
		} else if (nodeName === "div" || nodeName === "span") {
4199
			inline = $target.children("." + this._inlineClass);
4200
			inline.children().addClass("ui-state-disabled");
4201
			inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
4202
				prop("disabled", true);
4203
		}
4204
		this._disabledInputs = $.map(this._disabledInputs,
4205
			function(value) { return (value === target ? null : value); }); // delete entry
4206
		this._disabledInputs[this._disabledInputs.length] = target;
4207
	},
4208
4209
	/* Is the first field in a jQuery collection disabled as a datepicker?
4210
	 * @param  target	element - the target input field or division or span
4211
	 * @return boolean - true if disabled, false if enabled
4212
	 */
4213
	_isDisabledDatepicker: function(target) {
4214
		if (!target) {
4215
			return false;
4216
		}
4217
		for (var i = 0; i < this._disabledInputs.length; i++) {
4218
			if (this._disabledInputs[i] === target) {
4219
				return true;
4220
			}
4221
		}
4222
		return false;
4223
	},
4224
4225
	/* Retrieve the instance data for the target control.
4226
	 * @param  target  element - the target input field or division or span
4227
	 * @return  object - the associated instance data
4228
	 * @throws  error if a jQuery problem getting data
4229
	 */
4230
	_getInst: function(target) {
4231
		try {
4232
			return $.data(target, "datepicker");
4233
		}
4234
		catch (err) {
4235
			throw "Missing instance data for this datepicker";
4236
		}
4237
	},
4238
4239
	/* Update or retrieve the settings for a date picker attached to an input field or division.
4240
	 * @param  target  element - the target input field or division or span
4241
	 * @param  name	object - the new settings to update or
4242
	 *				string - the name of the setting to change or retrieve,
4243
	 *				when retrieving also "all" for all instance settings or
4244
	 *				"defaults" for all global defaults
4245
	 * @param  value   any - the new value for the setting
4246
	 *				(omit if above is an object or to retrieve a value)
4247
	 */
4248
	_optionDatepicker: function(target, name, value) {
4249
		var settings, date, minDate, maxDate,
4250
			inst = this._getInst(target);
4251
4252
		if (arguments.length === 2 && typeof name === "string") {
4253
			return (name === "defaults" ? $.extend({}, $.datepicker._defaults) :
4254
				(inst ? (name === "all" ? $.extend({}, inst.settings) :
4255
				this._get(inst, name)) : null));
4256
		}
4257
4258
		settings = name || {};
4259
		if (typeof name === "string") {
4260
			settings = {};
4261
			settings[name] = value;
4262
		}
4263
4264
		if (inst) {
4265
			if (this._curInst === inst) {
4266
				this._hideDatepicker();
4267
			}
4268
4269
			date = this._getDateDatepicker(target, true);
4270
			minDate = this._getMinMaxDate(inst, "min");
4271
			maxDate = this._getMinMaxDate(inst, "max");
4272
			datepicker_extendRemove(inst.settings, settings);
4273
			// reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
4274
			if (minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined) {
4275
				inst.settings.minDate = this._formatDate(inst, minDate);
4276
			}
4277
			if (maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined) {
4278
				inst.settings.maxDate = this._formatDate(inst, maxDate);
4279
			}
4280
			if ( "disabled" in settings ) {
4281
				if ( settings.disabled ) {
4282
					this._disableDatepicker(target);
4283
				} else {
4284
					this._enableDatepicker(target);
4285
				}
4286
			}
4287
			this._attachments($(target), inst);
4288
			this._autoSize(inst);
4289
			this._setDate(inst, date);
4290
			this._updateAlternate(inst);
4291
			this._updateDatepicker(inst);
4292
		}
4293
	},
4294
4295
	// change method deprecated
4296
	_changeDatepicker: function(target, name, value) {
4297
		this._optionDatepicker(target, name, value);
4298
	},
4299
4300
	/* Redraw the date picker attached to an input field or division.
4301
	 * @param  target  element - the target input field or division or span
4302
	 */
4303
	_refreshDatepicker: function(target) {
4304
		var inst = this._getInst(target);
4305
		if (inst) {
4306
			this._updateDatepicker(inst);
4307
		}
4308
	},
4309
4310
	/* Set the dates for a jQuery selection.
4311
	 * @param  target element - the target input field or division or span
4312
	 * @param  date	Date - the new date
4313
	 */
4314
	_setDateDatepicker: function(target, date) {
4315
		var inst = this._getInst(target);
4316
		if (inst) {
4317
			this._setDate(inst, date);
4318
			this._updateDatepicker(inst);
4319
			this._updateAlternate(inst);
4320
		}
4321
	},
4322
4323
	/* Get the date(s) for the first entry in a jQuery selection.
4324
	 * @param  target element - the target input field or division or span
4325
	 * @param  noDefault boolean - true if no default date is to be used
4326
	 * @return Date - the current date
4327
	 */
4328
	_getDateDatepicker: function(target, noDefault) {
4329
		var inst = this._getInst(target);
4330
		if (inst && !inst.inline) {
4331
			this._setDateFromField(inst, noDefault);
4332
		}
4333
		return (inst ? this._getDate(inst) : null);
4334
	},
4335
4336
	/* Handle keystrokes. */
4337
	_doKeyDown: function(event) {
4338
		var onSelect, dateStr, sel,
4339
			inst = $.datepicker._getInst(event.target),
4340
			handled = true,
4341
			isRTL = inst.dpDiv.is(".ui-datepicker-rtl");
4342
4343
		inst._keyEvent = true;
4344
		if ($.datepicker._datepickerShowing) {
4345
			switch (event.keyCode) {
4346
				case 9: $.datepicker._hideDatepicker();
4347
						handled = false;
4348
						break; // hide on tab out
4349
				case 13: sel = $("td." + $.datepicker._dayOverClass + ":not(." +
4350
									$.datepicker._currentClass + ")", inst.dpDiv);
4351
						if (sel[0]) {
4352
							$.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
4353
						}
4354
4355
						onSelect = $.datepicker._get(inst, "onSelect");
4356
						if (onSelect) {
4357
							dateStr = $.datepicker._formatDate(inst);
4358
4359
							// trigger custom callback
4360
							onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);
4361
						} else {
4362
							$.datepicker._hideDatepicker();
4363
						}
4364
4365
						return false; // don't submit the form
4366
				case 27: $.datepicker._hideDatepicker();
4367
						break; // hide on escape
4368
				case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
4369
							-$.datepicker._get(inst, "stepBigMonths") :
4370
							-$.datepicker._get(inst, "stepMonths")), "M");
4371
						break; // previous month/year on page up/+ ctrl
4372
				case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
4373
							+$.datepicker._get(inst, "stepBigMonths") :
4374
							+$.datepicker._get(inst, "stepMonths")), "M");
4375
						break; // next month/year on page down/+ ctrl
4376
				case 35: if (event.ctrlKey || event.metaKey) {
4377
							$.datepicker._clearDate(event.target);
4378
						}
4379
						handled = event.ctrlKey || event.metaKey;
4380
						break; // clear on ctrl or command +end
4381
				case 36: if (event.ctrlKey || event.metaKey) {
4382
							$.datepicker._gotoToday(event.target);
4383
						}
4384
						handled = event.ctrlKey || event.metaKey;
4385
						break; // current on ctrl or command +home
4386
				case 37: if (event.ctrlKey || event.metaKey) {
4387
							$.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), "D");
4388
						}
4389
						handled = event.ctrlKey || event.metaKey;
4390
						// -1 day on ctrl or command +left
4391
						if (event.originalEvent.altKey) {
4392
							$.datepicker._adjustDate(event.target, (event.ctrlKey ?
4393
								-$.datepicker._get(inst, "stepBigMonths") :
4394
								-$.datepicker._get(inst, "stepMonths")), "M");
4395
						}
4396
						// next month/year on alt +left on Mac
4397
						break;
4398
				case 38: if (event.ctrlKey || event.metaKey) {
4399
							$.datepicker._adjustDate(event.target, -7, "D");
4400
						}
4401
						handled = event.ctrlKey || event.metaKey;
4402
						break; // -1 week on ctrl or command +up
4403
				case 39: if (event.ctrlKey || event.metaKey) {
4404
							$.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), "D");
4405
						}
4406
						handled = event.ctrlKey || event.metaKey;
4407
						// +1 day on ctrl or command +right
4408
						if (event.originalEvent.altKey) {
4409
							$.datepicker._adjustDate(event.target, (event.ctrlKey ?
4410
								+$.datepicker._get(inst, "stepBigMonths") :
4411
								+$.datepicker._get(inst, "stepMonths")), "M");
4412
						}
4413
						// next month/year on alt +right
4414
						break;
4415
				case 40: if (event.ctrlKey || event.metaKey) {
4416
							$.datepicker._adjustDate(event.target, +7, "D");
4417
						}
4418
						handled = event.ctrlKey || event.metaKey;
4419
						break; // +1 week on ctrl or command +down
4420
				default: handled = false;
4421
			}
4422
		} else if (event.keyCode === 36 && event.ctrlKey) { // display the date picker on ctrl+home
4423
			$.datepicker._showDatepicker(this);
4424
		} else {
4425
			handled = false;
4426
		}
4427
4428
		if (handled) {
4429
			event.preventDefault();
4430
			event.stopPropagation();
4431
		}
4432
	},
4433
4434
	/* Filter entered characters - based on date format. */
4435
	_doKeyPress: function(event) {
4436
		var chars, chr,
4437
			inst = $.datepicker._getInst(event.target);
4438
4439
		if ($.datepicker._get(inst, "constrainInput")) {
4440
			chars = $.datepicker._possibleChars($.datepicker._get(inst, "dateFormat"));
4441
			chr = String.fromCharCode(event.charCode == null ? event.keyCode : event.charCode);
4442
			return event.ctrlKey || event.metaKey || (chr < " " || !chars || chars.indexOf(chr) > -1);
4443
		}
4444
	},
4445
4446
	/* Synchronise manual entry and field/alternate field. */
4447
	_doKeyUp: function(event) {
4448
		var date,
4449
			inst = $.datepicker._getInst(event.target);
4450
4451
		if (inst.input.val() !== inst.lastVal) {
4452
			try {
4453
				date = $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"),
4454
					(inst.input ? inst.input.val() : null),
4455
					$.datepicker._getFormatConfig(inst));
4456
4457
				if (date) { // only if valid
4458
					$.datepicker._setDateFromField(inst);
4459
					$.datepicker._updateAlternate(inst);
4460
					$.datepicker._updateDatepicker(inst);
4461
				}
4462
			}
4463
			catch (err) {
4464
			}
4465
		}
4466
		return true;
4467
	},
4468
4469
	/* Pop-up the date picker for a given input field.
4470
	 * If false returned from beforeShow event handler do not show.
4471
	 * @param  input  element - the input field attached to the date picker or
4472
	 *					event - if triggered by focus
4473
	 */
4474
	_showDatepicker: function(input) {
4475
		input = input.target || input;
4476
		if (input.nodeName.toLowerCase() !== "input") { // find from button/image trigger
4477
			input = $("input", input.parentNode)[0];
4478
		}
4479
4480
		if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput === input) { // already here
4481
			return;
4482
		}
4483
4484
		var inst, beforeShow, beforeShowSettings, isFixed,
4485
			offset, showAnim, duration;
4486
4487
		inst = $.datepicker._getInst(input);
4488
		if ($.datepicker._curInst && $.datepicker._curInst !== inst) {
4489
			$.datepicker._curInst.dpDiv.stop(true, true);
4490
			if ( inst && $.datepicker._datepickerShowing ) {
4491
				$.datepicker._hideDatepicker( $.datepicker._curInst.input[0] );
4492
			}
4493
		}
4494
4495
		beforeShow = $.datepicker._get(inst, "beforeShow");
4496
		beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {};
4497
		if(beforeShowSettings === false){
4498
			return;
4499
		}
4500
		datepicker_extendRemove(inst.settings, beforeShowSettings);
4501
4502
		inst.lastVal = null;
4503
		$.datepicker._lastInput = input;
4504
		$.datepicker._setDateFromField(inst);
4505
4506
		if ($.datepicker._inDialog) { // hide cursor
4507
			input.value = "";
4508
		}
4509
		if (!$.datepicker._pos) { // position below input
4510
			$.datepicker._pos = $.datepicker._findPos(input);
4511
			$.datepicker._pos[1] += input.offsetHeight; // add the height
4512
		}
4513
4514
		isFixed = false;
4515
		$(input).parents().each(function() {
4516
			isFixed |= $(this).css("position") === "fixed";
4517
			return !isFixed;
4518
		});
4519
4520
		offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
4521
		$.datepicker._pos = null;
4522
		//to avoid flashes on Firefox
4523
		inst.dpDiv.empty();
4524
		// determine sizing offscreen
4525
		inst.dpDiv.css({position: "absolute", display: "block", top: "-1000px"});
4526
		$.datepicker._updateDatepicker(inst);
4527
		// fix width for dynamic number of date pickers
4528
		// and adjust position before showing
4529
		offset = $.datepicker._checkOffset(inst, offset, isFixed);
4530
		inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
4531
			"static" : (isFixed ? "fixed" : "absolute")), display: "none",
4532
			left: offset.left + "px", top: offset.top + "px"});
4533
4534
		if (!inst.inline) {
4535
			showAnim = $.datepicker._get(inst, "showAnim");
4536
			duration = $.datepicker._get(inst, "duration");
4537
			inst.dpDiv.css( "z-index", datepicker_getZindex( $( input ) ) + 1 );
4538
			$.datepicker._datepickerShowing = true;
4539
4540
			if ( $.effects && $.effects.effect[ showAnim ] ) {
4541
				inst.dpDiv.show(showAnim, $.datepicker._get(inst, "showOptions"), duration);
4542
			} else {
4543
				inst.dpDiv[showAnim || "show"](showAnim ? duration : null);
4544
			}
4545
4546
			if ( $.datepicker._shouldFocusInput( inst ) ) {
4547
				inst.input.focus();
4548
			}
4549
4550
			$.datepicker._curInst = inst;
4551
		}
4552
	},
4553
4554
	/* Generate the date picker content. */
4555
	_updateDatepicker: function(inst) {
4556
		this.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
4557
		datepicker_instActive = inst; // for delegate hover events
4558
		inst.dpDiv.empty().append(this._generateHTML(inst));
4559
		this._attachHandlers(inst);
4560
4561
		var origyearshtml,
4562
			numMonths = this._getNumberOfMonths(inst),
4563
			cols = numMonths[1],
4564
			width = 17,
4565
			activeCell = inst.dpDiv.find( "." + this._dayOverClass + " a" );
4566
4567
		if ( activeCell.length > 0 ) {
4568
			datepicker_handleMouseover.apply( activeCell.get( 0 ) );
4569
		}
4570
4571
		inst.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width("");
4572
		if (cols > 1) {
4573
			inst.dpDiv.addClass("ui-datepicker-multi-" + cols).css("width", (width * cols) + "em");
4574
		}
4575
		inst.dpDiv[(numMonths[0] !== 1 || numMonths[1] !== 1 ? "add" : "remove") +
4576
			"Class"]("ui-datepicker-multi");
4577
		inst.dpDiv[(this._get(inst, "isRTL") ? "add" : "remove") +
4578
			"Class"]("ui-datepicker-rtl");
4579
4580
		if (inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) {
4581
			inst.input.focus();
4582
		}
4583
4584
		// deffered render of the years select (to avoid flashes on Firefox)
4585
		if( inst.yearshtml ){
4586
			origyearshtml = inst.yearshtml;
4587
			setTimeout(function(){
4588
				//assure that inst.yearshtml didn't change.
4589
				if( origyearshtml === inst.yearshtml && inst.yearshtml ){
4590
					inst.dpDiv.find("select.ui-datepicker-year:first").replaceWith(inst.yearshtml);
4591
				}
4592
				origyearshtml = inst.yearshtml = null;
4593
			}, 0);
4594
		}
4595
	},
4596
4597
	// #6694 - don't focus the input if it's already focused
4598
	// this breaks the change event in IE
4599
	// Support: IE and jQuery <1.9
4600
	_shouldFocusInput: function( inst ) {
4601
		return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" ) && !inst.input.is( ":focus" );
4602
	},
4603
4604
	/* Check positioning to remain on screen. */
4605
	_checkOffset: function(inst, offset, isFixed) {
4606
		var dpWidth = inst.dpDiv.outerWidth(),
4607
			dpHeight = inst.dpDiv.outerHeight(),
4608
			inputWidth = inst.input ? inst.input.outerWidth() : 0,
4609
			inputHeight = inst.input ? inst.input.outerHeight() : 0,
4610
			viewWidth = document.documentElement.clientWidth + (isFixed ? 0 : $(document).scrollLeft()),
4611
			viewHeight = document.documentElement.clientHeight + (isFixed ? 0 : $(document).scrollTop());
4612
4613
		offset.left -= (this._get(inst, "isRTL") ? (dpWidth - inputWidth) : 0);
4614
		offset.left -= (isFixed && offset.left === inst.input.offset().left) ? $(document).scrollLeft() : 0;
4615
		offset.top -= (isFixed && offset.top === (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
4616
4617
		// now check if datepicker is showing outside window viewport - move to a better place if so.
4618
		offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
4619
			Math.abs(offset.left + dpWidth - viewWidth) : 0);
4620
		offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
4621
			Math.abs(dpHeight + inputHeight) : 0);
4622
4623
		return offset;
4624
	},
4625
4626
	/* Find an object's position on the screen. */
4627
	_findPos: function(obj) {
4628
		var position,
4629
			inst = this._getInst(obj),
4630
			isRTL = this._get(inst, "isRTL");
4631
4632
		while (obj && (obj.type === "hidden" || obj.nodeType !== 1 || $.expr.filters.hidden(obj))) {
4633
			obj = obj[isRTL ? "previousSibling" : "nextSibling"];
4634
		}
4635
4636
		position = $(obj).offset();
4637
		return [position.left, position.top];
4638
	},
4639
4640
	/* Hide the date picker from view.
4641
	 * @param  input  element - the input field attached to the date picker
4642
	 */
4643
	_hideDatepicker: function(input) {
4644
		var showAnim, duration, postProcess, onClose,
4645
			inst = this._curInst;
4646
4647
		if (!inst || (input && inst !== $.data(input, "datepicker"))) {
4648
			return;
4649
		}
4650
4651
		if (this._datepickerShowing) {
4652
			showAnim = this._get(inst, "showAnim");
4653
			duration = this._get(inst, "duration");
4654
			postProcess = function() {
4655
				$.datepicker._tidyDialog(inst);
4656
			};
4657
4658
			// DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed
4659
			if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) {
4660
				inst.dpDiv.hide(showAnim, $.datepicker._get(inst, "showOptions"), duration, postProcess);
4661
			} else {
4662
				inst.dpDiv[(showAnim === "slideDown" ? "slideUp" :
4663
					(showAnim === "fadeIn" ? "fadeOut" : "hide"))]((showAnim ? duration : null), postProcess);
4664
			}
4665
4666
			if (!showAnim) {
4667
				postProcess();
4668
			}
4669
			this._datepickerShowing = false;
4670
4671
			onClose = this._get(inst, "onClose");
4672
			if (onClose) {
4673
				onClose.apply((inst.input ? inst.input[0] : null), [(inst.input ? inst.input.val() : ""), inst]);
4674
			}
4675
4676
			this._lastInput = null;
4677
			if (this._inDialog) {
4678
				this._dialogInput.css({ position: "absolute", left: "0", top: "-100px" });
4679
				if ($.blockUI) {
4680
					$.unblockUI();
4681
					$("body").append(this.dpDiv);
4682
				}
4683
			}
4684
			this._inDialog = false;
4685
		}
4686
	},
4687
4688
	/* Tidy up after a dialog display. */
4689
	_tidyDialog: function(inst) {
4690
		inst.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar");
4691
	},
4692
4693
	/* Close date picker if clicked elsewhere. */
4694
	_checkExternalClick: function(event) {
4695
		if (!$.datepicker._curInst) {
4696
			return;
4697
		}
4698
4699
		var $target = $(event.target),
4700
			inst = $.datepicker._getInst($target[0]);
4701
4702
		if ( ( ( $target[0].id !== $.datepicker._mainDivId &&
4703
				$target.parents("#" + $.datepicker._mainDivId).length === 0 &&
4704
				!$target.hasClass($.datepicker.markerClassName) &&
4705
				!$target.closest("." + $.datepicker._triggerClass).length &&
4706
				$.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI) ) ) ||
4707
			( $target.hasClass($.datepicker.markerClassName) && $.datepicker._curInst !== inst ) ) {
4708
				$.datepicker._hideDatepicker();
4709
		}
4710
	},
4711
4712
	/* Adjust one of the date sub-fields. */
4713
	_adjustDate: function(id, offset, period) {
4714
		var target = $(id),
4715
			inst = this._getInst(target[0]);
4716
4717
		if (this._isDisabledDatepicker(target[0])) {
4718
			return;
4719
		}
4720
		this._adjustInstDate(inst, offset +
4721
			(period === "M" ? this._get(inst, "showCurrentAtPos") : 0), // undo positioning
4722
			period);
4723
		this._updateDatepicker(inst);
4724
	},
4725
4726
	/* Action for current link. */
4727
	_gotoToday: function(id) {
4728
		var date,
4729
			target = $(id),
4730
			inst = this._getInst(target[0]);
4731
4732
		if (this._get(inst, "gotoCurrent") && inst.currentDay) {
4733
			inst.selectedDay = inst.currentDay;
4734
			inst.drawMonth = inst.selectedMonth = inst.currentMonth;
4735
			inst.drawYear = inst.selectedYear = inst.currentYear;
4736
		} else {
4737
			date = new Date();
4738
			inst.selectedDay = date.getDate();
4739
			inst.drawMonth = inst.selectedMonth = date.getMonth();
4740
			inst.drawYear = inst.selectedYear = date.getFullYear();
4741
		}
4742
		this._notifyChange(inst);
4743
		this._adjustDate(target);
4744
	},
4745
4746
	/* Action for selecting a new month/year. */
4747
	_selectMonthYear: function(id, select, period) {
4748
		var target = $(id),
4749
			inst = this._getInst(target[0]);
4750
4751
		inst["selected" + (period === "M" ? "Month" : "Year")] =
4752
		inst["draw" + (period === "M" ? "Month" : "Year")] =
4753
			parseInt(select.options[select.selectedIndex].value,10);
4754
4755
		this._notifyChange(inst);
4756
		this._adjustDate(target);
4757
	},
4758
4759
	/* Action for selecting a day. */
4760
	_selectDay: function(id, month, year, td) {
4761
		var inst,
4762
			target = $(id);
4763
4764
		if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
4765
			return;
4766
		}
4767
4768
		inst = this._getInst(target[0]);
4769
		inst.selectedDay = inst.currentDay = $("a", td).html();
4770
		inst.selectedMonth = inst.currentMonth = month;
4771
		inst.selectedYear = inst.currentYear = year;
4772
		this._selectDate(id, this._formatDate(inst,
4773
			inst.currentDay, inst.currentMonth, inst.currentYear));
4774
	},
4775
4776
	/* Erase the input field and hide the date picker. */
4777
	_clearDate: function(id) {
4778
		var target = $(id);
4779
		this._selectDate(target, "");
4780
	},
4781
4782
	/* Update the input field with the selected date. */
4783
	_selectDate: function(id, dateStr) {
4784
		var onSelect,
4785
			target = $(id),
4786
			inst = this._getInst(target[0]);
4787
4788
		dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
4789
		if (inst.input) {
4790
			inst.input.val(dateStr);
4791
		}
4792
		this._updateAlternate(inst);
4793
4794
		onSelect = this._get(inst, "onSelect");
4795
		if (onSelect) {
4796
			onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);  // trigger custom callback
4797
		} else if (inst.input) {
4798
			inst.input.trigger("change"); // fire the change event
4799
		}
4800
4801
		if (inst.inline){
4802
			this._updateDatepicker(inst);
4803
		} else {
4804
			this._hideDatepicker();
4805
			this._lastInput = inst.input[0];
4806
			if (typeof(inst.input[0]) !== "object") {
4807
				inst.input.focus(); // restore focus
4808
			}
4809
			this._lastInput = null;
4810
		}
4811
	},
4812
4813
	/* Update any alternate field to synchronise with the main field. */
4814
	_updateAlternate: function(inst) {
4815
		var altFormat, date, dateStr,
4816
			altField = this._get(inst, "altField");
4817
4818
		if (altField) { // update alternate field too
4819
			altFormat = this._get(inst, "altFormat") || this._get(inst, "dateFormat");
4820
			date = this._getDate(inst);
4821
			dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
4822
			$(altField).each(function() { $(this).val(dateStr); });
4823
		}
4824
	},
4825
4826
	/* Set as beforeShowDay function to prevent selection of weekends.
4827
	 * @param  date  Date - the date to customise
4828
	 * @return [boolean, string] - is this date selectable?, what is its CSS class?
4829
	 */
4830
	noWeekends: function(date) {
4831
		var day = date.getDay();
4832
		return [(day > 0 && day < 6), ""];
4833
	},
4834
4835
	/* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
4836
	 * @param  date  Date - the date to get the week for
4837
	 * @return  number - the number of the week within the year that contains this date
4838
	 */
4839
	iso8601Week: function(date) {
4840
		var time,
4841
			checkDate = new Date(date.getTime());
4842
4843
		// Find Thursday of this week starting on Monday
4844
		checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
4845
4846
		time = checkDate.getTime();
4847
		checkDate.setMonth(0); // Compare with Jan 1
4848
		checkDate.setDate(1);
4849
		return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
4850
	},
4851
4852
	/* Parse a string value into a date object.
4853
	 * See formatDate below for the possible formats.
4854
	 *
4855
	 * @param  format string - the expected format of the date
4856
	 * @param  value string - the date in the above format
4857
	 * @param  settings Object - attributes include:
4858
	 *					shortYearCutoff  number - the cutoff year for determining the century (optional)
4859
	 *					dayNamesShort	string[7] - abbreviated names of the days from Sunday (optional)
4860
	 *					dayNames		string[7] - names of the days from Sunday (optional)
4861
	 *					monthNamesShort string[12] - abbreviated names of the months (optional)
4862
	 *					monthNames		string[12] - names of the months (optional)
4863
	 * @return  Date - the extracted date value or null if value is blank
4864
	 */
4865
	parseDate: function (format, value, settings) {
4866
		if (format == null || value == null) {
4867
			throw "Invalid arguments";
4868
		}
4869
4870
		value = (typeof value === "object" ? value.toString() : value + "");
4871
		if (value === "") {
4872
			return null;
4873
		}
4874
4875
		var iFormat, dim, extra,
4876
			iValue = 0,
4877
			shortYearCutoffTemp = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff,
4878
			shortYearCutoff = (typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp :
4879
				new Date().getFullYear() % 100 + parseInt(shortYearCutoffTemp, 10)),
4880
			dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort,
4881
			dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames,
4882
			monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort,
4883
			monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames,
4884
			year = -1,
4885
			month = -1,
4886
			day = -1,
4887
			doy = -1,
4888
			literal = false,
4889
			date,
4890
			// Check whether a format character is doubled
4891
			lookAhead = function(match) {
4892
				var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
4893
				if (matches) {
4894
					iFormat++;
4895
				}
4896
				return matches;
4897
			},
4898
			// Extract a number from the string value
4899
			getNumber = function(match) {
4900
				var isDoubled = lookAhead(match),
4901
					size = (match === "@" ? 14 : (match === "!" ? 20 :
4902
					(match === "y" && isDoubled ? 4 : (match === "o" ? 3 : 2)))),
4903
					minSize = (match === "y" ? size : 1),
4904
					digits = new RegExp("^\\d{" + minSize + "," + size + "}"),
4905
					num = value.substring(iValue).match(digits);
4906
				if (!num) {
4907
					throw "Missing number at position " + iValue;
4908
				}
4909
				iValue += num[0].length;
4910
				return parseInt(num[0], 10);
4911
			},
4912
			// Extract a name from the string value and convert to an index
4913
			getName = function(match, shortNames, longNames) {
4914
				var index = -1,
4915
					names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) {
4916
						return [ [k, v] ];
4917
					}).sort(function (a, b) {
4918
						return -(a[1].length - b[1].length);
4919
					});
4920
4921
				$.each(names, function (i, pair) {
4922
					var name = pair[1];
4923
					if (value.substr(iValue, name.length).toLowerCase() === name.toLowerCase()) {
4924
						index = pair[0];
4925
						iValue += name.length;
4926
						return false;
4927
					}
4928
				});
4929
				if (index !== -1) {
4930
					return index + 1;
4931
				} else {
4932
					throw "Unknown name at position " + iValue;
4933
				}
4934
			},
4935
			// Confirm that a literal character matches the string value
4936
			checkLiteral = function() {
4937
				if (value.charAt(iValue) !== format.charAt(iFormat)) {
4938
					throw "Unexpected literal at position " + iValue;
4939
				}
4940
				iValue++;
4941
			};
4942
4943
		for (iFormat = 0; iFormat < format.length; iFormat++) {
4944
			if (literal) {
4945
				if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
4946
					literal = false;
4947
				} else {
4948
					checkLiteral();
4949
				}
4950
			} else {
4951
				switch (format.charAt(iFormat)) {
4952
					case "d":
4953
						day = getNumber("d");
4954
						break;
4955
					case "D":
4956
						getName("D", dayNamesShort, dayNames);
4957
						break;
4958
					case "o":
4959
						doy = getNumber("o");
4960
						break;
4961
					case "m":
4962
						month = getNumber("m");
4963
						break;
4964
					case "M":
4965
						month = getName("M", monthNamesShort, monthNames);
4966
						break;
4967
					case "y":
4968
						year = getNumber("y");
4969
						break;
4970
					case "@":
4971
						date = new Date(getNumber("@"));
4972
						year = date.getFullYear();
4973
						month = date.getMonth() + 1;
4974
						day = date.getDate();
4975
						break;
4976
					case "!":
4977
						date = new Date((getNumber("!") - this._ticksTo1970) / 10000);
4978
						year = date.getFullYear();
4979
						month = date.getMonth() + 1;
4980
						day = date.getDate();
4981
						break;
4982
					case "'":
4983
						if (lookAhead("'")){
4984
							checkLiteral();
4985
						} else {
4986
							literal = true;
4987
						}
4988
						break;
4989
					default:
4990
						checkLiteral();
4991
				}
4992
			}
4993
		}
4994
4995
		if (iValue < value.length){
4996
			extra = value.substr(iValue);
4997
			if (!/^\s+/.test(extra)) {
4998
				throw "Extra/unparsed characters found in date: " + extra;
4999
			}
5000
		}
5001
5002
		if (year === -1) {
5003
			year = new Date().getFullYear();
5004
		} else if (year < 100) {
5005
			year += new Date().getFullYear() - new Date().getFullYear() % 100 +
5006
				(year <= shortYearCutoff ? 0 : -100);
5007
		}
5008
5009
		if (doy > -1) {
5010
			month = 1;
5011
			day = doy;
5012
			do {
5013
				dim = this._getDaysInMonth(year, month - 1);
5014
				if (day <= dim) {
5015
					break;
5016
				}
5017
				month++;
5018
				day -= dim;
5019
			} while (true);
5020
		}
5021
5022
		date = this._daylightSavingAdjust(new Date(year, month - 1, day));
5023
		if (date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day) {
5024
			throw "Invalid date"; // E.g. 31/02/00
5025
		}
5026
		return date;
5027
	},
5028
5029
	/* Standard date formats. */
5030
	ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601)
5031
	COOKIE: "D, dd M yy",
5032
	ISO_8601: "yy-mm-dd",
5033
	RFC_822: "D, d M y",
5034
	RFC_850: "DD, dd-M-y",
5035
	RFC_1036: "D, d M y",
5036
	RFC_1123: "D, d M yy",
5037
	RFC_2822: "D, d M yy",
5038
	RSS: "D, d M y", // RFC 822
5039
	TICKS: "!",
5040
	TIMESTAMP: "@",
5041
	W3C: "yy-mm-dd", // ISO 8601
5042
5043
	_ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
5044
		Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
5045
5046
	/* Format a date object into a string value.
5047
	 * The format can be combinations of the following:
5048
	 * d  - day of month (no leading zero)
5049
	 * dd - day of month (two digit)
5050
	 * o  - day of year (no leading zeros)
5051
	 * oo - day of year (three digit)
5052
	 * D  - day name short
5053
	 * DD - day name long
5054
	 * m  - month of year (no leading zero)
5055
	 * mm - month of year (two digit)
5056
	 * M  - month name short
5057
	 * MM - month name long
5058
	 * y  - year (two digit)
5059
	 * yy - year (four digit)
5060
	 * @ - Unix timestamp (ms since 01/01/1970)
5061
	 * ! - Windows ticks (100ns since 01/01/0001)
5062
	 * "..." - literal text
5063
	 * '' - single quote
5064
	 *
5065
	 * @param  format string - the desired format of the date
5066
	 * @param  date Date - the date value to format
5067
	 * @param  settings Object - attributes include:
5068
	 *					dayNamesShort	string[7] - abbreviated names of the days from Sunday (optional)
5069
	 *					dayNames		string[7] - names of the days from Sunday (optional)
5070
	 *					monthNamesShort string[12] - abbreviated names of the months (optional)
5071
	 *					monthNames		string[12] - names of the months (optional)
5072
	 * @return  string - the date in the above format
5073
	 */
5074
	formatDate: function (format, date, settings) {
5075
		if (!date) {
5076
			return "";
5077
		}
5078
5079
		var iFormat,
5080
			dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort,
5081
			dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames,
5082
			monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort,
5083
			monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames,
5084
			// Check whether a format character is doubled
5085
			lookAhead = function(match) {
5086
				var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
5087
				if (matches) {
5088
					iFormat++;
5089
				}
5090
				return matches;
5091
			},
5092
			// Format a number, with leading zero if necessary
5093
			formatNumber = function(match, value, len) {
5094
				var num = "" + value;
5095
				if (lookAhead(match)) {
5096
					while (num.length < len) {
5097
						num = "0" + num;
5098
					}
5099
				}
5100
				return num;
5101
			},
5102
			// Format a name, short or long as requested
5103
			formatName = function(match, value, shortNames, longNames) {
5104
				return (lookAhead(match) ? longNames[value] : shortNames[value]);
5105
			},
5106
			output = "",
5107
			literal = false;
5108
5109
		if (date) {
5110
			for (iFormat = 0; iFormat < format.length; iFormat++) {
5111
				if (literal) {
5112
					if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
5113
						literal = false;
5114
					} else {
5115
						output += format.charAt(iFormat);
5116
					}
5117
				} else {
5118
					switch (format.charAt(iFormat)) {
5119
						case "d":
5120
							output += formatNumber("d", date.getDate(), 2);
5121
							break;
5122
						case "D":
5123
							output += formatName("D", date.getDay(), dayNamesShort, dayNames);
5124
							break;
5125
						case "o":
5126
							output += formatNumber("o",
5127
								Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3);
5128
							break;
5129
						case "m":
5130
							output += formatNumber("m", date.getMonth() + 1, 2);
5131
							break;
5132
						case "M":
5133
							output += formatName("M", date.getMonth(), monthNamesShort, monthNames);
5134
							break;
5135
						case "y":
5136
							output += (lookAhead("y") ? date.getFullYear() :
5137
								(date.getYear() % 100 < 10 ? "0" : "") + date.getYear() % 100);
5138
							break;
5139
						case "@":
5140
							output += date.getTime();
5141
							break;
5142
						case "!":
5143
							output += date.getTime() * 10000 + this._ticksTo1970;
5144
							break;
5145
						case "'":
5146
							if (lookAhead("'")) {
5147
								output += "'";
5148
							} else {
5149
								literal = true;
5150
							}
5151
							break;
5152
						default:
5153
							output += format.charAt(iFormat);
5154
					}
5155
				}
5156
			}
5157
		}
5158
		return output;
5159
	},
5160
5161
	/* Extract all possible characters from the date format. */
5162
	_possibleChars: function (format) {
5163
		var iFormat,
5164
			chars = "",
5165
			literal = false,
5166
			// Check whether a format character is doubled
5167
			lookAhead = function(match) {
5168
				var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
5169
				if (matches) {
5170
					iFormat++;
5171
				}
5172
				return matches;
5173
			};
5174
5175
		for (iFormat = 0; iFormat < format.length; iFormat++) {
5176
			if (literal) {
5177
				if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
5178
					literal = false;
5179
				} else {
5180
					chars += format.charAt(iFormat);
5181
				}
5182
			} else {
5183
				switch (format.charAt(iFormat)) {
5184
					case "d": case "m": case "y": case "@":
5185
						chars += "0123456789";
5186
						break;
5187
					case "D": case "M":
5188
						return null; // Accept anything
5189
					case "'":
5190
						if (lookAhead("'")) {
5191
							chars += "'";
5192
						} else {
5193
							literal = true;
5194
						}
5195
						break;
5196
					default:
5197
						chars += format.charAt(iFormat);
5198
				}
5199
			}
5200
		}
5201
		return chars;
5202
	},
5203
5204
	/* Get a setting value, defaulting if necessary. */
5205
	_get: function(inst, name) {
5206
		return inst.settings[name] !== undefined ?
5207
			inst.settings[name] : this._defaults[name];
5208
	},
5209
5210
	/* Parse existing date and initialise date picker. */
5211
	_setDateFromField: function(inst, noDefault) {
5212
		if (inst.input.val() === inst.lastVal) {
5213
			return;
5214
		}
5215
5216
		var dateFormat = this._get(inst, "dateFormat"),
5217
			dates = inst.lastVal = inst.input ? inst.input.val() : null,
5218
			defaultDate = this._getDefaultDate(inst),
5219
			date = defaultDate,
5220
			settings = this._getFormatConfig(inst);
5221
5222
		try {
5223
			date = this.parseDate(dateFormat, dates, settings) || defaultDate;
5224
		} catch (event) {
5225
			dates = (noDefault ? "" : dates);
5226
		}
5227
		inst.selectedDay = date.getDate();
5228
		inst.drawMonth = inst.selectedMonth = date.getMonth();
5229
		inst.drawYear = inst.selectedYear = date.getFullYear();
5230
		inst.currentDay = (dates ? date.getDate() : 0);
5231
		inst.currentMonth = (dates ? date.getMonth() : 0);
5232
		inst.currentYear = (dates ? date.getFullYear() : 0);
5233
		this._adjustInstDate(inst);
5234
	},
5235
5236
	/* Retrieve the default date shown on opening. */
5237
	_getDefaultDate: function(inst) {
5238
		return this._restrictMinMax(inst,
5239
			this._determineDate(inst, this._get(inst, "defaultDate"), new Date()));
5240
	},
5241
5242
	/* A date may be specified as an exact value or a relative one. */
5243
	_determineDate: function(inst, date, defaultDate) {
5244
		var offsetNumeric = function(offset) {
5245
				var date = new Date();
5246
				date.setDate(date.getDate() + offset);
5247
				return date;
5248
			},
5249
			offsetString = function(offset) {
5250
				try {
5251
					return $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"),
5252
						offset, $.datepicker._getFormatConfig(inst));
5253
				}
5254
				catch (e) {
5255
					// Ignore
5256
				}
5257
5258
				var date = (offset.toLowerCase().match(/^c/) ?
5259
					$.datepicker._getDate(inst) : null) || new Date(),
5260
					year = date.getFullYear(),
5261
					month = date.getMonth(),
5262
					day = date.getDate(),
5263
					pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,
5264
					matches = pattern.exec(offset);
5265
5266
				while (matches) {
5267
					switch (matches[2] || "d") {
5268
						case "d" : case "D" :
5269
							day += parseInt(matches[1],10); break;
5270
						case "w" : case "W" :
5271
							day += parseInt(matches[1],10) * 7; break;
5272
						case "m" : case "M" :
5273
							month += parseInt(matches[1],10);
5274
							day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
5275
							break;
5276
						case "y": case "Y" :
5277
							year += parseInt(matches[1],10);
5278
							day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
5279
							break;
5280
					}
5281
					matches = pattern.exec(offset);
5282
				}
5283
				return new Date(year, month, day);
5284
			},
5285
			newDate = (date == null || date === "" ? defaultDate : (typeof date === "string" ? offsetString(date) :
5286
				(typeof date === "number" ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime()))));
5287
5288
		newDate = (newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate);
5289
		if (newDate) {
5290
			newDate.setHours(0);
5291
			newDate.setMinutes(0);
5292
			newDate.setSeconds(0);
5293
			newDate.setMilliseconds(0);
5294
		}
5295
		return this._daylightSavingAdjust(newDate);
5296
	},
5297
5298
	/* Handle switch to/from daylight saving.
5299
	 * Hours may be non-zero on daylight saving cut-over:
5300
	 * > 12 when midnight changeover, but then cannot generate
5301
	 * midnight datetime, so jump to 1AM, otherwise reset.
5302
	 * @param  date  (Date) the date to check
5303
	 * @return  (Date) the corrected date
5304
	 */
5305
	_daylightSavingAdjust: function(date) {
5306
		if (!date) {
5307
			return null;
5308
		}
5309
		date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
5310
		return date;
5311
	},
5312
5313
	/* Set the date(s) directly. */
5314
	_setDate: function(inst, date, noChange) {
5315
		var clear = !date,
5316
			origMonth = inst.selectedMonth,
5317
			origYear = inst.selectedYear,
5318
			newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
5319
5320
		inst.selectedDay = inst.currentDay = newDate.getDate();
5321
		inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
5322
		inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
5323
		if ((origMonth !== inst.selectedMonth || origYear !== inst.selectedYear) && !noChange) {
5324
			this._notifyChange(inst);
5325
		}
5326
		this._adjustInstDate(inst);
5327
		if (inst.input) {
5328
			inst.input.val(clear ? "" : this._formatDate(inst));
5329
		}
5330
	},
5331
5332
	/* Retrieve the date(s) directly. */
5333
	_getDate: function(inst) {
5334
		var startDate = (!inst.currentYear || (inst.input && inst.input.val() === "") ? null :
5335
			this._daylightSavingAdjust(new Date(
5336
			inst.currentYear, inst.currentMonth, inst.currentDay)));
5337
			return startDate;
5338
	},
5339
5340
	/* Attach the onxxx handlers.  These are declared statically so
5341
	 * they work with static code transformers like Caja.
5342
	 */
5343
	_attachHandlers: function(inst) {
5344
		var stepMonths = this._get(inst, "stepMonths"),
5345
			id = "#" + inst.id.replace( /\\\\/g, "\\" );
5346
		inst.dpDiv.find("[data-handler]").map(function () {
5347
			var handler = {
5348
				prev: function () {
5349
					$.datepicker._adjustDate(id, -stepMonths, "M");
5350
				},
5351
				next: function () {
5352
					$.datepicker._adjustDate(id, +stepMonths, "M");
5353
				},
5354
				hide: function () {
5355
					$.datepicker._hideDatepicker();
5356
				},
5357
				today: function () {
5358
					$.datepicker._gotoToday(id);
5359
				},
5360
				selectDay: function () {
5361
					$.datepicker._selectDay(id, +this.getAttribute("data-month"), +this.getAttribute("data-year"), this);
5362
					return false;
5363
				},
5364
				selectMonth: function () {
5365
					$.datepicker._selectMonthYear(id, this, "M");
5366
					return false;
5367
				},
5368
				selectYear: function () {
5369
					$.datepicker._selectMonthYear(id, this, "Y");
5370
					return false;
5371
				}
5372
			};
5373
			$(this).bind(this.getAttribute("data-event"), handler[this.getAttribute("data-handler")]);
5374
		});
5375
	},
5376
5377
	/* Generate the HTML for the current state of the date picker. */
5378
	_generateHTML: function(inst) {
5379
		var maxDraw, prevText, prev, nextText, next, currentText, gotoDate,
5380
			controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin,
5381
			monthNames, monthNamesShort, beforeShowDay, showOtherMonths,
5382
			selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate,
5383
			cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows,
5384
			printDate, dRow, tbody, daySettings, otherMonth, unselectable,
5385
			tempDate = new Date(),
5386
			today = this._daylightSavingAdjust(
5387
				new Date(tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate())), // clear time
5388
			isRTL = this._get(inst, "isRTL"),
5389
			showButtonPanel = this._get(inst, "showButtonPanel"),
5390
			hideIfNoPrevNext = this._get(inst, "hideIfNoPrevNext"),
5391
			navigationAsDateFormat = this._get(inst, "navigationAsDateFormat"),
5392
			numMonths = this._getNumberOfMonths(inst),
5393
			showCurrentAtPos = this._get(inst, "showCurrentAtPos"),
5394
			stepMonths = this._get(inst, "stepMonths"),
5395
			isMultiMonth = (numMonths[0] !== 1 || numMonths[1] !== 1),
5396
			currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
5397
				new Date(inst.currentYear, inst.currentMonth, inst.currentDay))),
5398
			minDate = this._getMinMaxDate(inst, "min"),
5399
			maxDate = this._getMinMaxDate(inst, "max"),
5400
			drawMonth = inst.drawMonth - showCurrentAtPos,
5401
			drawYear = inst.drawYear;
5402
5403
		if (drawMonth < 0) {
5404
			drawMonth += 12;
5405
			drawYear--;
5406
		}
5407
		if (maxDate) {
5408
			maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
5409
				maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
5410
			maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
5411
			while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
5412
				drawMonth--;
5413
				if (drawMonth < 0) {
5414
					drawMonth = 11;
5415
					drawYear--;
5416
				}
5417
			}
5418
		}
5419
		inst.drawMonth = drawMonth;
5420
		inst.drawYear = drawYear;
5421
5422
		prevText = this._get(inst, "prevText");
5423
		prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
5424
			this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
5425
			this._getFormatConfig(inst)));
5426
5427
		prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
5428
			"<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click'" +
5429
			" title='" + prevText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w") + "'>" + prevText + "</span></a>" :
5430
			(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>"));
5431
5432
		nextText = this._get(inst, "nextText");
5433
		nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
5434
			this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
5435
			this._getFormatConfig(inst)));
5436
5437
		next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
5438
			"<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click'" +
5439
			" title='" + nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e") + "'>" + nextText + "</span></a>" :
5440
			(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>"));
5441
5442
		currentText = this._get(inst, "currentText");
5443
		gotoDate = (this._get(inst, "gotoCurrent") && inst.currentDay ? currentDate : today);
5444
		currentText = (!navigationAsDateFormat ? currentText :
5445
			this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
5446
5447
		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'>" +
5448
			this._get(inst, "closeText") + "</button>" : "");
5449
5450
		buttonPanel = (showButtonPanel) ? "<div class='ui-datepicker-buttonpane ui-widget-content'>" + (isRTL ? controls : "") +
5451
			(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'" +
5452
			">" + currentText + "</button>" : "") + (isRTL ? "" : controls) + "</div>" : "";
5453
5454
		firstDay = parseInt(this._get(inst, "firstDay"),10);
5455
		firstDay = (isNaN(firstDay) ? 0 : firstDay);
5456
5457
		showWeek = this._get(inst, "showWeek");
5458
		dayNames = this._get(inst, "dayNames");
5459
		dayNamesMin = this._get(inst, "dayNamesMin");
5460
		monthNames = this._get(inst, "monthNames");
5461
		monthNamesShort = this._get(inst, "monthNamesShort");
5462
		beforeShowDay = this._get(inst, "beforeShowDay");
5463
		showOtherMonths = this._get(inst, "showOtherMonths");
5464
		selectOtherMonths = this._get(inst, "selectOtherMonths");
5465
		defaultDate = this._getDefaultDate(inst);
5466
		html = "";
5467
		dow;
5468
		for (row = 0; row < numMonths[0]; row++) {
5469
			group = "";
5470
			this.maxRows = 4;
5471
			for (col = 0; col < numMonths[1]; col++) {
5472
				selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
5473
				cornerClass = " ui-corner-all";
5474
				calender = "";
5475
				if (isMultiMonth) {
5476
					calender += "<div class='ui-datepicker-group";
5477
					if (numMonths[1] > 1) {
5478
						switch (col) {
5479
							case 0: calender += " ui-datepicker-group-first";
5480
								cornerClass = " ui-corner-" + (isRTL ? "right" : "left"); break;
5481
							case numMonths[1]-1: calender += " ui-datepicker-group-last";
5482
								cornerClass = " ui-corner-" + (isRTL ? "left" : "right"); break;
5483
							default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break;
5484
						}
5485
					}
5486
					calender += "'>";
5487
				}
5488
				calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" +
5489
					(/all|left/.test(cornerClass) && row === 0 ? (isRTL ? next : prev) : "") +
5490
					(/all|right/.test(cornerClass) && row === 0 ? (isRTL ? prev : next) : "") +
5491
					this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
5492
					row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
5493
					"</div><table class='ui-datepicker-calendar'><thead>" +
5494
					"<tr>";
5495
				thead = (showWeek ? "<th class='ui-datepicker-week-col'>" + this._get(inst, "weekHeader") + "</th>" : "");
5496
				for (dow = 0; dow < 7; dow++) { // days of the week
5497
					day = (dow + firstDay) % 7;
5498
					thead += "<th scope='col'" + ((dow + firstDay + 6) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "") + ">" +
5499
						"<span title='" + dayNames[day] + "'>" + dayNamesMin[day] + "</span></th>";
5500
				}
5501
				calender += thead + "</tr></thead><tbody>";
5502
				daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
5503
				if (drawYear === inst.selectedYear && drawMonth === inst.selectedMonth) {
5504
					inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
5505
				}
5506
				leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
5507
				curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate
5508
				numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043)
5509
				this.maxRows = numRows;
5510
				printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
5511
				for (dRow = 0; dRow < numRows; dRow++) { // create date picker rows
5512
					calender += "<tr>";
5513
					tbody = (!showWeek ? "" : "<td class='ui-datepicker-week-col'>" +
5514
						this._get(inst, "calculateWeek")(printDate) + "</td>");
5515
					for (dow = 0; dow < 7; dow++) { // create date picker days
5516
						daySettings = (beforeShowDay ?
5517
							beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, ""]);
5518
						otherMonth = (printDate.getMonth() !== drawMonth);
5519
						unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
5520
							(minDate && printDate < minDate) || (maxDate && printDate > maxDate);
5521
						tbody += "<td class='" +
5522
							((dow + firstDay + 6) % 7 >= 5 ? " ui-datepicker-week-end" : "") + // highlight weekends
5523
							(otherMonth ? " ui-datepicker-other-month" : "") + // highlight days from other months
5524
							((printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent) || // user pressed key
5525
							(defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime()) ?
5526
							// or defaultDate is current printedDate and defaultDate is selectedDate
5527
							" " + this._dayOverClass : "") + // highlight selected day
5528
							(unselectable ? " " + this._unselectableClass + " ui-state-disabled": "") +  // highlight unselectable days
5529
							(otherMonth && !showOtherMonths ? "" : " " + daySettings[1] + // highlight custom dates
5530
							(printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "") + // highlight selected day
5531
							(printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "")) + "'" + // highlight today (if different)
5532
							((!otherMonth || showOtherMonths) && daySettings[2] ? " title='" + daySettings[2].replace(/'/g, "&#39;") + "'" : "") + // cell title
5533
							(unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'") + ">" + // actions
5534
							(otherMonth && !showOtherMonths ? "&#xa0;" : // display for other months
5535
							(unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" +
5536
							(printDate.getTime() === today.getTime() ? " ui-state-highlight" : "") +
5537
							(printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "") + // highlight selected day
5538
							(otherMonth ? " ui-priority-secondary" : "") + // distinguish dates from other months
5539
							"' href='#'>" + printDate.getDate() + "</a>")) + "</td>"; // display selectable date
5540
						printDate.setDate(printDate.getDate() + 1);
5541
						printDate = this._daylightSavingAdjust(printDate);
5542
					}
5543
					calender += tbody + "</tr>";
5544
				}
5545
				drawMonth++;
5546
				if (drawMonth > 11) {
5547
					drawMonth = 0;
5548
					drawYear++;
5549
				}
5550
				calender += "</tbody></table>" + (isMultiMonth ? "</div>" +
5551
							((numMonths[0] > 0 && col === numMonths[1]-1) ? "<div class='ui-datepicker-row-break'></div>" : "") : "");
5552
				group += calender;
5553
			}
5554
			html += group;
5555
		}
5556
		html += buttonPanel;
5557
		inst._keyEvent = false;
5558
		return html;
5559
	},
5560
5561
	/* Generate the month and year header. */
5562
	_generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
5563
			secondary, monthNames, monthNamesShort) {
5564
5565
		var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear,
5566
			changeMonth = this._get(inst, "changeMonth"),
5567
			changeYear = this._get(inst, "changeYear"),
5568
			showMonthAfterYear = this._get(inst, "showMonthAfterYear"),
5569
			html = "<div class='ui-datepicker-title'>",
5570
			monthHtml = "";
5571
5572
		// month selection
5573
		if (secondary || !changeMonth) {
5574
			monthHtml += "<span class='ui-datepicker-month'>" + monthNames[drawMonth] + "</span>";
5575
		} else {
5576
			inMinYear = (minDate && minDate.getFullYear() === drawYear);
5577
			inMaxYear = (maxDate && maxDate.getFullYear() === drawYear);
5578
			monthHtml += "<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>";
5579
			for ( month = 0; month < 12; month++) {
5580
				if ((!inMinYear || month >= minDate.getMonth()) && (!inMaxYear || month <= maxDate.getMonth())) {
5581
					monthHtml += "<option value='" + month + "'" +
5582
						(month === drawMonth ? " selected='selected'" : "") +
5583
						">" + monthNamesShort[month] + "</option>";
5584
				}
5585
			}
5586
			monthHtml += "</select>";
5587
		}
5588
5589
		if (!showMonthAfterYear) {
5590
			html += monthHtml + (secondary || !(changeMonth && changeYear) ? "&#xa0;" : "");
5591
		}
5592
5593
		// year selection
5594
		if ( !inst.yearshtml ) {
5595
			inst.yearshtml = "";
5596
			if (secondary || !changeYear) {
5597
				html += "<span class='ui-datepicker-year'>" + drawYear + "</span>";
5598
			} else {
5599
				// determine range of years to display
5600
				years = this._get(inst, "yearRange").split(":");
5601
				thisYear = new Date().getFullYear();
5602
				determineYear = function(value) {
5603
					var year = (value.match(/c[+\-].*/) ? drawYear + parseInt(value.substring(1), 10) :
5604
						(value.match(/[+\-].*/) ? thisYear + parseInt(value, 10) :
5605
						parseInt(value, 10)));
5606
					return (isNaN(year) ? thisYear : year);
5607
				};
5608
				year = determineYear(years[0]);
5609
				endYear = Math.max(year, determineYear(years[1] || ""));
5610
				year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
5611
				endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
5612
				inst.yearshtml += "<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>";
5613
				for (; year <= endYear; year++) {
5614
					inst.yearshtml += "<option value='" + year + "'" +
5615
						(year === drawYear ? " selected='selected'" : "") +
5616
						">" + year + "</option>";
5617
				}
5618
				inst.yearshtml += "</select>";
5619
5620
				html += inst.yearshtml;
5621
				inst.yearshtml = null;
5622
			}
5623
		}
5624
5625
		html += this._get(inst, "yearSuffix");
5626
		if (showMonthAfterYear) {
5627
			html += (secondary || !(changeMonth && changeYear) ? "&#xa0;" : "") + monthHtml;
5628
		}
5629
		html += "</div>"; // Close datepicker_header
5630
		return html;
5631
	},
5632
5633
	/* Adjust one of the date sub-fields. */
5634
	_adjustInstDate: function(inst, offset, period) {
5635
		var year = inst.drawYear + (period === "Y" ? offset : 0),
5636
			month = inst.drawMonth + (period === "M" ? offset : 0),
5637
			day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) + (period === "D" ? offset : 0),
5638
			date = this._restrictMinMax(inst, this._daylightSavingAdjust(new Date(year, month, day)));
5639
5640
		inst.selectedDay = date.getDate();
5641
		inst.drawMonth = inst.selectedMonth = date.getMonth();
5642
		inst.drawYear = inst.selectedYear = date.getFullYear();
5643
		if (period === "M" || period === "Y") {
5644
			this._notifyChange(inst);
5645
		}
5646
	},
5647
5648
	/* Ensure a date is within any min/max bounds. */
5649
	_restrictMinMax: function(inst, date) {
5650
		var minDate = this._getMinMaxDate(inst, "min"),
5651
			maxDate = this._getMinMaxDate(inst, "max"),
5652
			newDate = (minDate && date < minDate ? minDate : date);
5653
		return (maxDate && newDate > maxDate ? maxDate : newDate);
5654
	},
5655
5656
	/* Notify change of month/year. */
5657
	_notifyChange: function(inst) {
5658
		var onChange = this._get(inst, "onChangeMonthYear");
5659
		if (onChange) {
5660
			onChange.apply((inst.input ? inst.input[0] : null),
5661
				[inst.selectedYear, inst.selectedMonth + 1, inst]);
5662
		}
5663
	},
5664
5665
	/* Determine the number of months to show. */
5666
	_getNumberOfMonths: function(inst) {
5667
		var numMonths = this._get(inst, "numberOfMonths");
5668
		return (numMonths == null ? [1, 1] : (typeof numMonths === "number" ? [1, numMonths] : numMonths));
5669
	},
5670
5671
	/* Determine the current maximum date - ensure no time components are set. */
5672
	_getMinMaxDate: function(inst, minMax) {
5673
		return this._determineDate(inst, this._get(inst, minMax + "Date"), null);
5674
	},
5675
5676
	/* Find the number of days in a given month. */
5677
	_getDaysInMonth: function(year, month) {
5678
		return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate();
5679
	},
5680
5681
	/* Find the day of the week of the first of a month. */
5682
	_getFirstDayOfMonth: function(year, month) {
5683
		return new Date(year, month, 1).getDay();
5684
	},
5685
5686
	/* Determines if we should allow a "next/prev" month display change. */
5687
	_canAdjustMonth: function(inst, offset, curYear, curMonth) {
5688
		var numMonths = this._getNumberOfMonths(inst),
5689
			date = this._daylightSavingAdjust(new Date(curYear,
5690
			curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
5691
5692
		if (offset < 0) {
5693
			date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
5694
		}
5695
		return this._isInRange(inst, date);
5696
	},
5697
5698
	/* Is the given date in the accepted range? */
5699
	_isInRange: function(inst, date) {
5700
		var yearSplit, currentYear,
5701
			minDate = this._getMinMaxDate(inst, "min"),
5702
			maxDate = this._getMinMaxDate(inst, "max"),
5703
			minYear = null,
5704
			maxYear = null,
5705
			years = this._get(inst, "yearRange");
5706
			if (years){
5707
				yearSplit = years.split(":");
5708
				currentYear = new Date().getFullYear();
5709
				minYear = parseInt(yearSplit[0], 10);
5710
				maxYear = parseInt(yearSplit[1], 10);
5711
				if ( yearSplit[0].match(/[+\-].*/) ) {
5712
					minYear += currentYear;
5713
				}
5714
				if ( yearSplit[1].match(/[+\-].*/) ) {
5715
					maxYear += currentYear;
5716
				}
5717
			}
5718
5719
		return ((!minDate || date.getTime() >= minDate.getTime()) &&
5720
			(!maxDate || date.getTime() <= maxDate.getTime()) &&
5721
			(!minYear || date.getFullYear() >= minYear) &&
5722
			(!maxYear || date.getFullYear() <= maxYear));
5723
	},
5724
5725
	/* Provide the configuration settings for formatting/parsing. */
5726
	_getFormatConfig: function(inst) {
5727
		var shortYearCutoff = this._get(inst, "shortYearCutoff");
5728
		shortYearCutoff = (typeof shortYearCutoff !== "string" ? shortYearCutoff :
5729
			new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
5730
		return {shortYearCutoff: shortYearCutoff,
5731
			dayNamesShort: this._get(inst, "dayNamesShort"), dayNames: this._get(inst, "dayNames"),
5732
			monthNamesShort: this._get(inst, "monthNamesShort"), monthNames: this._get(inst, "monthNames")};
5733
	},
5734
5735
	/* Format the given date for display. */
5736
	_formatDate: function(inst, day, month, year) {
5737
		if (!day) {
5738
			inst.currentDay = inst.selectedDay;
5739
			inst.currentMonth = inst.selectedMonth;
5740
			inst.currentYear = inst.selectedYear;
5741
		}
5742
		var date = (day ? (typeof day === "object" ? day :
5743
			this._daylightSavingAdjust(new Date(year, month, day))) :
5744
			this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
5745
		return this.formatDate(this._get(inst, "dateFormat"), date, this._getFormatConfig(inst));
5746
	}
5747
});
5748
5749
/*
5750
 * Bind hover events for datepicker elements.
5751
 * Done via delegate so the binding only occurs once in the lifetime of the parent div.
5752
 * Global datepicker_instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
5753
 */
5754
function datepicker_bindHover(dpDiv) {
5755
	var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";
5756
	return dpDiv.delegate(selector, "mouseout", function() {
5757
			$(this).removeClass("ui-state-hover");
5758
			if (this.className.indexOf("ui-datepicker-prev") !== -1) {
5759
				$(this).removeClass("ui-datepicker-prev-hover");
5760
			}
5761
			if (this.className.indexOf("ui-datepicker-next") !== -1) {
5762
				$(this).removeClass("ui-datepicker-next-hover");
5763
			}
5764
		})
5765
		.delegate( selector, "mouseover", datepicker_handleMouseover );
5766
}
5767
5768
function datepicker_handleMouseover() {
5769
	if (!$.datepicker._isDisabledDatepicker( datepicker_instActive.inline? datepicker_instActive.dpDiv.parent()[0] : datepicker_instActive.input[0])) {
5770
		$(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover");
5771
		$(this).addClass("ui-state-hover");
5772
		if (this.className.indexOf("ui-datepicker-prev") !== -1) {
5773
			$(this).addClass("ui-datepicker-prev-hover");
5774
		}
5775
		if (this.className.indexOf("ui-datepicker-next") !== -1) {
5776
			$(this).addClass("ui-datepicker-next-hover");
5777
		}
5778
	}
5779
}
5780
5781
/* jQuery extend now ignores nulls! */
5782
function datepicker_extendRemove(target, props) {
5783
	$.extend(target, props);
5784
	for (var name in props) {
5785
		if (props[name] == null) {
5786
			target[name] = props[name];
5787
		}
5788
	}
5789
	return target;
5790
}
5791
5792
/* Invoke the datepicker functionality.
5793
   @param  options  string - a command, optionally followed by additional parameters or
5794
					Object - settings for attaching new datepicker functionality
5795
   @return  jQuery object */
5796
$.fn.datepicker = function(options){
5797
5798
	/* Verify an empty collection wasn't passed - Fixes #6976 */
5799
	if ( !this.length ) {
5800
		return this;
5801
	}
5802
5803
	/* Initialise the date picker. */
5804
	if (!$.datepicker.initialized) {
5805
		$(document).mousedown($.datepicker._checkExternalClick);
5806
		$.datepicker.initialized = true;
5807
	}
5808
5809
	/* Append datepicker main container to body if not exist. */
5810
	if ($("#"+$.datepicker._mainDivId).length === 0) {
5811
		$("body").append($.datepicker.dpDiv);
5812
	}
5813
5814
	var otherArgs = Array.prototype.slice.call(arguments, 1);
5815
	if (typeof options === "string" && (options === "isDisabled" || options === "getDate" || options === "widget")) {
5816
		return $.datepicker["_" + options + "Datepicker"].
5817
			apply($.datepicker, [this[0]].concat(otherArgs));
5818
	}
5819
	if (options === "option" && arguments.length === 2 && typeof arguments[1] === "string") {
5820
		return $.datepicker["_" + options + "Datepicker"].
5821
			apply($.datepicker, [this[0]].concat(otherArgs));
5822
	}
5823
	return this.each(function() {
5824
		typeof options === "string" ?
5825
			$.datepicker["_" + options + "Datepicker"].
5826
				apply($.datepicker, [this].concat(otherArgs)) :
5827
			$.datepicker._attachDatepicker(this, options);
5828
	});
5829
};
5830
5831
$.datepicker = new Datepicker(); // singleton instance
5832
$.datepicker.initialized = false;
5833
$.datepicker.uuid = new Date().getTime();
5834
$.datepicker.version = "1.11.4";
5835
5836
var datepicker = $.datepicker;
5837
5838
5839
/*!
5840
 * jQuery UI Draggable 1.11.4
5841
 * http://jqueryui.com
5842
 *
5843
 * Copyright jQuery Foundation and other contributors
5844
 * Released under the MIT license.
5845
 * http://jquery.org/license
5846
 *
5847
 * http://api.jqueryui.com/draggable/
5848
 */
5849
5850
5851
$.widget("ui.draggable", $.ui.mouse, {
5852
	version: "1.11.4",
5853
	widgetEventPrefix: "drag",
5854
	options: {
5855
		addClasses: true,
5856
		appendTo: "parent",
5857
		axis: false,
5858
		connectToSortable: false,
5859
		containment: false,
5860
		cursor: "auto",
5861
		cursorAt: false,
5862
		grid: false,
5863
		handle: false,
5864
		helper: "original",
5865
		iframeFix: false,
5866
		opacity: false,
5867
		refreshPositions: false,
5868
		revert: false,
5869
		revertDuration: 500,
5870
		scope: "default",
5871
		scroll: true,
5872
		scrollSensitivity: 20,
5873
		scrollSpeed: 20,
5874
		snap: false,
5875
		snapMode: "both",
5876
		snapTolerance: 20,
5877
		stack: false,
5878
		zIndex: false,
5879
5880
		// callbacks
5881
		drag: null,
5882
		start: null,
5883
		stop: null
5884
	},
5885
	_create: function() {
5886
5887
		if ( this.options.helper === "original" ) {
5888
			this._setPositionRelative();
5889
		}
5890
		if (this.options.addClasses){
5891
			this.element.addClass("ui-draggable");
5892
		}
5893
		if (this.options.disabled){
5894
			this.element.addClass("ui-draggable-disabled");
5895
		}
5896
		this._setHandleClassName();
5897
5898
		this._mouseInit();
5899
	},
5900
5901
	_setOption: function( key, value ) {
5902
		this._super( key, value );
5903
		if ( key === "handle" ) {
5904
			this._removeHandleClassName();
5905
			this._setHandleClassName();
5906
		}
5907
	},
5908
5909
	_destroy: function() {
5910
		if ( ( this.helper || this.element ).is( ".ui-draggable-dragging" ) ) {
5911
			this.destroyOnClear = true;
5912
			return;
5913
		}
5914
		this.element.removeClass( "ui-draggable ui-draggable-dragging ui-draggable-disabled" );
5915
		this._removeHandleClassName();
5916
		this._mouseDestroy();
5917
	},
5918
5919
	_mouseCapture: function(event) {
5920
		var o = this.options;
5921
5922
		this._blurActiveElement( event );
5923
5924
		// among others, prevent a drag on a resizable-handle
5925
		if (this.helper || o.disabled || $(event.target).closest(".ui-resizable-handle").length > 0) {
5926
			return false;
5927
		}
5928
5929
		//Quit if we're not on a valid handle
5930
		this.handle = this._getHandle(event);
5931
		if (!this.handle) {
5932
			return false;
5933
		}
5934
5935
		this._blockFrames( o.iframeFix === true ? "iframe" : o.iframeFix );
5936
5937
		return true;
5938
5939
	},
5940
5941
	_blockFrames: function( selector ) {
5942
		this.iframeBlocks = this.document.find( selector ).map(function() {
5943
			var iframe = $( this );
5944
5945
			return $( "<div>" )
5946
				.css( "position", "absolute" )
5947
				.appendTo( iframe.parent() )
5948
				.outerWidth( iframe.outerWidth() )
5949
				.outerHeight( iframe.outerHeight() )
5950
				.offset( iframe.offset() )[ 0 ];
5951
		});
5952
	},
5953
5954
	_unblockFrames: function() {
5955
		if ( this.iframeBlocks ) {
5956
			this.iframeBlocks.remove();
5957
			delete this.iframeBlocks;
5958
		}
5959
	},
5960
5961
	_blurActiveElement: function( event ) {
5962
		var document = this.document[ 0 ];
5963
5964
		// Only need to blur if the event occurred on the draggable itself, see #10527
5965
		if ( !this.handleElement.is( event.target ) ) {
5966
			return;
5967
		}
5968
5969
		// support: IE9
5970
		// IE9 throws an "Unspecified error" accessing document.activeElement from an <iframe>
5971
		try {
5972
5973
			// Support: IE9, IE10
5974
			// If the <body> is blurred, IE will switch windows, see #9520
5975
			if ( document.activeElement && document.activeElement.nodeName.toLowerCase() !== "body" ) {
5976
5977
				// Blur any element that currently has focus, see #4261
5978
				$( document.activeElement ).blur();
5979
			}
5980
		} catch ( error ) {}
5981
	},
5982
5983
	_mouseStart: function(event) {
5984
5985
		var o = this.options;
5986
5987
		//Create and append the visible helper
5988
		this.helper = this._createHelper(event);
5989
5990
		this.helper.addClass("ui-draggable-dragging");
5991
5992
		//Cache the helper size
5993
		this._cacheHelperProportions();
5994
5995
		//If ddmanager is used for droppables, set the global draggable
5996
		if ($.ui.ddmanager) {
5997
			$.ui.ddmanager.current = this;
5998
		}
5999
6000
		/*
6001
		 * - Position generation -
6002
		 * This block generates everything position related - it's the core of draggables.
6003
		 */
6004
6005
		//Cache the margins of the original element
6006
		this._cacheMargins();
6007
6008
		//Store the helper's css position
6009
		this.cssPosition = this.helper.css( "position" );
6010
		this.scrollParent = this.helper.scrollParent( true );
6011
		this.offsetParent = this.helper.offsetParent();
6012
		this.hasFixedAncestor = this.helper.parents().filter(function() {
6013
				return $( this ).css( "position" ) === "fixed";
6014
			}).length > 0;
6015
6016
		//The element's absolute position on the page minus margins
6017
		this.positionAbs = this.element.offset();
6018
		this._refreshOffsets( event );
6019
6020
		//Generate the original position
6021
		this.originalPosition = this.position = this._generatePosition( event, false );
6022
		this.originalPageX = event.pageX;
6023
		this.originalPageY = event.pageY;
6024
6025
		//Adjust the mouse offset relative to the helper if "cursorAt" is supplied
6026
		(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
6027
6028
		//Set a containment if given in the options
6029
		this._setContainment();
6030
6031
		//Trigger event + callbacks
6032
		if (this._trigger("start", event) === false) {
6033
			this._clear();
6034
			return false;
6035
		}
6036
6037
		//Recache the helper size
6038
		this._cacheHelperProportions();
6039
6040
		//Prepare the droppable offsets
6041
		if ($.ui.ddmanager && !o.dropBehaviour) {
6042
			$.ui.ddmanager.prepareOffsets(this, event);
6043
		}
6044
6045
		// Reset helper's right/bottom css if they're set and set explicit width/height instead
6046
		// as this prevents resizing of elements with right/bottom set (see #7772)
6047
		this._normalizeRightBottom();
6048
6049
		this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
6050
6051
		//If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003)
6052
		if ( $.ui.ddmanager ) {
6053
			$.ui.ddmanager.dragStart(this, event);
6054
		}
6055
6056
		return true;
6057
	},
6058
6059
	_refreshOffsets: function( event ) {
6060
		this.offset = {
6061
			top: this.positionAbs.top - this.margins.top,
6062
			left: this.positionAbs.left - this.margins.left,
6063
			scroll: false,
6064
			parent: this._getParentOffset(),
6065
			relative: this._getRelativeOffset()
6066
		};
6067
6068
		this.offset.click = {
6069
			left: event.pageX - this.offset.left,
6070
			top: event.pageY - this.offset.top
6071
		};
6072
	},
6073
6074
	_mouseDrag: function(event, noPropagation) {
6075
		// reset any necessary cached properties (see #5009)
6076
		if ( this.hasFixedAncestor ) {
6077
			this.offset.parent = this._getParentOffset();
6078
		}
6079
6080
		//Compute the helpers position
6081
		this.position = this._generatePosition( event, true );
6082
		this.positionAbs = this._convertPositionTo("absolute");
6083
6084
		//Call plugins and callbacks and use the resulting position if something is returned
6085
		if (!noPropagation) {
6086
			var ui = this._uiHash();
6087
			if (this._trigger("drag", event, ui) === false) {
6088
				this._mouseUp({});
6089
				return false;
6090
			}
6091
			this.position = ui.position;
6092
		}
6093
6094
		this.helper[ 0 ].style.left = this.position.left + "px";
6095
		this.helper[ 0 ].style.top = this.position.top + "px";
6096
6097
		if ($.ui.ddmanager) {
6098
			$.ui.ddmanager.drag(this, event);
6099
		}
6100
6101
		return false;
6102
	},
6103
6104
	_mouseStop: function(event) {
6105
6106
		//If we are using droppables, inform the manager about the drop
6107
		var that = this,
6108
			dropped = false;
6109
		if ($.ui.ddmanager && !this.options.dropBehaviour) {
6110
			dropped = $.ui.ddmanager.drop(this, event);
6111
		}
6112
6113
		//if a drop comes from outside (a sortable)
6114
		if (this.dropped) {
6115
			dropped = this.dropped;
6116
			this.dropped = false;
6117
		}
6118
6119
		if ((this.options.revert === "invalid" && !dropped) || (this.options.revert === "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) {
6120
			$(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
6121
				if (that._trigger("stop", event) !== false) {
6122
					that._clear();
6123
				}
6124
			});
6125
		} else {
6126
			if (this._trigger("stop", event) !== false) {
6127
				this._clear();
6128
			}
6129
		}
6130
6131
		return false;
6132
	},
6133
6134
	_mouseUp: function( event ) {
6135
		this._unblockFrames();
6136
6137
		//If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003)
6138
		if ( $.ui.ddmanager ) {
6139
			$.ui.ddmanager.dragStop(this, event);
6140
		}
6141
6142
		// Only need to focus if the event occurred on the draggable itself, see #10527
6143
		if ( this.handleElement.is( event.target ) ) {
6144
			// The interaction is over; whether or not the click resulted in a drag, focus the element
6145
			this.element.focus();
6146
		}
6147
6148
		return $.ui.mouse.prototype._mouseUp.call(this, event);
6149
	},
6150
6151
	cancel: function() {
6152
6153
		if (this.helper.is(".ui-draggable-dragging")) {
6154
			this._mouseUp({});
6155
		} else {
6156
			this._clear();
6157
		}
6158
6159
		return this;
6160
6161
	},
6162
6163
	_getHandle: function(event) {
6164
		return this.options.handle ?
6165
			!!$( event.target ).closest( this.element.find( this.options.handle ) ).length :
6166
			true;
6167
	},
6168
6169
	_setHandleClassName: function() {
6170
		this.handleElement = this.options.handle ?
6171
			this.element.find( this.options.handle ) : this.element;
6172
		this.handleElement.addClass( "ui-draggable-handle" );
6173
	},
6174
6175
	_removeHandleClassName: function() {
6176
		this.handleElement.removeClass( "ui-draggable-handle" );
6177
	},
6178
6179
	_createHelper: function(event) {
6180
6181
		var o = this.options,
6182
			helperIsFunction = $.isFunction( o.helper ),
6183
			helper = helperIsFunction ?
6184
				$( o.helper.apply( this.element[ 0 ], [ event ] ) ) :
6185
				( o.helper === "clone" ?
6186
					this.element.clone().removeAttr( "id" ) :
6187
					this.element );
6188
6189
		if (!helper.parents("body").length) {
6190
			helper.appendTo((o.appendTo === "parent" ? this.element[0].parentNode : o.appendTo));
6191
		}
6192
6193
		// http://bugs.jqueryui.com/ticket/9446
6194
		// a helper function can return the original element
6195
		// which wouldn't have been set to relative in _create
6196
		if ( helperIsFunction && helper[ 0 ] === this.element[ 0 ] ) {
6197
			this._setPositionRelative();
6198
		}
6199
6200
		if (helper[0] !== this.element[0] && !(/(fixed|absolute)/).test(helper.css("position"))) {
6201
			helper.css("position", "absolute");
6202
		}
6203
6204
		return helper;
6205
6206
	},
6207
6208
	_setPositionRelative: function() {
6209
		if ( !( /^(?:r|a|f)/ ).test( this.element.css( "position" ) ) ) {
6210
			this.element[ 0 ].style.position = "relative";
6211
		}
6212
	},
6213
6214
	_adjustOffsetFromHelper: function(obj) {
6215
		if (typeof obj === "string") {
6216
			obj = obj.split(" ");
6217
		}
6218
		if ($.isArray(obj)) {
6219
			obj = { left: +obj[0], top: +obj[1] || 0 };
6220
		}
6221
		if ("left" in obj) {
6222
			this.offset.click.left = obj.left + this.margins.left;
6223
		}
6224
		if ("right" in obj) {
6225
			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
6226
		}
6227
		if ("top" in obj) {
6228
			this.offset.click.top = obj.top + this.margins.top;
6229
		}
6230
		if ("bottom" in obj) {
6231
			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
6232
		}
6233
	},
6234
6235
	_isRootNode: function( element ) {
6236
		return ( /(html|body)/i ).test( element.tagName ) || element === this.document[ 0 ];
6237
	},
6238
6239
	_getParentOffset: function() {
6240
6241
		//Get the offsetParent and cache its position
6242
		var po = this.offsetParent.offset(),
6243
			document = this.document[ 0 ];
6244
6245
		// This is a special case where we need to modify a offset calculated on start, since the following happened:
6246
		// 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
6247
		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
6248
		//    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
6249
		if (this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) {
6250
			po.left += this.scrollParent.scrollLeft();
6251
			po.top += this.scrollParent.scrollTop();
6252
		}
6253
6254
		if ( this._isRootNode( this.offsetParent[ 0 ] ) ) {
6255
			po = { top: 0, left: 0 };
6256
		}
6257
6258
		return {
6259
			top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"), 10) || 0),
6260
			left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"), 10) || 0)
6261
		};
6262
6263
	},
6264
6265
	_getRelativeOffset: function() {
6266
		if ( this.cssPosition !== "relative" ) {
6267
			return { top: 0, left: 0 };
6268
		}
6269
6270
		var p = this.element.position(),
6271
			scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );
6272
6273
		return {
6274
			top: p.top - ( parseInt(this.helper.css( "top" ), 10) || 0 ) + ( !scrollIsRootNode ? this.scrollParent.scrollTop() : 0 ),
6275
			left: p.left - ( parseInt(this.helper.css( "left" ), 10) || 0 ) + ( !scrollIsRootNode ? this.scrollParent.scrollLeft() : 0 )
6276
		};
6277
6278
	},
6279
6280
	_cacheMargins: function() {
6281
		this.margins = {
6282
			left: (parseInt(this.element.css("marginLeft"), 10) || 0),
6283
			top: (parseInt(this.element.css("marginTop"), 10) || 0),
6284
			right: (parseInt(this.element.css("marginRight"), 10) || 0),
6285
			bottom: (parseInt(this.element.css("marginBottom"), 10) || 0)
6286
		};
6287
	},
6288
6289
	_cacheHelperProportions: function() {
6290
		this.helperProportions = {
6291
			width: this.helper.outerWidth(),
6292
			height: this.helper.outerHeight()
6293
		};
6294
	},
6295
6296
	_setContainment: function() {
6297
6298
		var isUserScrollable, c, ce,
6299
			o = this.options,
6300
			document = this.document[ 0 ];
6301
6302
		this.relativeContainer = null;
6303
6304
		if ( !o.containment ) {
6305
			this.containment = null;
6306
			return;
6307
		}
6308
6309
		if ( o.containment === "window" ) {
6310
			this.containment = [
6311
				$( window ).scrollLeft() - this.offset.relative.left - this.offset.parent.left,
6312
				$( window ).scrollTop() - this.offset.relative.top - this.offset.parent.top,
6313
				$( window ).scrollLeft() + $( window ).width() - this.helperProportions.width - this.margins.left,
6314
				$( window ).scrollTop() + ( $( window ).height() || document.body.parentNode.scrollHeight ) - this.helperProportions.height - this.margins.top
6315
			];
6316
			return;
6317
		}
6318
6319
		if ( o.containment === "document") {
6320
			this.containment = [
6321
				0,
6322
				0,
6323
				$( document ).width() - this.helperProportions.width - this.margins.left,
6324
				( $( document ).height() || document.body.parentNode.scrollHeight ) - this.helperProportions.height - this.margins.top
6325
			];
6326
			return;
6327
		}
6328
6329
		if ( o.containment.constructor === Array ) {
6330
			this.containment = o.containment;
6331
			return;
6332
		}
6333
6334
		if ( o.containment === "parent" ) {
6335
			o.containment = this.helper[ 0 ].parentNode;
6336
		}
6337
6338
		c = $( o.containment );
6339
		ce = c[ 0 ];
6340
6341
		if ( !ce ) {
6342
			return;
6343
		}
6344
6345
		isUserScrollable = /(scroll|auto)/.test( c.css( "overflow" ) );
6346
6347
		this.containment = [
6348
			( parseInt( c.css( "borderLeftWidth" ), 10 ) || 0 ) + ( parseInt( c.css( "paddingLeft" ), 10 ) || 0 ),
6349
			( parseInt( c.css( "borderTopWidth" ), 10 ) || 0 ) + ( parseInt( c.css( "paddingTop" ), 10 ) || 0 ),
6350
			( isUserScrollable ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) -
6351
				( parseInt( c.css( "borderRightWidth" ), 10 ) || 0 ) -
6352
				( parseInt( c.css( "paddingRight" ), 10 ) || 0 ) -
6353
				this.helperProportions.width -
6354
				this.margins.left -
6355
				this.margins.right,
6356
			( isUserScrollable ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) -
6357
				( parseInt( c.css( "borderBottomWidth" ), 10 ) || 0 ) -
6358
				( parseInt( c.css( "paddingBottom" ), 10 ) || 0 ) -
6359
				this.helperProportions.height -
6360
				this.margins.top -
6361
				this.margins.bottom
6362
		];
6363
		this.relativeContainer = c;
6364
	},
6365
6366
	_convertPositionTo: function(d, pos) {
6367
6368
		if (!pos) {
6369
			pos = this.position;
6370
		}
6371
6372
		var mod = d === "absolute" ? 1 : -1,
6373
			scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );
6374
6375
		return {
6376
			top: (
6377
				pos.top	+																// The absolute mouse position
6378
				this.offset.relative.top * mod +										// Only for relative positioned nodes: Relative offset from element to offset parent
6379
				this.offset.parent.top * mod -										// The offsetParent's offset without borders (offset + border)
6380
				( ( this.cssPosition === "fixed" ? -this.offset.scroll.top : ( scrollIsRootNode ? 0 : this.offset.scroll.top ) ) * mod)
6381
			),
6382
			left: (
6383
				pos.left +																// The absolute mouse position
6384
				this.offset.relative.left * mod +										// Only for relative positioned nodes: Relative offset from element to offset parent
6385
				this.offset.parent.left * mod	-										// The offsetParent's offset without borders (offset + border)
6386
				( ( this.cssPosition === "fixed" ? -this.offset.scroll.left : ( scrollIsRootNode ? 0 : this.offset.scroll.left ) ) * mod)
6387
			)
6388
		};
6389
6390
	},
6391
6392
	_generatePosition: function( event, constrainPosition ) {
6393
6394
		var containment, co, top, left,
6395
			o = this.options,
6396
			scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ),
6397
			pageX = event.pageX,
6398
			pageY = event.pageY;
6399
6400
		// Cache the scroll
6401
		if ( !scrollIsRootNode || !this.offset.scroll ) {
6402
			this.offset.scroll = {
6403
				top: this.scrollParent.scrollTop(),
6404
				left: this.scrollParent.scrollLeft()
6405
			};
6406
		}
6407
6408
		/*
6409
		 * - Position constraining -
6410
		 * Constrain the position to a mix of grid, containment.
6411
		 */
6412
6413
		// If we are not dragging yet, we won't check for options
6414
		if ( constrainPosition ) {
6415
			if ( this.containment ) {
6416
				if ( this.relativeContainer ){
6417
					co = this.relativeContainer.offset();
6418
					containment = [
6419
						this.containment[ 0 ] + co.left,
6420
						this.containment[ 1 ] + co.top,
6421
						this.containment[ 2 ] + co.left,
6422
						this.containment[ 3 ] + co.top
6423
					];
6424
				} else {
6425
					containment = this.containment;
6426
				}
6427
6428
				if (event.pageX - this.offset.click.left < containment[0]) {
6429
					pageX = containment[0] + this.offset.click.left;
6430
				}
6431
				if (event.pageY - this.offset.click.top < containment[1]) {
6432
					pageY = containment[1] + this.offset.click.top;
6433
				}
6434
				if (event.pageX - this.offset.click.left > containment[2]) {
6435
					pageX = containment[2] + this.offset.click.left;
6436
				}
6437
				if (event.pageY - this.offset.click.top > containment[3]) {
6438
					pageY = containment[3] + this.offset.click.top;
6439
				}
6440
			}
6441
6442
			if (o.grid) {
6443
				//Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950)
6444
				top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY;
6445
				pageY = containment ? ((top - this.offset.click.top >= containment[1] || top - this.offset.click.top > containment[3]) ? top : ((top - this.offset.click.top >= containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
6446
6447
				left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX;
6448
				pageX = containment ? ((left - this.offset.click.left >= containment[0] || left - this.offset.click.left > containment[2]) ? left : ((left - this.offset.click.left >= containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
6449
			}
6450
6451
			if ( o.axis === "y" ) {
6452
				pageX = this.originalPageX;
6453
			}
6454
6455
			if ( o.axis === "x" ) {
6456
				pageY = this.originalPageY;
6457
			}
6458
		}
6459
6460
		return {
6461
			top: (
6462
				pageY -																	// The absolute mouse position
6463
				this.offset.click.top	-												// Click offset (relative to the element)
6464
				this.offset.relative.top -												// Only for relative positioned nodes: Relative offset from element to offset parent
6465
				this.offset.parent.top +												// The offsetParent's offset without borders (offset + border)
6466
				( this.cssPosition === "fixed" ? -this.offset.scroll.top : ( scrollIsRootNode ? 0 : this.offset.scroll.top ) )
6467
			),
6468
			left: (
6469
				pageX -																	// The absolute mouse position
6470
				this.offset.click.left -												// Click offset (relative to the element)
6471
				this.offset.relative.left -												// Only for relative positioned nodes: Relative offset from element to offset parent
6472
				this.offset.parent.left +												// The offsetParent's offset without borders (offset + border)
6473
				( this.cssPosition === "fixed" ? -this.offset.scroll.left : ( scrollIsRootNode ? 0 : this.offset.scroll.left ) )
6474
			)
6475
		};
6476
6477
	},
6478
6479
	_clear: function() {
6480
		this.helper.removeClass("ui-draggable-dragging");
6481
		if (this.helper[0] !== this.element[0] && !this.cancelHelperRemoval) {
6482
			this.helper.remove();
6483
		}
6484
		this.helper = null;
6485
		this.cancelHelperRemoval = false;
6486
		if ( this.destroyOnClear ) {
6487
			this.destroy();
6488
		}
6489
	},
6490
6491
	_normalizeRightBottom: function() {
6492
		if ( this.options.axis !== "y" && this.helper.css( "right" ) !== "auto" ) {
6493
			this.helper.width( this.helper.width() );
6494
			this.helper.css( "right", "auto" );
6495
		}
6496
		if ( this.options.axis !== "x" && this.helper.css( "bottom" ) !== "auto" ) {
6497
			this.helper.height( this.helper.height() );
6498
			this.helper.css( "bottom", "auto" );
6499
		}
6500
	},
6501
6502
	// From now on bulk stuff - mainly helpers
6503
6504
	_trigger: function( type, event, ui ) {
6505
		ui = ui || this._uiHash();
6506
		$.ui.plugin.call( this, type, [ event, ui, this ], true );
6507
6508
		// Absolute position and offset (see #6884 ) have to be recalculated after plugins
6509
		if ( /^(drag|start|stop)/.test( type ) ) {
6510
			this.positionAbs = this._convertPositionTo( "absolute" );
6511
			ui.offset = this.positionAbs;
6512
		}
6513
		return $.Widget.prototype._trigger.call( this, type, event, ui );
6514
	},
6515
6516
	plugins: {},
6517
6518
	_uiHash: function() {
6519
		return {
6520
			helper: this.helper,
6521
			position: this.position,
6522
			originalPosition: this.originalPosition,
6523
			offset: this.positionAbs
6524
		};
6525
	}
6526
6527
});
6528
6529
$.ui.plugin.add( "draggable", "connectToSortable", {
6530
	start: function( event, ui, draggable ) {
6531
		var uiSortable = $.extend( {}, ui, {
6532
			item: draggable.element
6533
		});
6534
6535
		draggable.sortables = [];
6536
		$( draggable.options.connectToSortable ).each(function() {
6537
			var sortable = $( this ).sortable( "instance" );
6538
6539
			if ( sortable && !sortable.options.disabled ) {
6540
				draggable.sortables.push( sortable );
6541
6542
				// refreshPositions is called at drag start to refresh the containerCache
6543
				// which is used in drag. This ensures it's initialized and synchronized
6544
				// with any changes that might have happened on the page since initialization.
6545
				sortable.refreshPositions();
6546
				sortable._trigger("activate", event, uiSortable);
6547
			}
6548
		});
6549
	},
6550
	stop: function( event, ui, draggable ) {
6551
		var uiSortable = $.extend( {}, ui, {
6552
			item: draggable.element
6553
		});
6554
6555
		draggable.cancelHelperRemoval = false;
6556
6557
		$.each( draggable.sortables, function() {
6558
			var sortable = this;
6559
6560
			if ( sortable.isOver ) {
6561
				sortable.isOver = 0;
6562
6563
				// Allow this sortable to handle removing the helper
6564
				draggable.cancelHelperRemoval = true;
6565
				sortable.cancelHelperRemoval = false;
6566
6567
				// Use _storedCSS To restore properties in the sortable,
6568
				// as this also handles revert (#9675) since the draggable
6569
				// may have modified them in unexpected ways (#8809)
6570
				sortable._storedCSS = {
6571
					position: sortable.placeholder.css( "position" ),
6572
					top: sortable.placeholder.css( "top" ),
6573
					left: sortable.placeholder.css( "left" )
6574
				};
6575
6576
				sortable._mouseStop(event);
6577
6578
				// Once drag has ended, the sortable should return to using
6579
				// its original helper, not the shared helper from draggable
6580
				sortable.options.helper = sortable.options._helper;
6581
			} else {
6582
				// Prevent this Sortable from removing the helper.
6583
				// However, don't set the draggable to remove the helper
6584
				// either as another connected Sortable may yet handle the removal.
6585
				sortable.cancelHelperRemoval = true;
6586
6587
				sortable._trigger( "deactivate", event, uiSortable );
6588
			}
6589
		});
6590
	},
6591
	drag: function( event, ui, draggable ) {
6592
		$.each( draggable.sortables, function() {
6593
			var innermostIntersecting = false,
6594
				sortable = this;
6595
6596
			// Copy over variables that sortable's _intersectsWith uses
6597
			sortable.positionAbs = draggable.positionAbs;
6598
			sortable.helperProportions = draggable.helperProportions;
6599
			sortable.offset.click = draggable.offset.click;
6600
6601
			if ( sortable._intersectsWith( sortable.containerCache ) ) {
6602
				innermostIntersecting = true;
6603
6604
				$.each( draggable.sortables, function() {
6605
					// Copy over variables that sortable's _intersectsWith uses
6606
					this.positionAbs = draggable.positionAbs;
6607
					this.helperProportions = draggable.helperProportions;
6608
					this.offset.click = draggable.offset.click;
6609
6610
					if ( this !== sortable &&
6611
							this._intersectsWith( this.containerCache ) &&
6612
							$.contains( sortable.element[ 0 ], this.element[ 0 ] ) ) {
6613
						innermostIntersecting = false;
6614
					}
6615
6616
					return innermostIntersecting;
6617
				});
6618
			}
6619
6620
			if ( innermostIntersecting ) {
6621
				// If it intersects, we use a little isOver variable and set it once,
6622
				// so that the move-in stuff gets fired only once.
6623
				if ( !sortable.isOver ) {
6624
					sortable.isOver = 1;
6625
6626
					// Store draggable's parent in case we need to reappend to it later.
6627
					draggable._parent = ui.helper.parent();
6628
6629
					sortable.currentItem = ui.helper
6630
						.appendTo( sortable.element )
6631
						.data( "ui-sortable-item", true );
6632
6633
					// Store helper option to later restore it
6634
					sortable.options._helper = sortable.options.helper;
6635
6636
					sortable.options.helper = function() {
6637
						return ui.helper[ 0 ];
6638
					};
6639
6640
					// Fire the start events of the sortable with our passed browser event,
6641
					// and our own helper (so it doesn't create a new one)
6642
					event.target = sortable.currentItem[ 0 ];
6643
					sortable._mouseCapture( event, true );
6644
					sortable._mouseStart( event, true, true );
6645
6646
					// Because the browser event is way off the new appended portlet,
6647
					// modify necessary variables to reflect the changes
6648
					sortable.offset.click.top = draggable.offset.click.top;
6649
					sortable.offset.click.left = draggable.offset.click.left;
6650
					sortable.offset.parent.left -= draggable.offset.parent.left -
6651
						sortable.offset.parent.left;
6652
					sortable.offset.parent.top -= draggable.offset.parent.top -
6653
						sortable.offset.parent.top;
6654
6655
					draggable._trigger( "toSortable", event );
6656
6657
					// Inform draggable that the helper is in a valid drop zone,
6658
					// used solely in the revert option to handle "valid/invalid".
6659
					draggable.dropped = sortable.element;
6660
6661
					// Need to refreshPositions of all sortables in the case that
6662
					// adding to one sortable changes the location of the other sortables (#9675)
6663
					$.each( draggable.sortables, function() {
6664
						this.refreshPositions();
6665
					});
6666
6667
					// hack so receive/update callbacks work (mostly)
6668
					draggable.currentItem = draggable.element;
6669
					sortable.fromOutside = draggable;
6670
				}
6671
6672
				if ( sortable.currentItem ) {
6673
					sortable._mouseDrag( event );
6674
					// Copy the sortable's position because the draggable's can potentially reflect
6675
					// a relative position, while sortable is always absolute, which the dragged
6676
					// element has now become. (#8809)
6677
					ui.position = sortable.position;
6678
				}
6679
			} else {
6680
				// If it doesn't intersect with the sortable, and it intersected before,
6681
				// we fake the drag stop of the sortable, but make sure it doesn't remove
6682
				// the helper by using cancelHelperRemoval.
6683
				if ( sortable.isOver ) {
6684
6685
					sortable.isOver = 0;
6686
					sortable.cancelHelperRemoval = true;
6687
6688
					// Calling sortable's mouseStop would trigger a revert,
6689
					// so revert must be temporarily false until after mouseStop is called.
6690
					sortable.options._revert = sortable.options.revert;
6691
					sortable.options.revert = false;
6692
6693
					sortable._trigger( "out", event, sortable._uiHash( sortable ) );
6694
					sortable._mouseStop( event, true );
6695
6696
					// restore sortable behaviors that were modfied
6697
					// when the draggable entered the sortable area (#9481)
6698
					sortable.options.revert = sortable.options._revert;
6699
					sortable.options.helper = sortable.options._helper;
6700
6701
					if ( sortable.placeholder ) {
6702
						sortable.placeholder.remove();
6703
					}
6704
6705
					// Restore and recalculate the draggable's offset considering the sortable
6706
					// may have modified them in unexpected ways. (#8809, #10669)
6707
					ui.helper.appendTo( draggable._parent );
6708
					draggable._refreshOffsets( event );
6709
					ui.position = draggable._generatePosition( event, true );
6710
6711
					draggable._trigger( "fromSortable", event );
6712
6713
					// Inform draggable that the helper is no longer in a valid drop zone
6714
					draggable.dropped = false;
6715
6716
					// Need to refreshPositions of all sortables just in case removing
6717
					// from one sortable changes the location of other sortables (#9675)
6718
					$.each( draggable.sortables, function() {
6719
						this.refreshPositions();
6720
					});
6721
				}
6722
			}
6723
		});
6724
	}
6725
});
6726
6727
$.ui.plugin.add("draggable", "cursor", {
6728
	start: function( event, ui, instance ) {
6729
		var t = $( "body" ),
6730
			o = instance.options;
6731
6732
		if (t.css("cursor")) {
6733
			o._cursor = t.css("cursor");
6734
		}
6735
		t.css("cursor", o.cursor);
6736
	},
6737
	stop: function( event, ui, instance ) {
6738
		var o = instance.options;
6739
		if (o._cursor) {
6740
			$("body").css("cursor", o._cursor);
6741
		}
6742
	}
6743
});
6744
6745
$.ui.plugin.add("draggable", "opacity", {
6746
	start: function( event, ui, instance ) {
6747
		var t = $( ui.helper ),
6748
			o = instance.options;
6749
		if (t.css("opacity")) {
6750
			o._opacity = t.css("opacity");
6751
		}
6752
		t.css("opacity", o.opacity);
6753
	},
6754
	stop: function( event, ui, instance ) {
6755
		var o = instance.options;
6756
		if (o._opacity) {
6757
			$(ui.helper).css("opacity", o._opacity);
6758
		}
6759
	}
6760
});
6761
6762
$.ui.plugin.add("draggable", "scroll", {
6763
	start: function( event, ui, i ) {
6764
		if ( !i.scrollParentNotHidden ) {
6765
			i.scrollParentNotHidden = i.helper.scrollParent( false );
6766
		}
6767
6768
		if ( i.scrollParentNotHidden[ 0 ] !== i.document[ 0 ] && i.scrollParentNotHidden[ 0 ].tagName !== "HTML" ) {
6769
			i.overflowOffset = i.scrollParentNotHidden.offset();
6770
		}
6771
	},
6772
	drag: function( event, ui, i  ) {
6773
6774
		var o = i.options,
6775
			scrolled = false,
6776
			scrollParent = i.scrollParentNotHidden[ 0 ],
6777
			document = i.document[ 0 ];
6778
6779
		if ( scrollParent !== document && scrollParent.tagName !== "HTML" ) {
6780
			if ( !o.axis || o.axis !== "x" ) {
6781
				if ( ( i.overflowOffset.top + scrollParent.offsetHeight ) - event.pageY < o.scrollSensitivity ) {
6782
					scrollParent.scrollTop = scrolled = scrollParent.scrollTop + o.scrollSpeed;
6783
				} else if ( event.pageY - i.overflowOffset.top < o.scrollSensitivity ) {
6784
					scrollParent.scrollTop = scrolled = scrollParent.scrollTop - o.scrollSpeed;
6785
				}
6786
			}
6787
6788
			if ( !o.axis || o.axis !== "y" ) {
6789
				if ( ( i.overflowOffset.left + scrollParent.offsetWidth ) - event.pageX < o.scrollSensitivity ) {
6790
					scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft + o.scrollSpeed;
6791
				} else if ( event.pageX - i.overflowOffset.left < o.scrollSensitivity ) {
6792
					scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft - o.scrollSpeed;
6793
				}
6794
			}
6795
6796
		} else {
6797
6798
			if (!o.axis || o.axis !== "x") {
6799
				if (event.pageY - $(document).scrollTop() < o.scrollSensitivity) {
6800
					scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
6801
				} else if ($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) {
6802
					scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
6803
				}
6804
			}
6805
6806
			if (!o.axis || o.axis !== "y") {
6807
				if (event.pageX - $(document).scrollLeft() < o.scrollSensitivity) {
6808
					scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
6809
				} else if ($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) {
6810
					scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
6811
				}
6812
			}
6813
6814
		}
6815
6816
		if (scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) {
6817
			$.ui.ddmanager.prepareOffsets(i, event);
6818
		}
6819
6820
	}
6821
});
6822
6823
$.ui.plugin.add("draggable", "snap", {
6824
	start: function( event, ui, i ) {
6825
6826
		var o = i.options;
6827
6828
		i.snapElements = [];
6829
6830
		$(o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap).each(function() {
6831
			var $t = $(this),
6832
				$o = $t.offset();
6833
			if (this !== i.element[0]) {
6834
				i.snapElements.push({
6835
					item: this,
6836
					width: $t.outerWidth(), height: $t.outerHeight(),
6837
					top: $o.top, left: $o.left
6838
				});
6839
			}
6840
		});
6841
6842
	},
6843
	drag: function( event, ui, inst ) {
6844
6845
		var ts, bs, ls, rs, l, r, t, b, i, first,
6846
			o = inst.options,
6847
			d = o.snapTolerance,
6848
			x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
6849
			y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
6850
6851
		for (i = inst.snapElements.length - 1; i >= 0; i--){
6852
6853
			l = inst.snapElements[i].left - inst.margins.left;
6854
			r = l + inst.snapElements[i].width;
6855
			t = inst.snapElements[i].top - inst.margins.top;
6856
			b = t + inst.snapElements[i].height;
6857
6858
			if ( x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d || !$.contains( inst.snapElements[ i ].item.ownerDocument, inst.snapElements[ i ].item ) ) {
6859
				if (inst.snapElements[i].snapping) {
6860
					(inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
6861
				}
6862
				inst.snapElements[i].snapping = false;
6863
				continue;
6864
			}
6865
6866
			if (o.snapMode !== "inner") {
6867
				ts = Math.abs(t - y2) <= d;
6868
				bs = Math.abs(b - y1) <= d;
6869
				ls = Math.abs(l - x2) <= d;
6870
				rs = Math.abs(r - x1) <= d;
6871
				if (ts) {
6872
					ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top;
6873
				}
6874
				if (bs) {
6875
					ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top;
6876
				}
6877
				if (ls) {
6878
					ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left;
6879
				}
6880
				if (rs) {
6881
					ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left;
6882
				}
6883
			}
6884
6885
			first = (ts || bs || ls || rs);
6886
6887
			if (o.snapMode !== "outer") {
6888
				ts = Math.abs(t - y1) <= d;
6889
				bs = Math.abs(b - y2) <= d;
6890
				ls = Math.abs(l - x1) <= d;
6891
				rs = Math.abs(r - x2) <= d;
6892
				if (ts) {
6893
					ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top;
6894
				}
6895
				if (bs) {
6896
					ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top;
6897
				}
6898
				if (ls) {
6899
					ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left;
6900
				}
6901
				if (rs) {
6902
					ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left;
6903
				}
6904
			}
6905
6906
			if (!inst.snapElements[i].snapping && (ts || bs || ls || rs || first)) {
6907
				(inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
6908
			}
6909
			inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
6910
6911
		}
6912
6913
	}
6914
});
6915
6916
$.ui.plugin.add("draggable", "stack", {
6917
	start: function( event, ui, instance ) {
6918
		var min,
6919
			o = instance.options,
6920
			group = $.makeArray($(o.stack)).sort(function(a, b) {
6921
				return (parseInt($(a).css("zIndex"), 10) || 0) - (parseInt($(b).css("zIndex"), 10) || 0);
6922
			});
6923
6924
		if (!group.length) { return; }
6925
6926
		min = parseInt($(group[0]).css("zIndex"), 10) || 0;
6927
		$(group).each(function(i) {
6928
			$(this).css("zIndex", min + i);
6929
		});
6930
		this.css("zIndex", (min + group.length));
6931
	}
6932
});
6933
6934
$.ui.plugin.add("draggable", "zIndex", {
6935
	start: function( event, ui, instance ) {
6936
		var t = $( ui.helper ),
6937
			o = instance.options;
6938
6939
		if (t.css("zIndex")) {
6940
			o._zIndex = t.css("zIndex");
6941
		}
6942
		t.css("zIndex", o.zIndex);
6943
	},
6944
	stop: function( event, ui, instance ) {
6945
		var o = instance.options;
6946
6947
		if (o._zIndex) {
6948
			$(ui.helper).css("zIndex", o._zIndex);
6949
		}
6950
	}
6951
});
6952
6953
var draggable = $.ui.draggable;
6954
6955
6956
/*!
6957
 * jQuery UI Resizable 1.11.4
6958
 * http://jqueryui.com
6959
 *
6960
 * Copyright jQuery Foundation and other contributors
6961
 * Released under the MIT license.
6962
 * http://jquery.org/license
6963
 *
6964
 * http://api.jqueryui.com/resizable/
6965
 */
6966
6967
6968
$.widget("ui.resizable", $.ui.mouse, {
6969
	version: "1.11.4",
6970
	widgetEventPrefix: "resize",
6971
	options: {
6972
		alsoResize: false,
6973
		animate: false,
6974
		animateDuration: "slow",
6975
		animateEasing: "swing",
6976
		aspectRatio: false,
6977
		autoHide: false,
6978
		containment: false,
6979
		ghost: false,
6980
		grid: false,
6981
		handles: "e,s,se",
6982
		helper: false,
6983
		maxHeight: null,
6984
		maxWidth: null,
6985
		minHeight: 10,
6986
		minWidth: 10,
6987
		// See #7960
6988
		zIndex: 90,
6989
6990
		// callbacks
6991
		resize: null,
6992
		start: null,
6993
		stop: null
6994
	},
6995
6996
	_num: function( value ) {
6997
		return parseInt( value, 10 ) || 0;
6998
	},
6999
7000
	_isNumber: function( value ) {
7001
		return !isNaN( parseInt( value, 10 ) );
7002
	},
7003
7004
	_hasScroll: function( el, a ) {
7005
7006
		if ( $( el ).css( "overflow" ) === "hidden") {
7007
			return false;
7008
		}
7009
7010
		var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
7011
			has = false;
7012
7013
		if ( el[ scroll ] > 0 ) {
7014
			return true;
7015
		}
7016
7017
		// TODO: determine which cases actually cause this to happen
7018
		// if the element doesn't have the scroll set, see if it's possible to
7019
		// set the scroll
7020
		el[ scroll ] = 1;
7021
		has = ( el[ scroll ] > 0 );
7022
		el[ scroll ] = 0;
7023
		return has;
7024
	},
7025
7026
	_create: function() {
7027
7028
		var n, i, handle, axis, hname,
7029
			that = this,
7030
			o = this.options;
7031
		this.element.addClass("ui-resizable");
7032
7033
		$.extend(this, {
7034
			_aspectRatio: !!(o.aspectRatio),
7035
			aspectRatio: o.aspectRatio,
7036
			originalElement: this.element,
7037
			_proportionallyResizeElements: [],
7038
			_helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null
7039
		});
7040
7041
		// Wrap the element if it cannot hold child nodes
7042
		if (this.element[0].nodeName.match(/^(canvas|textarea|input|select|button|img)$/i)) {
7043
7044
			this.element.wrap(
7045
				$("<div class='ui-wrapper' style='overflow: hidden;'></div>").css({
7046
					position: this.element.css("position"),
7047
					width: this.element.outerWidth(),
7048
					height: this.element.outerHeight(),
7049
					top: this.element.css("top"),
7050
					left: this.element.css("left")
7051
				})
7052
			);
7053
7054
			this.element = this.element.parent().data(
7055
				"ui-resizable", this.element.resizable( "instance" )
7056
			);
7057
7058
			this.elementIsWrapper = true;
7059
7060
			this.element.css({
7061
				marginLeft: this.originalElement.css("marginLeft"),
7062
				marginTop: this.originalElement.css("marginTop"),
7063
				marginRight: this.originalElement.css("marginRight"),
7064
				marginBottom: this.originalElement.css("marginBottom")
7065
			});
7066
			this.originalElement.css({
7067
				marginLeft: 0,
7068
				marginTop: 0,
7069
				marginRight: 0,
7070
				marginBottom: 0
7071
			});
7072
			// support: Safari
7073
			// Prevent Safari textarea resize
7074
			this.originalResizeStyle = this.originalElement.css("resize");
7075
			this.originalElement.css("resize", "none");
7076
7077
			this._proportionallyResizeElements.push( this.originalElement.css({
7078
				position: "static",
7079
				zoom: 1,
7080
				display: "block"
7081
			}) );
7082
7083
			// support: IE9
7084
			// avoid IE jump (hard set the margin)
7085
			this.originalElement.css({ margin: this.originalElement.css("margin") });
7086
7087
			this._proportionallyResize();
7088
		}
7089
7090
		this.handles = o.handles ||
7091
			( !$(".ui-resizable-handle", this.element).length ?
7092
				"e,s,se" : {
7093
					n: ".ui-resizable-n",
7094
					e: ".ui-resizable-e",
7095
					s: ".ui-resizable-s",
7096
					w: ".ui-resizable-w",
7097
					se: ".ui-resizable-se",
7098
					sw: ".ui-resizable-sw",
7099
					ne: ".ui-resizable-ne",
7100
					nw: ".ui-resizable-nw"
7101
				} );
7102
7103
		this._handles = $();
7104
		if ( this.handles.constructor === String ) {
7105
7106
			if ( this.handles === "all") {
7107
				this.handles = "n,e,s,w,se,sw,ne,nw";
7108
			}
7109
7110
			n = this.handles.split(",");
7111
			this.handles = {};
7112
7113
			for (i = 0; i < n.length; i++) {
7114
7115
				handle = $.trim(n[i]);
7116
				hname = "ui-resizable-" + handle;
7117
				axis = $("<div class='ui-resizable-handle " + hname + "'></div>");
7118
7119
				axis.css({ zIndex: o.zIndex });
7120
7121
				// TODO : What's going on here?
7122
				if ("se" === handle) {
7123
					axis.addClass("ui-icon ui-icon-gripsmall-diagonal-se");
7124
				}
7125
7126
				this.handles[handle] = ".ui-resizable-" + handle;
7127
				this.element.append(axis);
7128
			}
7129
7130
		}
7131
7132
		this._renderAxis = function(target) {
7133
7134
			var i, axis, padPos, padWrapper;
7135
7136
			target = target || this.element;
7137
7138
			for (i in this.handles) {
7139
7140
				if (this.handles[i].constructor === String) {
7141
					this.handles[i] = this.element.children( this.handles[ i ] ).first().show();
7142
				} else if ( this.handles[ i ].jquery || this.handles[ i ].nodeType ) {
7143
					this.handles[ i ] = $( this.handles[ i ] );
7144
					this._on( this.handles[ i ], { "mousedown": that._mouseDown });
7145
				}
7146
7147
				if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/^(textarea|input|select|button)$/i)) {
7148
7149
					axis = $(this.handles[i], this.element);
7150
7151
					padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
7152
7153
					padPos = [ "padding",
7154
						/ne|nw|n/.test(i) ? "Top" :
7155
						/se|sw|s/.test(i) ? "Bottom" :
7156
						/^e$/.test(i) ? "Right" : "Left" ].join("");
7157
7158
					target.css(padPos, padWrapper);
7159
7160
					this._proportionallyResize();
7161
				}
7162
7163
				this._handles = this._handles.add( this.handles[ i ] );
7164
			}
7165
		};
7166
7167
		// TODO: make renderAxis a prototype function
7168
		this._renderAxis(this.element);
7169
7170
		this._handles = this._handles.add( this.element.find( ".ui-resizable-handle" ) );
7171
		this._handles.disableSelection();
7172
7173
		this._handles.mouseover(function() {
7174
			if (!that.resizing) {
7175
				if (this.className) {
7176
					axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
7177
				}
7178
				that.axis = axis && axis[1] ? axis[1] : "se";
7179
			}
7180
		});
7181
7182
		if (o.autoHide) {
7183
			this._handles.hide();
7184
			$(this.element)
7185
				.addClass("ui-resizable-autohide")
7186
				.mouseenter(function() {
7187
					if (o.disabled) {
7188
						return;
7189
					}
7190
					$(this).removeClass("ui-resizable-autohide");
7191
					that._handles.show();
7192
				})
7193
				.mouseleave(function() {
7194
					if (o.disabled) {
7195
						return;
7196
					}
7197
					if (!that.resizing) {
7198
						$(this).addClass("ui-resizable-autohide");
7199
						that._handles.hide();
7200
					}
7201
				});
7202
		}
7203
7204
		this._mouseInit();
7205
	},
7206
7207
	_destroy: function() {
7208
7209
		this._mouseDestroy();
7210
7211
		var wrapper,
7212
			_destroy = function(exp) {
7213
				$(exp)
7214
					.removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
7215
					.removeData("resizable")
7216
					.removeData("ui-resizable")
7217
					.unbind(".resizable")
7218
					.find(".ui-resizable-handle")
7219
						.remove();
7220
			};
7221
7222
		// TODO: Unwrap at same DOM position
7223
		if (this.elementIsWrapper) {
7224
			_destroy(this.element);
7225
			wrapper = this.element;
7226
			this.originalElement.css({
7227
				position: wrapper.css("position"),
7228
				width: wrapper.outerWidth(),
7229
				height: wrapper.outerHeight(),
7230
				top: wrapper.css("top"),
7231
				left: wrapper.css("left")
7232
			}).insertAfter( wrapper );
7233
			wrapper.remove();
7234
		}
7235
7236
		this.originalElement.css("resize", this.originalResizeStyle);
7237
		_destroy(this.originalElement);
7238
7239
		return this;
7240
	},
7241
7242
	_mouseCapture: function(event) {
7243
		var i, handle,
7244
			capture = false;
7245
7246
		for (i in this.handles) {
7247
			handle = $(this.handles[i])[0];
7248
			if (handle === event.target || $.contains(handle, event.target)) {
7249
				capture = true;
7250
			}
7251
		}
7252
7253
		return !this.options.disabled && capture;
7254
	},
7255
7256
	_mouseStart: function(event) {
7257
7258
		var curleft, curtop, cursor,
7259
			o = this.options,
7260
			el = this.element;
7261
7262
		this.resizing = true;
7263
7264
		this._renderProxy();
7265
7266
		curleft = this._num(this.helper.css("left"));
7267
		curtop = this._num(this.helper.css("top"));
7268
7269
		if (o.containment) {
7270
			curleft += $(o.containment).scrollLeft() || 0;
7271
			curtop += $(o.containment).scrollTop() || 0;
7272
		}
7273
7274
		this.offset = this.helper.offset();
7275
		this.position = { left: curleft, top: curtop };
7276
7277
		this.size = this._helper ? {
7278
				width: this.helper.width(),
7279
				height: this.helper.height()
7280
			} : {
7281
				width: el.width(),
7282
				height: el.height()
7283
			};
7284
7285
		this.originalSize = this._helper ? {
7286
				width: el.outerWidth(),
7287
				height: el.outerHeight()
7288
			} : {
7289
				width: el.width(),
7290
				height: el.height()
7291
			};
7292
7293
		this.sizeDiff = {
7294
			width: el.outerWidth() - el.width(),
7295
			height: el.outerHeight() - el.height()
7296
		};
7297
7298
		this.originalPosition = { left: curleft, top: curtop };
7299
		this.originalMousePosition = { left: event.pageX, top: event.pageY };
7300
7301
		this.aspectRatio = (typeof o.aspectRatio === "number") ?
7302
			o.aspectRatio :
7303
			((this.originalSize.width / this.originalSize.height) || 1);
7304
7305
		cursor = $(".ui-resizable-" + this.axis).css("cursor");
7306
		$("body").css("cursor", cursor === "auto" ? this.axis + "-resize" : cursor);
7307
7308
		el.addClass("ui-resizable-resizing");
7309
		this._propagate("start", event);
7310
		return true;
7311
	},
7312
7313
	_mouseDrag: function(event) {
7314
7315
		var data, props,
7316
			smp = this.originalMousePosition,
7317
			a = this.axis,
7318
			dx = (event.pageX - smp.left) || 0,
7319
			dy = (event.pageY - smp.top) || 0,
7320
			trigger = this._change[a];
7321
7322
		this._updatePrevProperties();
7323
7324
		if (!trigger) {
7325
			return false;
7326
		}
7327
7328
		data = trigger.apply(this, [ event, dx, dy ]);
7329
7330
		this._updateVirtualBoundaries(event.shiftKey);
7331
		if (this._aspectRatio || event.shiftKey) {
7332
			data = this._updateRatio(data, event);
7333
		}
7334
7335
		data = this._respectSize(data, event);
7336
7337
		this._updateCache(data);
7338
7339
		this._propagate("resize", event);
7340
7341
		props = this._applyChanges();
7342
7343
		if ( !this._helper && this._proportionallyResizeElements.length ) {
7344
			this._proportionallyResize();
7345
		}
7346
7347
		if ( !$.isEmptyObject( props ) ) {
7348
			this._updatePrevProperties();
7349
			this._trigger( "resize", event, this.ui() );
7350
			this._applyChanges();
7351
		}
7352
7353
		return false;
7354
	},
7355
7356
	_mouseStop: function(event) {
7357
7358
		this.resizing = false;
7359
		var pr, ista, soffseth, soffsetw, s, left, top,
7360
			o = this.options, that = this;
7361
7362
		if (this._helper) {
7363
7364
			pr = this._proportionallyResizeElements;
7365
			ista = pr.length && (/textarea/i).test(pr[0].nodeName);
7366
			soffseth = ista && this._hasScroll(pr[0], "left") ? 0 : that.sizeDiff.height;
7367
			soffsetw = ista ? 0 : that.sizeDiff.width;
7368
7369
			s = {
7370
				width: (that.helper.width()  - soffsetw),
7371
				height: (that.helper.height() - soffseth)
7372
			};
7373
			left = (parseInt(that.element.css("left"), 10) +
7374
				(that.position.left - that.originalPosition.left)) || null;
7375
			top = (parseInt(that.element.css("top"), 10) +
7376
				(that.position.top - that.originalPosition.top)) || null;
7377
7378
			if (!o.animate) {
7379
				this.element.css($.extend(s, { top: top, left: left }));
7380
			}
7381
7382
			that.helper.height(that.size.height);
7383
			that.helper.width(that.size.width);
7384
7385
			if (this._helper && !o.animate) {
7386
				this._proportionallyResize();
7387
			}
7388
		}
7389
7390
		$("body").css("cursor", "auto");
7391
7392
		this.element.removeClass("ui-resizable-resizing");
7393
7394
		this._propagate("stop", event);
7395
7396
		if (this._helper) {
7397
			this.helper.remove();
7398
		}
7399
7400
		return false;
7401
7402
	},
7403
7404
	_updatePrevProperties: function() {
7405
		this.prevPosition = {
7406
			top: this.position.top,
7407
			left: this.position.left
7408
		};
7409
		this.prevSize = {
7410
			width: this.size.width,
7411
			height: this.size.height
7412
		};
7413
	},
7414
7415
	_applyChanges: function() {
7416
		var props = {};
7417
7418
		if ( this.position.top !== this.prevPosition.top ) {
7419
			props.top = this.position.top + "px";
7420
		}
7421
		if ( this.position.left !== this.prevPosition.left ) {
7422
			props.left = this.position.left + "px";
7423
		}
7424
		if ( this.size.width !== this.prevSize.width ) {
7425
			props.width = this.size.width + "px";
7426
		}
7427
		if ( this.size.height !== this.prevSize.height ) {
7428
			props.height = this.size.height + "px";
7429
		}
7430
7431
		this.helper.css( props );
7432
7433
		return props;
7434
	},
7435
7436
	_updateVirtualBoundaries: function(forceAspectRatio) {
7437
		var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b,
7438
			o = this.options;
7439
7440
		b = {
7441
			minWidth: this._isNumber(o.minWidth) ? o.minWidth : 0,
7442
			maxWidth: this._isNumber(o.maxWidth) ? o.maxWidth : Infinity,
7443
			minHeight: this._isNumber(o.minHeight) ? o.minHeight : 0,
7444
			maxHeight: this._isNumber(o.maxHeight) ? o.maxHeight : Infinity
7445
		};
7446
7447
		if (this._aspectRatio || forceAspectRatio) {
7448
			pMinWidth = b.minHeight * this.aspectRatio;
7449
			pMinHeight = b.minWidth / this.aspectRatio;
7450
			pMaxWidth = b.maxHeight * this.aspectRatio;
7451
			pMaxHeight = b.maxWidth / this.aspectRatio;
7452
7453
			if (pMinWidth > b.minWidth) {
7454
				b.minWidth = pMinWidth;
7455
			}
7456
			if (pMinHeight > b.minHeight) {
7457
				b.minHeight = pMinHeight;
7458
			}
7459
			if (pMaxWidth < b.maxWidth) {
7460
				b.maxWidth = pMaxWidth;
7461
			}
7462
			if (pMaxHeight < b.maxHeight) {
7463
				b.maxHeight = pMaxHeight;
7464
			}
7465
		}
7466
		this._vBoundaries = b;
7467
	},
7468
7469
	_updateCache: function(data) {
7470
		this.offset = this.helper.offset();
7471
		if (this._isNumber(data.left)) {
7472
			this.position.left = data.left;
7473
		}
7474
		if (this._isNumber(data.top)) {
7475
			this.position.top = data.top;
7476
		}
7477
		if (this._isNumber(data.height)) {
7478
			this.size.height = data.height;
7479
		}
7480
		if (this._isNumber(data.width)) {
7481
			this.size.width = data.width;
7482
		}
7483
	},
7484
7485
	_updateRatio: function( data ) {
7486
7487
		var cpos = this.position,
7488
			csize = this.size,
7489
			a = this.axis;
7490
7491
		if (this._isNumber(data.height)) {
7492
			data.width = (data.height * this.aspectRatio);
7493
		} else if (this._isNumber(data.width)) {
7494
			data.height = (data.width / this.aspectRatio);
7495
		}
7496
7497
		if (a === "sw") {
7498
			data.left = cpos.left + (csize.width - data.width);
7499
			data.top = null;
7500
		}
7501
		if (a === "nw") {
7502
			data.top = cpos.top + (csize.height - data.height);
7503
			data.left = cpos.left + (csize.width - data.width);
7504
		}
7505
7506
		return data;
7507
	},
7508
7509
	_respectSize: function( data ) {
7510
7511
		var o = this._vBoundaries,
7512
			a = this.axis,
7513
			ismaxw = this._isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width),
7514
			ismaxh = this._isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
7515
			isminw = this._isNumber(data.width) && o.minWidth && (o.minWidth > data.width),
7516
			isminh = this._isNumber(data.height) && o.minHeight && (o.minHeight > data.height),
7517
			dw = this.originalPosition.left + this.originalSize.width,
7518
			dh = this.position.top + this.size.height,
7519
			cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
7520
		if (isminw) {
7521
			data.width = o.minWidth;
7522
		}
7523
		if (isminh) {
7524
			data.height = o.minHeight;
7525
		}
7526
		if (ismaxw) {
7527
			data.width = o.maxWidth;
7528
		}
7529
		if (ismaxh) {
7530
			data.height = o.maxHeight;
7531
		}
7532
7533
		if (isminw && cw) {
7534
			data.left = dw - o.minWidth;
7535
		}
7536
		if (ismaxw && cw) {
7537
			data.left = dw - o.maxWidth;
7538
		}
7539
		if (isminh && ch) {
7540
			data.top = dh - o.minHeight;
7541
		}
7542
		if (ismaxh && ch) {
7543
			data.top = dh - o.maxHeight;
7544
		}
7545
7546
		// Fixing jump error on top/left - bug #2330
7547
		if (!data.width && !data.height && !data.left && data.top) {
7548
			data.top = null;
7549
		} else if (!data.width && !data.height && !data.top && data.left) {
7550
			data.left = null;
7551
		}
7552
7553
		return data;
7554
	},
7555
7556
	_getPaddingPlusBorderDimensions: function( element ) {
7557
		var i = 0,
7558
			widths = [],
7559
			borders = [
7560
				element.css( "borderTopWidth" ),
7561
				element.css( "borderRightWidth" ),
7562
				element.css( "borderBottomWidth" ),
7563
				element.css( "borderLeftWidth" )
7564
			],
7565
			paddings = [
7566
				element.css( "paddingTop" ),
7567
				element.css( "paddingRight" ),
7568
				element.css( "paddingBottom" ),
7569
				element.css( "paddingLeft" )
7570
			];
7571
7572
		for ( ; i < 4; i++ ) {
7573
			widths[ i ] = ( parseInt( borders[ i ], 10 ) || 0 );
7574
			widths[ i ] += ( parseInt( paddings[ i ], 10 ) || 0 );
7575
		}
7576
7577
		return {
7578
			height: widths[ 0 ] + widths[ 2 ],
7579
			width: widths[ 1 ] + widths[ 3 ]
7580
		};
7581
	},
7582
7583
	_proportionallyResize: function() {
7584
7585
		if (!this._proportionallyResizeElements.length) {
7586
			return;
7587
		}
7588
7589
		var prel,
7590
			i = 0,
7591
			element = this.helper || this.element;
7592
7593
		for ( ; i < this._proportionallyResizeElements.length; i++) {
7594
7595
			prel = this._proportionallyResizeElements[i];
7596
7597
			// TODO: Seems like a bug to cache this.outerDimensions
7598
			// considering that we are in a loop.
7599
			if (!this.outerDimensions) {
7600
				this.outerDimensions = this._getPaddingPlusBorderDimensions( prel );
7601
			}
7602
7603
			prel.css({
7604
				height: (element.height() - this.outerDimensions.height) || 0,
7605
				width: (element.width() - this.outerDimensions.width) || 0
7606
			});
7607
7608
		}
7609
7610
	},
7611
7612
	_renderProxy: function() {
7613
7614
		var el = this.element, o = this.options;
7615
		this.elementOffset = el.offset();
7616
7617
		if (this._helper) {
7618
7619
			this.helper = this.helper || $("<div style='overflow:hidden;'></div>");
7620
7621
			this.helper.addClass(this._helper).css({
7622
				width: this.element.outerWidth() - 1,
7623
				height: this.element.outerHeight() - 1,
7624
				position: "absolute",
7625
				left: this.elementOffset.left + "px",
7626
				top: this.elementOffset.top + "px",
7627
				zIndex: ++o.zIndex //TODO: Don't modify option
7628
			});
7629
7630
			this.helper
7631
				.appendTo("body")
7632
				.disableSelection();
7633
7634
		} else {
7635
			this.helper = this.element;
7636
		}
7637
7638
	},
7639
7640
	_change: {
7641
		e: function(event, dx) {
7642
			return { width: this.originalSize.width + dx };
7643
		},
7644
		w: function(event, dx) {
7645
			var cs = this.originalSize, sp = this.originalPosition;
7646
			return { left: sp.left + dx, width: cs.width - dx };
7647
		},
7648
		n: function(event, dx, dy) {
7649
			var cs = this.originalSize, sp = this.originalPosition;
7650
			return { top: sp.top + dy, height: cs.height - dy };
7651
		},
7652
		s: function(event, dx, dy) {
7653
			return { height: this.originalSize.height + dy };
7654
		},
7655
		se: function(event, dx, dy) {
7656
			return $.extend(this._change.s.apply(this, arguments),
7657
				this._change.e.apply(this, [ event, dx, dy ]));
7658
		},
7659
		sw: function(event, dx, dy) {
7660
			return $.extend(this._change.s.apply(this, arguments),
7661
				this._change.w.apply(this, [ event, dx, dy ]));
7662
		},
7663
		ne: function(event, dx, dy) {
7664
			return $.extend(this._change.n.apply(this, arguments),
7665
				this._change.e.apply(this, [ event, dx, dy ]));
7666
		},
7667
		nw: function(event, dx, dy) {
7668
			return $.extend(this._change.n.apply(this, arguments),
7669
				this._change.w.apply(this, [ event, dx, dy ]));
7670
		}
7671
	},
7672
7673
	_propagate: function(n, event) {
7674
		$.ui.plugin.call(this, n, [ event, this.ui() ]);
7675
		(n !== "resize" && this._trigger(n, event, this.ui()));
7676
	},
7677
7678
	plugins: {},
7679
7680
	ui: function() {
7681
		return {
7682
			originalElement: this.originalElement,
7683
			element: this.element,
7684
			helper: this.helper,
7685
			position: this.position,
7686
			size: this.size,
7687
			originalSize: this.originalSize,
7688
			originalPosition: this.originalPosition
7689
		};
7690
	}
7691
7692
});
7693
7694
/*
7695
 * Resizable Extensions
7696
 */
7697
7698
$.ui.plugin.add("resizable", "animate", {
7699
7700
	stop: function( event ) {
7701
		var that = $(this).resizable( "instance" ),
7702
			o = that.options,
7703
			pr = that._proportionallyResizeElements,
7704
			ista = pr.length && (/textarea/i).test(pr[0].nodeName),
7705
			soffseth = ista && that._hasScroll(pr[0], "left") ? 0 : that.sizeDiff.height,
7706
			soffsetw = ista ? 0 : that.sizeDiff.width,
7707
			style = { width: (that.size.width - soffsetw), height: (that.size.height - soffseth) },
7708
			left = (parseInt(that.element.css("left"), 10) +
7709
				(that.position.left - that.originalPosition.left)) || null,
7710
			top = (parseInt(that.element.css("top"), 10) +
7711
				(that.position.top - that.originalPosition.top)) || null;
7712
7713
		that.element.animate(
7714
			$.extend(style, top && left ? { top: top, left: left } : {}), {
7715
				duration: o.animateDuration,
7716
				easing: o.animateEasing,
7717
				step: function() {
7718
7719
					var data = {
7720
						width: parseInt(that.element.css("width"), 10),
7721
						height: parseInt(that.element.css("height"), 10),
7722
						top: parseInt(that.element.css("top"), 10),
7723
						left: parseInt(that.element.css("left"), 10)
7724
					};
7725
7726
					if (pr && pr.length) {
7727
						$(pr[0]).css({ width: data.width, height: data.height });
7728
					}
7729
7730
					// propagating resize, and updating values for each animation step
7731
					that._updateCache(data);
7732
					that._propagate("resize", event);
7733
7734
				}
7735
			}
7736
		);
7737
	}
7738
7739
});
7740
7741
$.ui.plugin.add( "resizable", "containment", {
7742
7743
	start: function() {
7744
		var element, p, co, ch, cw, width, height,
7745
			that = $( this ).resizable( "instance" ),
7746
			o = that.options,
7747
			el = that.element,
7748
			oc = o.containment,
7749
			ce = ( oc instanceof $ ) ? oc.get( 0 ) : ( /parent/.test( oc ) ) ? el.parent().get( 0 ) : oc;
7750
7751
		if ( !ce ) {
7752
			return;
7753
		}
7754
7755
		that.containerElement = $( ce );
7756
7757
		if ( /document/.test( oc ) || oc === document ) {
7758
			that.containerOffset = {
7759
				left: 0,
7760
				top: 0
7761
			};
7762
			that.containerPosition = {
7763
				left: 0,
7764
				top: 0
7765
			};
7766
7767
			that.parentData = {
7768
				element: $( document ),
7769
				left: 0,
7770
				top: 0,
7771
				width: $( document ).width(),
7772
				height: $( document ).height() || document.body.parentNode.scrollHeight
7773
			};
7774
		} else {
7775
			element = $( ce );
7776
			p = [];
7777
			$([ "Top", "Right", "Left", "Bottom" ]).each(function( i, name ) {
7778
				p[ i ] = that._num( element.css( "padding" + name ) );
7779
			});
7780
7781
			that.containerOffset = element.offset();
7782
			that.containerPosition = element.position();
7783
			that.containerSize = {
7784
				height: ( element.innerHeight() - p[ 3 ] ),
7785
				width: ( element.innerWidth() - p[ 1 ] )
7786
			};
7787
7788
			co = that.containerOffset;
7789
			ch = that.containerSize.height;
7790
			cw = that.containerSize.width;
7791
			width = ( that._hasScroll ( ce, "left" ) ? ce.scrollWidth : cw );
7792
			height = ( that._hasScroll ( ce ) ? ce.scrollHeight : ch ) ;
7793
7794
			that.parentData = {
7795
				element: ce,
7796
				left: co.left,
7797
				top: co.top,
7798
				width: width,
7799
				height: height
7800
			};
7801
		}
7802
	},
7803
7804
	resize: function( event ) {
7805
		var woset, hoset, isParent, isOffsetRelative,
7806
			that = $( this ).resizable( "instance" ),
7807
			o = that.options,
7808
			co = that.containerOffset,
7809
			cp = that.position,
7810
			pRatio = that._aspectRatio || event.shiftKey,
7811
			cop = {
7812
				top: 0,
7813
				left: 0
7814
			},
7815
			ce = that.containerElement,
7816
			continueResize = true;
7817
7818
		if ( ce[ 0 ] !== document && ( /static/ ).test( ce.css( "position" ) ) ) {
7819
			cop = co;
7820
		}
7821
7822
		if ( cp.left < ( that._helper ? co.left : 0 ) ) {
7823
			that.size.width = that.size.width +
7824
				( that._helper ?
7825
					( that.position.left - co.left ) :
7826
					( that.position.left - cop.left ) );
7827
7828
			if ( pRatio ) {
7829
				that.size.height = that.size.width / that.aspectRatio;
7830
				continueResize = false;
7831
			}
7832
			that.position.left = o.helper ? co.left : 0;
7833
		}
7834
7835
		if ( cp.top < ( that._helper ? co.top : 0 ) ) {
7836
			that.size.height = that.size.height +
7837
				( that._helper ?
7838
					( that.position.top - co.top ) :
7839
					that.position.top );
7840
7841
			if ( pRatio ) {
7842
				that.size.width = that.size.height * that.aspectRatio;
7843
				continueResize = false;
7844
			}
7845
			that.position.top = that._helper ? co.top : 0;
7846
		}
7847
7848
		isParent = that.containerElement.get( 0 ) === that.element.parent().get( 0 );
7849
		isOffsetRelative = /relative|absolute/.test( that.containerElement.css( "position" ) );
7850
7851
		if ( isParent && isOffsetRelative ) {
7852
			that.offset.left = that.parentData.left + that.position.left;
7853
			that.offset.top = that.parentData.top + that.position.top;
7854
		} else {
7855
			that.offset.left = that.element.offset().left;
7856
			that.offset.top = that.element.offset().top;
7857
		}
7858
7859
		woset = Math.abs( that.sizeDiff.width +
7860
			(that._helper ?
7861
				that.offset.left - cop.left :
7862
				(that.offset.left - co.left)) );
7863
7864
		hoset = Math.abs( that.sizeDiff.height +
7865
			(that._helper ?
7866
				that.offset.top - cop.top :
7867
				(that.offset.top - co.top)) );
7868
7869
		if ( woset + that.size.width >= that.parentData.width ) {
7870
			that.size.width = that.parentData.width - woset;
7871
			if ( pRatio ) {
7872
				that.size.height = that.size.width / that.aspectRatio;
7873
				continueResize = false;
7874
			}
7875
		}
7876
7877
		if ( hoset + that.size.height >= that.parentData.height ) {
7878
			that.size.height = that.parentData.height - hoset;
7879
			if ( pRatio ) {
7880
				that.size.width = that.size.height * that.aspectRatio;
7881
				continueResize = false;
7882
			}
7883
		}
7884
7885
		if ( !continueResize ) {
7886
			that.position.left = that.prevPosition.left;
7887
			that.position.top = that.prevPosition.top;
7888
			that.size.width = that.prevSize.width;
7889
			that.size.height = that.prevSize.height;
7890
		}
7891
	},
7892
7893
	stop: function() {
7894
		var that = $( this ).resizable( "instance" ),
7895
			o = that.options,
7896
			co = that.containerOffset,
7897
			cop = that.containerPosition,
7898
			ce = that.containerElement,
7899
			helper = $( that.helper ),
7900
			ho = helper.offset(),
7901
			w = helper.outerWidth() - that.sizeDiff.width,
7902
			h = helper.outerHeight() - that.sizeDiff.height;
7903
7904
		if ( that._helper && !o.animate && ( /relative/ ).test( ce.css( "position" ) ) ) {
7905
			$( this ).css({
7906
				left: ho.left - cop.left - co.left,
7907
				width: w,
7908
				height: h
7909
			});
7910
		}
7911
7912
		if ( that._helper && !o.animate && ( /static/ ).test( ce.css( "position" ) ) ) {
7913
			$( this ).css({
7914
				left: ho.left - cop.left - co.left,
7915
				width: w,
7916
				height: h
7917
			});
7918
		}
7919
	}
7920
});
7921
7922
$.ui.plugin.add("resizable", "alsoResize", {
7923
7924
	start: function() {
7925
		var that = $(this).resizable( "instance" ),
7926
			o = that.options;
7927
7928
		$(o.alsoResize).each(function() {
7929
			var el = $(this);
7930
			el.data("ui-resizable-alsoresize", {
7931
				width: parseInt(el.width(), 10), height: parseInt(el.height(), 10),
7932
				left: parseInt(el.css("left"), 10), top: parseInt(el.css("top"), 10)
7933
			});
7934
		});
7935
	},
7936
7937
	resize: function(event, ui) {
7938
		var that = $(this).resizable( "instance" ),
7939
			o = that.options,
7940
			os = that.originalSize,
7941
			op = that.originalPosition,
7942
			delta = {
7943
				height: (that.size.height - os.height) || 0,
7944
				width: (that.size.width - os.width) || 0,
7945
				top: (that.position.top - op.top) || 0,
7946
				left: (that.position.left - op.left) || 0
7947
			};
7948
7949
			$(o.alsoResize).each(function() {
7950
				var el = $(this), start = $(this).data("ui-resizable-alsoresize"), style = {},
7951
					css = el.parents(ui.originalElement[0]).length ?
7952
							[ "width", "height" ] :
7953
							[ "width", "height", "top", "left" ];
7954
7955
				$.each(css, function(i, prop) {
7956
					var sum = (start[prop] || 0) + (delta[prop] || 0);
7957
					if (sum && sum >= 0) {
7958
						style[prop] = sum || null;
7959
					}
7960
				});
7961
7962
				el.css(style);
7963
			});
7964
	},
7965
7966
	stop: function() {
7967
		$(this).removeData("resizable-alsoresize");
7968
	}
7969
});
7970
7971
$.ui.plugin.add("resizable", "ghost", {
7972
7973
	start: function() {
7974
7975
		var that = $(this).resizable( "instance" ), o = that.options, cs = that.size;
7976
7977
		that.ghost = that.originalElement.clone();
7978
		that.ghost
7979
			.css({
7980
				opacity: 0.25,
7981
				display: "block",
7982
				position: "relative",
7983
				height: cs.height,
7984
				width: cs.width,
7985
				margin: 0,
7986
				left: 0,
7987
				top: 0
7988
			})
7989
			.addClass("ui-resizable-ghost")
7990
			.addClass(typeof o.ghost === "string" ? o.ghost : "");
7991
7992
		that.ghost.appendTo(that.helper);
7993
7994
	},
7995
7996
	resize: function() {
7997
		var that = $(this).resizable( "instance" );
7998
		if (that.ghost) {
7999
			that.ghost.css({
8000
				position: "relative",
8001
				height: that.size.height,
8002
				width: that.size.width
8003
			});
8004
		}
8005
	},
8006
8007
	stop: function() {
8008
		var that = $(this).resizable( "instance" );
8009
		if (that.ghost && that.helper) {
8010
			that.helper.get(0).removeChild(that.ghost.get(0));
8011
		}
8012
	}
8013
8014
});
8015
8016
$.ui.plugin.add("resizable", "grid", {
8017
8018
	resize: function() {
8019
		var outerDimensions,
8020
			that = $(this).resizable( "instance" ),
8021
			o = that.options,
8022
			cs = that.size,
8023
			os = that.originalSize,
8024
			op = that.originalPosition,
8025
			a = that.axis,
8026
			grid = typeof o.grid === "number" ? [ o.grid, o.grid ] : o.grid,
8027
			gridX = (grid[0] || 1),
8028
			gridY = (grid[1] || 1),
8029
			ox = Math.round((cs.width - os.width) / gridX) * gridX,
8030
			oy = Math.round((cs.height - os.height) / gridY) * gridY,
8031
			newWidth = os.width + ox,
8032
			newHeight = os.height + oy,
8033
			isMaxWidth = o.maxWidth && (o.maxWidth < newWidth),
8034
			isMaxHeight = o.maxHeight && (o.maxHeight < newHeight),
8035
			isMinWidth = o.minWidth && (o.minWidth > newWidth),
8036
			isMinHeight = o.minHeight && (o.minHeight > newHeight);
8037
8038
		o.grid = grid;
8039
8040
		if (isMinWidth) {
8041
			newWidth += gridX;
8042
		}
8043
		if (isMinHeight) {
8044
			newHeight += gridY;
8045
		}
8046
		if (isMaxWidth) {
8047
			newWidth -= gridX;
8048
		}
8049
		if (isMaxHeight) {
8050
			newHeight -= gridY;
8051
		}
8052
8053
		if (/^(se|s|e)$/.test(a)) {
8054
			that.size.width = newWidth;
8055
			that.size.height = newHeight;
8056
		} else if (/^(ne)$/.test(a)) {
8057
			that.size.width = newWidth;
8058
			that.size.height = newHeight;
8059
			that.position.top = op.top - oy;
8060
		} else if (/^(sw)$/.test(a)) {
8061
			that.size.width = newWidth;
8062
			that.size.height = newHeight;
8063
			that.position.left = op.left - ox;
8064
		} else {
8065
			if ( newHeight - gridY <= 0 || newWidth - gridX <= 0) {
8066
				outerDimensions = that._getPaddingPlusBorderDimensions( this );
8067
			}
8068
8069
			if ( newHeight - gridY > 0 ) {
8070
				that.size.height = newHeight;
8071
				that.position.top = op.top - oy;
8072
			} else {
8073
				newHeight = gridY - outerDimensions.height;
8074
				that.size.height = newHeight;
8075
				that.position.top = op.top + os.height - newHeight;
8076
			}
8077
			if ( newWidth - gridX > 0 ) {
8078
				that.size.width = newWidth;
8079
				that.position.left = op.left - ox;
8080
			} else {
8081
				newWidth = gridX - outerDimensions.width;
8082
				that.size.width = newWidth;
8083
				that.position.left = op.left + os.width - newWidth;
8084
			}
8085
		}
8086
	}
8087
8088
});
8089
8090
var resizable = $.ui.resizable;
8091
8092
8093
/*!
8094
 * jQuery UI Dialog 1.11.4
8095
 * http://jqueryui.com
8096
 *
8097
 * Copyright jQuery Foundation and other contributors
8098
 * Released under the MIT license.
8099
 * http://jquery.org/license
8100
 *
8101
 * http://api.jqueryui.com/dialog/
8102
 */
8103
8104
8105
var dialog = $.widget( "ui.dialog", {
8106
	version: "1.11.4",
8107
	options: {
8108
		appendTo: "body",
8109
		autoOpen: true,
8110
		buttons: [],
8111
		closeOnEscape: true,
8112
		closeText: "Close",
8113
		dialogClass: "",
8114
		draggable: true,
8115
		hide: null,
8116
		height: "auto",
8117
		maxHeight: null,
8118
		maxWidth: null,
8119
		minHeight: 150,
8120
		minWidth: 150,
8121
		modal: false,
8122
		position: {
8123
			my: "center",
8124
			at: "center",
8125
			of: window,
8126
			collision: "fit",
8127
			// Ensure the titlebar is always visible
8128
			using: function( pos ) {
8129
				var topOffset = $( this ).css( pos ).offset().top;
8130
				if ( topOffset < 0 ) {
8131
					$( this ).css( "top", pos.top - topOffset );
8132
				}
8133
			}
8134
		},
8135
		resizable: true,
8136
		show: null,
8137
		title: null,
8138
		width: 300,
8139
8140
		// callbacks
8141
		beforeClose: null,
8142
		close: null,
8143
		drag: null,
8144
		dragStart: null,
8145
		dragStop: null,
8146
		focus: null,
8147
		open: null,
8148
		resize: null,
8149
		resizeStart: null,
8150
		resizeStop: null
8151
	},
8152
8153
	sizeRelatedOptions: {
8154
		buttons: true,
8155
		height: true,
8156
		maxHeight: true,
8157
		maxWidth: true,
8158
		minHeight: true,
8159
		minWidth: true,
8160
		width: true
8161
	},
8162
8163
	resizableRelatedOptions: {
8164
		maxHeight: true,
8165
		maxWidth: true,
8166
		minHeight: true,
8167
		minWidth: true
8168
	},
8169
8170
	_create: function() {
8171
		this.originalCss = {
8172
			display: this.element[ 0 ].style.display,
8173
			width: this.element[ 0 ].style.width,
8174
			minHeight: this.element[ 0 ].style.minHeight,
8175
			maxHeight: this.element[ 0 ].style.maxHeight,
8176
			height: this.element[ 0 ].style.height
8177
		};
8178
		this.originalPosition = {
8179
			parent: this.element.parent(),
8180
			index: this.element.parent().children().index( this.element )
8181
		};
8182
		this.originalTitle = this.element.attr( "title" );
8183
		this.options.title = this.options.title || this.originalTitle;
8184
8185
		this._createWrapper();
8186
8187
		this.element
8188
			.show()
8189
			.removeAttr( "title" )
8190
			.addClass( "ui-dialog-content ui-widget-content" )
8191
			.appendTo( this.uiDialog );
8192
8193
		this._createTitlebar();
8194
		this._createButtonPane();
8195
8196
		if ( this.options.draggable && $.fn.draggable ) {
8197
			this._makeDraggable();
8198
		}
8199
		if ( this.options.resizable && $.fn.resizable ) {
8200
			this._makeResizable();
8201
		}
8202
8203
		this._isOpen = false;
8204
8205
		this._trackFocus();
8206
	},
8207
8208
	_init: function() {
8209
		if ( this.options.autoOpen ) {
8210
			this.open();
8211
		}
8212
	},
8213
8214
	_appendTo: function() {
8215
		var element = this.options.appendTo;
8216
		if ( element && (element.jquery || element.nodeType) ) {
8217
			return $( element );
8218
		}
8219
		return this.document.find( element || "body" ).eq( 0 );
8220
	},
8221
8222
	_destroy: function() {
8223
		var next,
8224
			originalPosition = this.originalPosition;
8225
8226
		this._untrackInstance();
8227
		this._destroyOverlay();
8228
8229
		this.element
8230
			.removeUniqueId()
8231
			.removeClass( "ui-dialog-content ui-widget-content" )
8232
			.css( this.originalCss )
8233
			// Without detaching first, the following becomes really slow
8234
			.detach();
8235
8236
		this.uiDialog.stop( true, true ).remove();
8237
8238
		if ( this.originalTitle ) {
8239
			this.element.attr( "title", this.originalTitle );
8240
		}
8241
8242
		next = originalPosition.parent.children().eq( originalPosition.index );
8243
		// Don't try to place the dialog next to itself (#8613)
8244
		if ( next.length && next[ 0 ] !== this.element[ 0 ] ) {
8245
			next.before( this.element );
8246
		} else {
8247
			originalPosition.parent.append( this.element );
8248
		}
8249
	},
8250
8251
	widget: function() {
8252
		return this.uiDialog;
8253
	},
8254
8255
	disable: $.noop,
8256
	enable: $.noop,
8257
8258
	close: function( event ) {
8259
		var activeElement,
8260
			that = this;
8261
8262
		if ( !this._isOpen || this._trigger( "beforeClose", event ) === false ) {
8263
			return;
8264
		}
8265
8266
		this._isOpen = false;
8267
		this._focusedElement = null;
8268
		this._destroyOverlay();
8269
		this._untrackInstance();
8270
8271
		if ( !this.opener.filter( ":focusable" ).focus().length ) {
8272
8273
			// support: IE9
8274
			// IE9 throws an "Unspecified error" accessing document.activeElement from an <iframe>
8275
			try {
8276
				activeElement = this.document[ 0 ].activeElement;
8277
8278
				// Support: IE9, IE10
8279
				// If the <body> is blurred, IE will switch windows, see #4520
8280
				if ( activeElement && activeElement.nodeName.toLowerCase() !== "body" ) {
8281
8282
					// Hiding a focused element doesn't trigger blur in WebKit
8283
					// so in case we have nothing to focus on, explicitly blur the active element
8284
					// https://bugs.webkit.org/show_bug.cgi?id=47182
8285
					$( activeElement ).blur();
8286
				}
8287
			} catch ( error ) {}
8288
		}
8289
8290
		this._hide( this.uiDialog, this.options.hide, function() {
8291
			that._trigger( "close", event );
8292
		});
8293
	},
8294
8295
	isOpen: function() {
8296
		return this._isOpen;
8297
	},
8298
8299
	moveToTop: function() {
8300
		this._moveToTop();
8301
	},
8302
8303
	_moveToTop: function( event, silent ) {
8304
		var moved = false,
8305
			zIndices = this.uiDialog.siblings( ".ui-front:visible" ).map(function() {
8306
				return +$( this ).css( "z-index" );
8307
			}).get(),
8308
			zIndexMax = Math.max.apply( null, zIndices );
8309
8310
		if ( zIndexMax >= +this.uiDialog.css( "z-index" ) ) {
8311
			this.uiDialog.css( "z-index", zIndexMax + 1 );
8312
			moved = true;
8313
		}
8314
8315
		if ( moved && !silent ) {
8316
			this._trigger( "focus", event );
8317
		}
8318
		return moved;
8319
	},
8320
8321
	open: function() {
8322
		var that = this;
8323
		if ( this._isOpen ) {
8324
			if ( this._moveToTop() ) {
8325
				this._focusTabbable();
8326
			}
8327
			return;
8328
		}
8329
8330
		this._isOpen = true;
8331
		this.opener = $( this.document[ 0 ].activeElement );
8332
8333
		this._size();
8334
		this._position();
8335
		this._createOverlay();
8336
		this._moveToTop( null, true );
8337
8338
		// Ensure the overlay is moved to the top with the dialog, but only when
8339
		// opening. The overlay shouldn't move after the dialog is open so that
8340
		// modeless dialogs opened after the modal dialog stack properly.
8341
		if ( this.overlay ) {
8342
			this.overlay.css( "z-index", this.uiDialog.css( "z-index" ) - 1 );
8343
		}
8344
8345
		this._show( this.uiDialog, this.options.show, function() {
8346
			that._focusTabbable();
8347
			that._trigger( "focus" );
8348
		});
8349
8350
		// Track the dialog immediately upon openening in case a focus event
8351
		// somehow occurs outside of the dialog before an element inside the
8352
		// dialog is focused (#10152)
8353
		this._makeFocusTarget();
8354
8355
		this._trigger( "open" );
8356
	},
8357
8358
	_focusTabbable: function() {
8359
		// Set focus to the first match:
8360
		// 1. An element that was focused previously
8361
		// 2. First element inside the dialog matching [autofocus]
8362
		// 3. Tabbable element inside the content element
8363
		// 4. Tabbable element inside the buttonpane
8364
		// 5. The close button
8365
		// 6. The dialog itself
8366
		var hasFocus = this._focusedElement;
8367
		if ( !hasFocus ) {
8368
			hasFocus = this.element.find( "[autofocus]" );
8369
		}
8370
		if ( !hasFocus.length ) {
8371
			hasFocus = this.element.find( ":tabbable" );
8372
		}
8373
		if ( !hasFocus.length ) {
8374
			hasFocus = this.uiDialogButtonPane.find( ":tabbable" );
8375
		}
8376
		if ( !hasFocus.length ) {
8377
			hasFocus = this.uiDialogTitlebarClose.filter( ":tabbable" );
8378
		}
8379
		if ( !hasFocus.length ) {
8380
			hasFocus = this.uiDialog;
8381
		}
8382
		hasFocus.eq( 0 ).focus();
8383
	},
8384
8385
	_keepFocus: function( event ) {
8386
		function checkFocus() {
8387
			var activeElement = this.document[0].activeElement,
8388
				isActive = this.uiDialog[0] === activeElement ||
8389
					$.contains( this.uiDialog[0], activeElement );
8390
			if ( !isActive ) {
8391
				this._focusTabbable();
8392
			}
8393
		}
8394
		event.preventDefault();
8395
		checkFocus.call( this );
8396
		// support: IE
8397
		// IE <= 8 doesn't prevent moving focus even with event.preventDefault()
8398
		// so we check again later
8399
		this._delay( checkFocus );
8400
	},
8401
8402
	_createWrapper: function() {
8403
		this.uiDialog = $("<div>")
8404
			.addClass( "ui-dialog ui-widget ui-widget-content ui-corner-all ui-front " +
8405
				this.options.dialogClass )
8406
			.hide()
8407
			.attr({
8408
				// Setting tabIndex makes the div focusable
8409
				tabIndex: -1,
8410
				role: "dialog"
8411
			})
8412
			.appendTo( this._appendTo() );
8413
8414
		this._on( this.uiDialog, {
8415
			keydown: function( event ) {
8416
				if ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
8417
						event.keyCode === $.ui.keyCode.ESCAPE ) {
8418
					event.preventDefault();
8419
					this.close( event );
8420
					return;
8421
				}
8422
8423
				// prevent tabbing out of dialogs
8424
				if ( event.keyCode !== $.ui.keyCode.TAB || event.isDefaultPrevented() ) {
8425
					return;
8426
				}
8427
				var tabbables = this.uiDialog.find( ":tabbable" ),
8428
					first = tabbables.filter( ":first" ),
8429
					last = tabbables.filter( ":last" );
8430
8431
				if ( ( event.target === last[0] || event.target === this.uiDialog[0] ) && !event.shiftKey ) {
8432
					this._delay(function() {
8433
						first.focus();
8434
					});
8435
					event.preventDefault();
8436
				} else if ( ( event.target === first[0] || event.target === this.uiDialog[0] ) && event.shiftKey ) {
8437
					this._delay(function() {
8438
						last.focus();
8439
					});
8440
					event.preventDefault();
8441
				}
8442
			},
8443
			mousedown: function( event ) {
8444
				if ( this._moveToTop( event ) ) {
8445
					this._focusTabbable();
8446
				}
8447
			}
8448
		});
8449
8450
		// We assume that any existing aria-describedby attribute means
8451
		// that the dialog content is marked up properly
8452
		// otherwise we brute force the content as the description
8453
		if ( !this.element.find( "[aria-describedby]" ).length ) {
8454
			this.uiDialog.attr({
8455
				"aria-describedby": this.element.uniqueId().attr( "id" )
8456
			});
8457
		}
8458
	},
8459
8460
	_createTitlebar: function() {
8461
		var uiDialogTitle;
8462
8463
		this.uiDialogTitlebar = $( "<div>" )
8464
			.addClass( "ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix" )
8465
			.prependTo( this.uiDialog );
8466
		this._on( this.uiDialogTitlebar, {
8467
			mousedown: function( event ) {
8468
				// Don't prevent click on close button (#8838)
8469
				// Focusing a dialog that is partially scrolled out of view
8470
				// causes the browser to scroll it into view, preventing the click event
8471
				if ( !$( event.target ).closest( ".ui-dialog-titlebar-close" ) ) {
8472
					// Dialog isn't getting focus when dragging (#8063)
8473
					this.uiDialog.focus();
8474
				}
8475
			}
8476
		});
8477
8478
		// support: IE
8479
		// Use type="button" to prevent enter keypresses in textboxes from closing the
8480
		// dialog in IE (#9312)
8481
		this.uiDialogTitlebarClose = $( "<button type='button'></button>" )
8482
			.button({
8483
				label: this.options.closeText,
8484
				icons: {
8485
					primary: "ui-icon-closethick"
8486
				},
8487
				text: false
8488
			})
8489
			.addClass( "ui-dialog-titlebar-close" )
8490
			.appendTo( this.uiDialogTitlebar );
8491
		this._on( this.uiDialogTitlebarClose, {
8492
			click: function( event ) {
8493
				event.preventDefault();
8494
				this.close( event );
8495
			}
8496
		});
8497
8498
		uiDialogTitle = $( "<span>" )
8499
			.uniqueId()
8500
			.addClass( "ui-dialog-title" )
8501
			.prependTo( this.uiDialogTitlebar );
8502
		this._title( uiDialogTitle );
8503
8504
		this.uiDialog.attr({
8505
			"aria-labelledby": uiDialogTitle.attr( "id" )
8506
		});
8507
	},
8508
8509
	_title: function( title ) {
8510
		if ( !this.options.title ) {
8511
			title.html( "&#160;" );
8512
		}
8513
		title.text( this.options.title );
8514
	},
8515
8516
	_createButtonPane: function() {
8517
		this.uiDialogButtonPane = $( "<div>" )
8518
			.addClass( "ui-dialog-buttonpane ui-widget-content ui-helper-clearfix" );
8519
8520
		this.uiButtonSet = $( "<div>" )
8521
			.addClass( "ui-dialog-buttonset" )
8522
			.appendTo( this.uiDialogButtonPane );
8523
8524
		this._createButtons();
8525
	},
8526
8527
	_createButtons: function() {
8528
		var that = this,
8529
			buttons = this.options.buttons;
8530
8531
		// if we already have a button pane, remove it
8532
		this.uiDialogButtonPane.remove();
8533
		this.uiButtonSet.empty();
8534
8535
		if ( $.isEmptyObject( buttons ) || ($.isArray( buttons ) && !buttons.length) ) {
8536
			this.uiDialog.removeClass( "ui-dialog-buttons" );
8537
			return;
8538
		}
8539
8540
		$.each( buttons, function( name, props ) {
8541
			var click, buttonOptions;
8542
			props = $.isFunction( props ) ?
8543
				{ click: props, text: name } :
8544
				props;
8545
			// Default to a non-submitting button
8546
			props = $.extend( { type: "button" }, props );
8547
			// Change the context for the click callback to be the main element
8548
			click = props.click;
8549
			props.click = function() {
8550
				click.apply( that.element[ 0 ], arguments );
8551
			};
8552
			buttonOptions = {
8553
				icons: props.icons,
8554
				text: props.showText
8555
			};
8556
			delete props.icons;
8557
			delete props.showText;
8558
			$( "<button></button>", props )
8559
				.button( buttonOptions )
8560
				.appendTo( that.uiButtonSet );
8561
		});
8562
		this.uiDialog.addClass( "ui-dialog-buttons" );
8563
		this.uiDialogButtonPane.appendTo( this.uiDialog );
8564
	},
8565
8566
	_makeDraggable: function() {
8567
		var that = this,
8568
			options = this.options;
8569
8570
		function filteredUi( ui ) {
8571
			return {
8572
				position: ui.position,
8573
				offset: ui.offset
8574
			};
8575
		}
8576
8577
		this.uiDialog.draggable({
8578
			cancel: ".ui-dialog-content, .ui-dialog-titlebar-close",
8579
			handle: ".ui-dialog-titlebar",
8580
			containment: "document",
8581
			start: function( event, ui ) {
8582
				$( this ).addClass( "ui-dialog-dragging" );
8583
				that._blockFrames();
8584
				that._trigger( "dragStart", event, filteredUi( ui ) );
8585
			},
8586
			drag: function( event, ui ) {
8587
				that._trigger( "drag", event, filteredUi( ui ) );
8588
			},
8589
			stop: function( event, ui ) {
8590
				var left = ui.offset.left - that.document.scrollLeft(),
8591
					top = ui.offset.top - that.document.scrollTop();
8592
8593
				options.position = {
8594
					my: "left top",
8595
					at: "left" + (left >= 0 ? "+" : "") + left + " " +
8596
						"top" + (top >= 0 ? "+" : "") + top,
8597
					of: that.window
8598
				};
8599
				$( this ).removeClass( "ui-dialog-dragging" );
8600
				that._unblockFrames();
8601
				that._trigger( "dragStop", event, filteredUi( ui ) );
8602
			}
8603
		});
8604
	},
8605
8606
	_makeResizable: function() {
8607
		var that = this,
8608
			options = this.options,
8609
			handles = options.resizable,
8610
			// .ui-resizable has position: relative defined in the stylesheet
8611
			// but dialogs have to use absolute or fixed positioning
8612
			position = this.uiDialog.css("position"),
8613
			resizeHandles = typeof handles === "string" ?
8614
				handles	:
8615
				"n,e,s,w,se,sw,ne,nw";
8616
8617
		function filteredUi( ui ) {
8618
			return {
8619
				originalPosition: ui.originalPosition,
8620
				originalSize: ui.originalSize,
8621
				position: ui.position,
8622
				size: ui.size
8623
			};
8624
		}
8625
8626
		this.uiDialog.resizable({
8627
			cancel: ".ui-dialog-content",
8628
			containment: "document",
8629
			alsoResize: this.element,
8630
			maxWidth: options.maxWidth,
8631
			maxHeight: options.maxHeight,
8632
			minWidth: options.minWidth,
8633
			minHeight: this._minHeight(),
8634
			handles: resizeHandles,
8635
			start: function( event, ui ) {
8636
				$( this ).addClass( "ui-dialog-resizing" );
8637
				that._blockFrames();
8638
				that._trigger( "resizeStart", event, filteredUi( ui ) );
8639
			},
8640
			resize: function( event, ui ) {
8641
				that._trigger( "resize", event, filteredUi( ui ) );
8642
			},
8643
			stop: function( event, ui ) {
8644
				var offset = that.uiDialog.offset(),
8645
					left = offset.left - that.document.scrollLeft(),
8646
					top = offset.top - that.document.scrollTop();
8647
8648
				options.height = that.uiDialog.height();
8649
				options.width = that.uiDialog.width();
8650
				options.position = {
8651
					my: "left top",
8652
					at: "left" + (left >= 0 ? "+" : "") + left + " " +
8653
						"top" + (top >= 0 ? "+" : "") + top,
8654
					of: that.window
8655
				};
8656
				$( this ).removeClass( "ui-dialog-resizing" );
8657
				that._unblockFrames();
8658
				that._trigger( "resizeStop", event, filteredUi( ui ) );
8659
			}
8660
		})
8661
		.css( "position", position );
8662
	},
8663
8664
	_trackFocus: function() {
8665
		this._on( this.widget(), {
8666
			focusin: function( event ) {
8667
				this._makeFocusTarget();
8668
				this._focusedElement = $( event.target );
8669
			}
8670
		});
8671
	},
8672
8673
	_makeFocusTarget: function() {
8674
		this._untrackInstance();
8675
		this._trackingInstances().unshift( this );
8676
	},
8677
8678
	_untrackInstance: function() {
8679
		var instances = this._trackingInstances(),
8680
			exists = $.inArray( this, instances );
8681
		if ( exists !== -1 ) {
8682
			instances.splice( exists, 1 );
8683
		}
8684
	},
8685
8686
	_trackingInstances: function() {
8687
		var instances = this.document.data( "ui-dialog-instances" );
8688
		if ( !instances ) {
8689
			instances = [];
8690
			this.document.data( "ui-dialog-instances", instances );
8691
		}
8692
		return instances;
8693
	},
8694
8695
	_minHeight: function() {
8696
		var options = this.options;
8697
8698
		return options.height === "auto" ?
8699
			options.minHeight :
8700
			Math.min( options.minHeight, options.height );
8701
	},
8702
8703
	_position: function() {
8704
		// Need to show the dialog to get the actual offset in the position plugin
8705
		var isVisible = this.uiDialog.is( ":visible" );
8706
		if ( !isVisible ) {
8707
			this.uiDialog.show();
8708
		}
8709
		this.uiDialog.position( this.options.position );
8710
		if ( !isVisible ) {
8711
			this.uiDialog.hide();
8712
		}
8713
	},
8714
8715
	_setOptions: function( options ) {
8716
		var that = this,
8717
			resize = false,
8718
			resizableOptions = {};
8719
8720
		$.each( options, function( key, value ) {
8721
			that._setOption( key, value );
8722
8723
			if ( key in that.sizeRelatedOptions ) {
8724
				resize = true;
8725
			}
8726
			if ( key in that.resizableRelatedOptions ) {
8727
				resizableOptions[ key ] = value;
8728
			}
8729
		});
8730
8731
		if ( resize ) {
8732
			this._size();
8733
			this._position();
8734
		}
8735
		if ( this.uiDialog.is( ":data(ui-resizable)" ) ) {
8736
			this.uiDialog.resizable( "option", resizableOptions );
8737
		}
8738
	},
8739
8740
	_setOption: function( key, value ) {
8741
		var isDraggable, isResizable,
8742
			uiDialog = this.uiDialog;
8743
8744
		if ( key === "dialogClass" ) {
8745
			uiDialog
8746
				.removeClass( this.options.dialogClass )
8747
				.addClass( value );
8748
		}
8749
8750
		if ( key === "disabled" ) {
8751
			return;
8752
		}
8753
8754
		this._super( key, value );
8755
8756
		if ( key === "appendTo" ) {
8757
			this.uiDialog.appendTo( this._appendTo() );
8758
		}
8759
8760
		if ( key === "buttons" ) {
8761
			this._createButtons();
8762
		}
8763
8764
		if ( key === "closeText" ) {
8765
			this.uiDialogTitlebarClose.button({
8766
				// Ensure that we always pass a string
8767
				label: "" + value
8768
			});
8769
		}
8770
8771
		if ( key === "draggable" ) {
8772
			isDraggable = uiDialog.is( ":data(ui-draggable)" );
8773
			if ( isDraggable && !value ) {
8774
				uiDialog.draggable( "destroy" );
8775
			}
8776
8777
			if ( !isDraggable && value ) {
8778
				this._makeDraggable();
8779
			}
8780
		}
8781
8782
		if ( key === "position" ) {
8783
			this._position();
8784
		}
8785
8786
		if ( key === "resizable" ) {
8787
			// currently resizable, becoming non-resizable
8788
			isResizable = uiDialog.is( ":data(ui-resizable)" );
8789
			if ( isResizable && !value ) {
8790
				uiDialog.resizable( "destroy" );
8791
			}
8792
8793
			// currently resizable, changing handles
8794
			if ( isResizable && typeof value === "string" ) {
8795
				uiDialog.resizable( "option", "handles", value );
8796
			}
8797
8798
			// currently non-resizable, becoming resizable
8799
			if ( !isResizable && value !== false ) {
8800
				this._makeResizable();
8801
			}
8802
		}
8803
8804
		if ( key === "title" ) {
8805
			this._title( this.uiDialogTitlebar.find( ".ui-dialog-title" ) );
8806
		}
8807
	},
8808
8809
	_size: function() {
8810
		// If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
8811
		// divs will both have width and height set, so we need to reset them
8812
		var nonContentHeight, minContentHeight, maxContentHeight,
8813
			options = this.options;
8814
8815
		// Reset content sizing
8816
		this.element.show().css({
8817
			width: "auto",
8818
			minHeight: 0,
8819
			maxHeight: "none",
8820
			height: 0
8821
		});
8822
8823
		if ( options.minWidth > options.width ) {
8824
			options.width = options.minWidth;
8825
		}
8826
8827
		// reset wrapper sizing
8828
		// determine the height of all the non-content elements
8829
		nonContentHeight = this.uiDialog.css({
8830
				height: "auto",
8831
				width: options.width
8832
			})
8833
			.outerHeight();
8834
		minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
8835
		maxContentHeight = typeof options.maxHeight === "number" ?
8836
			Math.max( 0, options.maxHeight - nonContentHeight ) :
8837
			"none";
8838
8839
		if ( options.height === "auto" ) {
8840
			this.element.css({
8841
				minHeight: minContentHeight,
8842
				maxHeight: maxContentHeight,
8843
				height: "auto"
8844
			});
8845
		} else {
8846
			this.element.height( Math.max( 0, options.height - nonContentHeight ) );
8847
		}
8848
8849
		if ( this.uiDialog.is( ":data(ui-resizable)" ) ) {
8850
			this.uiDialog.resizable( "option", "minHeight", this._minHeight() );
8851
		}
8852
	},
8853
8854
	_blockFrames: function() {
8855
		this.iframeBlocks = this.document.find( "iframe" ).map(function() {
8856
			var iframe = $( this );
8857
8858
			return $( "<div>" )
8859
				.css({
8860
					position: "absolute",
8861
					width: iframe.outerWidth(),
8862
					height: iframe.outerHeight()
8863
				})
8864
				.appendTo( iframe.parent() )
8865
				.offset( iframe.offset() )[0];
8866
		});
8867
	},
8868
8869
	_unblockFrames: function() {
8870
		if ( this.iframeBlocks ) {
8871
			this.iframeBlocks.remove();
8872
			delete this.iframeBlocks;
8873
		}
8874
	},
8875
8876
	_allowInteraction: function( event ) {
8877
		if ( $( event.target ).closest( ".ui-dialog" ).length ) {
8878
			return true;
8879
		}
8880
8881
		// TODO: Remove hack when datepicker implements
8882
		// the .ui-front logic (#8989)
8883
		return !!$( event.target ).closest( ".ui-datepicker" ).length;
8884
	},
8885
8886
	_createOverlay: function() {
8887
		if ( !this.options.modal ) {
8888
			return;
8889
		}
8890
8891
		// We use a delay in case the overlay is created from an
8892
		// event that we're going to be cancelling (#2804)
8893
		var isOpening = true;
8894
		this._delay(function() {
8895
			isOpening = false;
8896
		});
8897
8898
		if ( !this.document.data( "ui-dialog-overlays" ) ) {
8899
8900
			// Prevent use of anchors and inputs
8901
			// Using _on() for an event handler shared across many instances is
8902
			// safe because the dialogs stack and must be closed in reverse order
8903
			this._on( this.document, {
8904
				focusin: function( event ) {
8905
					if ( isOpening ) {
8906
						return;
8907
					}
8908
8909
					if ( !this._allowInteraction( event ) ) {
8910
						event.preventDefault();
8911
						this._trackingInstances()[ 0 ]._focusTabbable();
8912
					}
8913
				}
8914
			});
8915
		}
8916
8917
		this.overlay = $( "<div>" )
8918
			.addClass( "ui-widget-overlay ui-front" )
8919
			.appendTo( this._appendTo() );
8920
		this._on( this.overlay, {
8921
			mousedown: "_keepFocus"
8922
		});
8923
		this.document.data( "ui-dialog-overlays",
8924
			(this.document.data( "ui-dialog-overlays" ) || 0) + 1 );
8925
	},
8926
8927
	_destroyOverlay: function() {
8928
		if ( !this.options.modal ) {
8929
			return;
8930
		}
8931
8932
		if ( this.overlay ) {
8933
			var overlays = this.document.data( "ui-dialog-overlays" ) - 1;
8934
8935
			if ( !overlays ) {
8936
				this.document
8937
					.unbind( "focusin" )
8938
					.removeData( "ui-dialog-overlays" );
8939
			} else {
8940
				this.document.data( "ui-dialog-overlays", overlays );
8941
			}
8942
8943
			this.overlay.remove();
8944
			this.overlay = null;
8945
		}
8946
	}
8947
});
8948
8949
8950
/*!
8951
 * jQuery UI Droppable 1.11.4
8952
 * http://jqueryui.com
8953
 *
8954
 * Copyright jQuery Foundation and other contributors
8955
 * Released under the MIT license.
8956
 * http://jquery.org/license
8957
 *
8958
 * http://api.jqueryui.com/droppable/
8959
 */
8960
8961
8962
$.widget( "ui.droppable", {
8963
	version: "1.11.4",
8964
	widgetEventPrefix: "drop",
8965
	options: {
8966
		accept: "*",
8967
		activeClass: false,
8968
		addClasses: true,
8969
		greedy: false,
8970
		hoverClass: false,
8971
		scope: "default",
8972
		tolerance: "intersect",
8973
8974
		// callbacks
8975
		activate: null,
8976
		deactivate: null,
8977
		drop: null,
8978
		out: null,
8979
		over: null
8980
	},
8981
	_create: function() {
8982
8983
		var proportions,
8984
			o = this.options,
8985
			accept = o.accept;
8986
8987
		this.isover = false;
8988
		this.isout = true;
8989
8990
		this.accept = $.isFunction( accept ) ? accept : function( d ) {
8991
			return d.is( accept );
8992
		};
8993
8994
		this.proportions = function( /* valueToWrite */ ) {
8995
			if ( arguments.length ) {
8996
				// Store the droppable's proportions
8997
				proportions = arguments[ 0 ];
8998
			} else {
8999
				// Retrieve or derive the droppable's proportions
9000
				return proportions ?
9001
					proportions :
9002
					proportions = {
9003
						width: this.element[ 0 ].offsetWidth,
9004
						height: this.element[ 0 ].offsetHeight
9005
					};
9006
			}
9007
		};
9008
9009
		this._addToManager( o.scope );
9010
9011
		o.addClasses && this.element.addClass( "ui-droppable" );
9012
9013
	},
9014
9015
	_addToManager: function( scope ) {
9016
		// Add the reference and positions to the manager
9017
		$.ui.ddmanager.droppables[ scope ] = $.ui.ddmanager.droppables[ scope ] || [];
9018
		$.ui.ddmanager.droppables[ scope ].push( this );
9019
	},
9020
9021
	_splice: function( drop ) {
9022
		var i = 0;
9023
		for ( ; i < drop.length; i++ ) {
9024
			if ( drop[ i ] === this ) {
9025
				drop.splice( i, 1 );
9026
			}
9027
		}
9028
	},
9029
9030
	_destroy: function() {
9031
		var drop = $.ui.ddmanager.droppables[ this.options.scope ];
9032
9033
		this._splice( drop );
9034
9035
		this.element.removeClass( "ui-droppable ui-droppable-disabled" );
9036
	},
9037
9038
	_setOption: function( key, value ) {
9039
9040
		if ( key === "accept" ) {
9041
			this.accept = $.isFunction( value ) ? value : function( d ) {
9042
				return d.is( value );
9043
			};
9044
		} else if ( key === "scope" ) {
9045
			var drop = $.ui.ddmanager.droppables[ this.options.scope ];
9046
9047
			this._splice( drop );
9048
			this._addToManager( value );
9049
		}
9050
9051
		this._super( key, value );
9052
	},
9053
9054
	_activate: function( event ) {
9055
		var draggable = $.ui.ddmanager.current;
9056
		if ( this.options.activeClass ) {
9057
			this.element.addClass( this.options.activeClass );
9058
		}
9059
		if ( draggable ){
9060
			this._trigger( "activate", event, this.ui( draggable ) );
9061
		}
9062
	},
9063
9064
	_deactivate: function( event ) {
9065
		var draggable = $.ui.ddmanager.current;
9066
		if ( this.options.activeClass ) {
9067
			this.element.removeClass( this.options.activeClass );
9068
		}
9069
		if ( draggable ){
9070
			this._trigger( "deactivate", event, this.ui( draggable ) );
9071
		}
9072
	},
9073
9074
	_over: function( event ) {
9075
9076
		var draggable = $.ui.ddmanager.current;
9077
9078
		// Bail if draggable and droppable are same element
9079
		if ( !draggable || ( draggable.currentItem || draggable.element )[ 0 ] === this.element[ 0 ] ) {
9080
			return;
9081
		}
9082
9083
		if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem || draggable.element ) ) ) {
9084
			if ( this.options.hoverClass ) {
9085
				this.element.addClass( this.options.hoverClass );
9086
			}
9087
			this._trigger( "over", event, this.ui( draggable ) );
9088
		}
9089
9090
	},
9091
9092
	_out: function( event ) {
9093
9094
		var draggable = $.ui.ddmanager.current;
9095
9096
		// Bail if draggable and droppable are same element
9097
		if ( !draggable || ( draggable.currentItem || draggable.element )[ 0 ] === this.element[ 0 ] ) {
9098
			return;
9099
		}
9100
9101
		if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem || draggable.element ) ) ) {
9102
			if ( this.options.hoverClass ) {
9103
				this.element.removeClass( this.options.hoverClass );
9104
			}
9105
			this._trigger( "out", event, this.ui( draggable ) );
9106
		}
9107
9108
	},
9109
9110
	_drop: function( event, custom ) {
9111
9112
		var draggable = custom || $.ui.ddmanager.current,
9113
			childrenIntersection = false;
9114
9115
		// Bail if draggable and droppable are same element
9116
		if ( !draggable || ( draggable.currentItem || draggable.element )[ 0 ] === this.element[ 0 ] ) {
9117
			return false;
9118
		}
9119
9120
		this.element.find( ":data(ui-droppable)" ).not( ".ui-draggable-dragging" ).each(function() {
9121
			var inst = $( this ).droppable( "instance" );
9122
			if (
9123
				inst.options.greedy &&
9124
				!inst.options.disabled &&
9125
				inst.options.scope === draggable.options.scope &&
9126
				inst.accept.call( inst.element[ 0 ], ( draggable.currentItem || draggable.element ) ) &&
9127
				$.ui.intersect( draggable, $.extend( inst, { offset: inst.element.offset() } ), inst.options.tolerance, event )
9128
			) { childrenIntersection = true; return false; }
9129
		});
9130
		if ( childrenIntersection ) {
9131
			return false;
9132
		}
9133
9134
		if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem || draggable.element ) ) ) {
9135
			if ( this.options.activeClass ) {
9136
				this.element.removeClass( this.options.activeClass );
9137
			}
9138
			if ( this.options.hoverClass ) {
9139
				this.element.removeClass( this.options.hoverClass );
9140
			}
9141
			this._trigger( "drop", event, this.ui( draggable ) );
9142
			return this.element;
9143
		}
9144
9145
		return false;
9146
9147
	},
9148
9149
	ui: function( c ) {
9150
		return {
9151
			draggable: ( c.currentItem || c.element ),
9152
			helper: c.helper,
9153
			position: c.position,
9154
			offset: c.positionAbs
9155
		};
9156
	}
9157
9158
});
9159
9160
$.ui.intersect = (function() {
9161
	function isOverAxis( x, reference, size ) {
9162
		return ( x >= reference ) && ( x < ( reference + size ) );
9163
	}
9164
9165
	return function( draggable, droppable, toleranceMode, event ) {
9166
9167
		if ( !droppable.offset ) {
9168
			return false;
9169
		}
9170
9171
		var x1 = ( draggable.positionAbs || draggable.position.absolute ).left + draggable.margins.left,
9172
			y1 = ( draggable.positionAbs || draggable.position.absolute ).top + draggable.margins.top,
9173
			x2 = x1 + draggable.helperProportions.width,
9174
			y2 = y1 + draggable.helperProportions.height,
9175
			l = droppable.offset.left,
9176
			t = droppable.offset.top,
9177
			r = l + droppable.proportions().width,
9178
			b = t + droppable.proportions().height;
9179
9180
		switch ( toleranceMode ) {
9181
		case "fit":
9182
			return ( l <= x1 && x2 <= r && t <= y1 && y2 <= b );
9183
		case "intersect":
9184
			return ( l < x1 + ( draggable.helperProportions.width / 2 ) && // Right Half
9185
				x2 - ( draggable.helperProportions.width / 2 ) < r && // Left Half
9186
				t < y1 + ( draggable.helperProportions.height / 2 ) && // Bottom Half
9187
				y2 - ( draggable.helperProportions.height / 2 ) < b ); // Top Half
9188
		case "pointer":
9189
			return isOverAxis( event.pageY, t, droppable.proportions().height ) && isOverAxis( event.pageX, l, droppable.proportions().width );
9190
		case "touch":
9191
			return (
9192
				( y1 >= t && y1 <= b ) || // Top edge touching
9193
				( y2 >= t && y2 <= b ) || // Bottom edge touching
9194
				( y1 < t && y2 > b ) // Surrounded vertically
9195
			) && (
9196
				( x1 >= l && x1 <= r ) || // Left edge touching
9197
				( x2 >= l && x2 <= r ) || // Right edge touching
9198
				( x1 < l && x2 > r ) // Surrounded horizontally
9199
			);
9200
		default:
9201
			return false;
9202
		}
9203
	};
9204
})();
9205
9206
/*
9207
	This manager tracks offsets of draggables and droppables
9208
*/
9209
$.ui.ddmanager = {
9210
	current: null,
9211
	droppables: { "default": [] },
9212
	prepareOffsets: function( t, event ) {
9213
9214
		var i, j,
9215
			m = $.ui.ddmanager.droppables[ t.options.scope ] || [],
9216
			type = event ? event.type : null, // workaround for #2317
9217
			list = ( t.currentItem || t.element ).find( ":data(ui-droppable)" ).addBack();
9218
9219
		droppablesLoop: for ( i = 0; i < m.length; i++ ) {
9220
9221
			// No disabled and non-accepted
9222
			if ( m[ i ].options.disabled || ( t && !m[ i ].accept.call( m[ i ].element[ 0 ], ( t.currentItem || t.element ) ) ) ) {
9223
				continue;
9224
			}
9225
9226
			// Filter out elements in the current dragged item
9227
			for ( j = 0; j < list.length; j++ ) {
9228
				if ( list[ j ] === m[ i ].element[ 0 ] ) {
9229
					m[ i ].proportions().height = 0;
9230
					continue droppablesLoop;
9231
				}
9232
			}
9233
9234
			m[ i ].visible = m[ i ].element.css( "display" ) !== "none";
9235
			if ( !m[ i ].visible ) {
9236
				continue;
9237
			}
9238
9239
			// Activate the droppable if used directly from draggables
9240
			if ( type === "mousedown" ) {
9241
				m[ i ]._activate.call( m[ i ], event );
9242
			}
9243
9244
			m[ i ].offset = m[ i ].element.offset();
9245
			m[ i ].proportions({ width: m[ i ].element[ 0 ].offsetWidth, height: m[ i ].element[ 0 ].offsetHeight });
9246
9247
		}
9248
9249
	},
9250
	drop: function( draggable, event ) {
9251
9252
		var dropped = false;
9253
		// Create a copy of the droppables in case the list changes during the drop (#9116)
9254
		$.each( ( $.ui.ddmanager.droppables[ draggable.options.scope ] || [] ).slice(), function() {
9255
9256
			if ( !this.options ) {
9257
				return;
9258
			}
9259
			if ( !this.options.disabled && this.visible && $.ui.intersect( draggable, this, this.options.tolerance, event ) ) {
9260
				dropped = this._drop.call( this, event ) || dropped;
9261
			}
9262
9263
			if ( !this.options.disabled && this.visible && this.accept.call( this.element[ 0 ], ( draggable.currentItem || draggable.element ) ) ) {
9264
				this.isout = true;
9265
				this.isover = false;
9266
				this._deactivate.call( this, event );
9267
			}
9268
9269
		});
9270
		return dropped;
9271
9272
	},
9273
	dragStart: function( draggable, event ) {
9274
		// Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003)
9275
		draggable.element.parentsUntil( "body" ).bind( "scroll.droppable", function() {
9276
			if ( !draggable.options.refreshPositions ) {
9277
				$.ui.ddmanager.prepareOffsets( draggable, event );
9278
			}
9279
		});
9280
	},
9281
	drag: function( draggable, event ) {
9282
9283
		// If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
9284
		if ( draggable.options.refreshPositions ) {
9285
			$.ui.ddmanager.prepareOffsets( draggable, event );
9286
		}
9287
9288
		// Run through all droppables and check their positions based on specific tolerance options
9289
		$.each( $.ui.ddmanager.droppables[ draggable.options.scope ] || [], function() {
9290
9291
			if ( this.options.disabled || this.greedyChild || !this.visible ) {
9292
				return;
9293
			}
9294
9295
			var parentInstance, scope, parent,
9296
				intersects = $.ui.intersect( draggable, this, this.options.tolerance, event ),
9297
				c = !intersects && this.isover ? "isout" : ( intersects && !this.isover ? "isover" : null );
9298
			if ( !c ) {
9299
				return;
9300
			}
9301
9302
			if ( this.options.greedy ) {
9303
				// find droppable parents with same scope
9304
				scope = this.options.scope;
9305
				parent = this.element.parents( ":data(ui-droppable)" ).filter(function() {
9306
					return $( this ).droppable( "instance" ).options.scope === scope;
9307
				});
9308
9309
				if ( parent.length ) {
9310
					parentInstance = $( parent[ 0 ] ).droppable( "instance" );
9311
					parentInstance.greedyChild = ( c === "isover" );
9312
				}
9313
			}
9314
9315
			// we just moved into a greedy child
9316
			if ( parentInstance && c === "isover" ) {
9317
				parentInstance.isover = false;
9318
				parentInstance.isout = true;
9319
				parentInstance._out.call( parentInstance, event );
9320
			}
9321
9322
			this[ c ] = true;
9323
			this[c === "isout" ? "isover" : "isout"] = false;
9324
			this[c === "isover" ? "_over" : "_out"].call( this, event );
9325
9326
			// we just moved out of a greedy child
9327
			if ( parentInstance && c === "isout" ) {
9328
				parentInstance.isout = false;
9329
				parentInstance.isover = true;
9330
				parentInstance._over.call( parentInstance, event );
9331
			}
9332
		});
9333
9334
	},
9335
	dragStop: function( draggable, event ) {
9336
		draggable.element.parentsUntil( "body" ).unbind( "scroll.droppable" );
9337
		// Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003)
9338
		if ( !draggable.options.refreshPositions ) {
9339
			$.ui.ddmanager.prepareOffsets( draggable, event );
9340
		}
9341
	}
9342
};
9343
9344
var droppable = $.ui.droppable;
9345
9346
9347
/*!
9348
 * jQuery UI Effects 1.11.4
9349
 * http://jqueryui.com
9350
 *
9351
 * Copyright jQuery Foundation and other contributors
9352
 * Released under the MIT license.
9353
 * http://jquery.org/license
9354
 *
9355
 * http://api.jqueryui.com/category/effects-core/
9356
 */
9357
9358
9359
var dataSpace = "ui-effects-",
9360
9361
	// Create a local jQuery because jQuery Color relies on it and the
9362
	// global may not exist with AMD and a custom build (#10199)
9363
	jQuery = $;
9364
9365
$.effects = {
9366
	effect: {}
9367
};
9368
9369
/*!
9370
 * jQuery Color Animations v2.1.2
9371
 * https://github.com/jquery/jquery-color
9372
 *
9373
 * Copyright 2014 jQuery Foundation and other contributors
9374
 * Released under the MIT license.
9375
 * http://jquery.org/license
9376
 *
9377
 * Date: Wed Jan 16 08:47:09 2013 -0600
9378
 */
9379
(function( jQuery, undefined ) {
9380
9381
	var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor",
9382
9383
	// plusequals test for += 100 -= 100
9384
	rplusequals = /^([\-+])=\s*(\d+\.?\d*)/,
9385
	// a set of RE's that can match strings and generate color tuples.
9386
	stringParsers = [ {
9387
			re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
9388
			parse: function( execResult ) {
9389
				return [
9390
					execResult[ 1 ],
9391
					execResult[ 2 ],
9392
					execResult[ 3 ],
9393
					execResult[ 4 ]
9394
				];
9395
			}
9396
		}, {
9397
			re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
9398
			parse: function( execResult ) {
9399
				return [
9400
					execResult[ 1 ] * 2.55,
9401
					execResult[ 2 ] * 2.55,
9402
					execResult[ 3 ] * 2.55,
9403
					execResult[ 4 ]
9404
				];
9405
			}
9406
		}, {
9407
			// this regex ignores A-F because it's compared against an already lowercased string
9408
			re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/,
9409
			parse: function( execResult ) {
9410
				return [
9411
					parseInt( execResult[ 1 ], 16 ),
9412
					parseInt( execResult[ 2 ], 16 ),
9413
					parseInt( execResult[ 3 ], 16 )
9414
				];
9415
			}
9416
		}, {
9417
			// this regex ignores A-F because it's compared against an already lowercased string
9418
			re: /#([a-f0-9])([a-f0-9])([a-f0-9])/,
9419
			parse: function( execResult ) {
9420
				return [
9421
					parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ),
9422
					parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ),
9423
					parseInt( execResult[ 3 ] + execResult[ 3 ], 16 )
9424
				];
9425
			}
9426
		}, {
9427
			re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
9428
			space: "hsla",
9429
			parse: function( execResult ) {
9430
				return [
9431
					execResult[ 1 ],
9432
					execResult[ 2 ] / 100,
9433
					execResult[ 3 ] / 100,
9434
					execResult[ 4 ]
9435
				];
9436
			}
9437
		} ],
9438
9439
	// jQuery.Color( )
9440
	color = jQuery.Color = function( color, green, blue, alpha ) {
9441
		return new jQuery.Color.fn.parse( color, green, blue, alpha );
9442
	},
9443
	spaces = {
9444
		rgba: {
9445
			props: {
9446
				red: {
9447
					idx: 0,
9448
					type: "byte"
9449
				},
9450
				green: {
9451
					idx: 1,
9452
					type: "byte"
9453
				},
9454
				blue: {
9455
					idx: 2,
9456
					type: "byte"
9457
				}
9458
			}
9459
		},
9460
9461
		hsla: {
9462
			props: {
9463
				hue: {
9464
					idx: 0,
9465
					type: "degrees"
9466
				},
9467
				saturation: {
9468
					idx: 1,
9469
					type: "percent"
9470
				},
9471
				lightness: {
9472
					idx: 2,
9473
					type: "percent"
9474
				}
9475
			}
9476
		}
9477
	},
9478
	propTypes = {
9479
		"byte": {
9480
			floor: true,
9481
			max: 255
9482
		},
9483
		"percent": {
9484
			max: 1
9485
		},
9486
		"degrees": {
9487
			mod: 360,
9488
			floor: true
9489
		}
9490
	},
9491
	support = color.support = {},
9492
9493
	// element for support tests
9494
	supportElem = jQuery( "<p>" )[ 0 ],
9495
9496
	// colors = jQuery.Color.names
9497
	colors,
9498
9499
	// local aliases of functions called often
9500
	each = jQuery.each;
9501
9502
// determine rgba support immediately
9503
supportElem.style.cssText = "background-color:rgba(1,1,1,.5)";
9504
support.rgba = supportElem.style.backgroundColor.indexOf( "rgba" ) > -1;
9505
9506
// define cache name and alpha properties
9507
// for rgba and hsla spaces
9508
each( spaces, function( spaceName, space ) {
9509
	space.cache = "_" + spaceName;
9510
	space.props.alpha = {
9511
		idx: 3,
9512
		type: "percent",
9513
		def: 1
9514
	};
9515
});
9516
9517
function clamp( value, prop, allowEmpty ) {
9518
	var type = propTypes[ prop.type ] || {};
9519
9520
	if ( value == null ) {
9521
		return (allowEmpty || !prop.def) ? null : prop.def;
9522
	}
9523
9524
	// ~~ is an short way of doing floor for positive numbers
9525
	value = type.floor ? ~~value : parseFloat( value );
9526
9527
	// IE will pass in empty strings as value for alpha,
9528
	// which will hit this case
9529
	if ( isNaN( value ) ) {
9530
		return prop.def;
9531
	}
9532
9533
	if ( type.mod ) {
9534
		// we add mod before modding to make sure that negatives values
9535
		// get converted properly: -10 -> 350
9536
		return (value + type.mod) % type.mod;
9537
	}
9538
9539
	// for now all property types without mod have min and max
9540
	return 0 > value ? 0 : type.max < value ? type.max : value;
9541
}
9542
9543
function stringParse( string ) {
9544
	var inst = color(),
9545
		rgba = inst._rgba = [];
9546
9547
	string = string.toLowerCase();
9548
9549
	each( stringParsers, function( i, parser ) {
9550
		var parsed,
9551
			match = parser.re.exec( string ),
9552
			values = match && parser.parse( match ),
9553
			spaceName = parser.space || "rgba";
9554
9555
		if ( values ) {
9556
			parsed = inst[ spaceName ]( values );
9557
9558
			// if this was an rgba parse the assignment might happen twice
9559
			// oh well....
9560
			inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ];
9561
			rgba = inst._rgba = parsed._rgba;
9562
9563
			// exit each( stringParsers ) here because we matched
9564
			return false;
9565
		}
9566
	});
9567
9568
	// Found a stringParser that handled it
9569
	if ( rgba.length ) {
9570
9571
		// if this came from a parsed string, force "transparent" when alpha is 0
9572
		// chrome, (and maybe others) return "transparent" as rgba(0,0,0,0)
9573
		if ( rgba.join() === "0,0,0,0" ) {
9574
			jQuery.extend( rgba, colors.transparent );
9575
		}
9576
		return inst;
9577
	}
9578
9579
	// named colors
9580
	return colors[ string ];
9581
}
9582
9583
color.fn = jQuery.extend( color.prototype, {
9584
	parse: function( red, green, blue, alpha ) {
9585
		if ( red === undefined ) {
9586
			this._rgba = [ null, null, null, null ];
9587
			return this;
9588
		}
9589
		if ( red.jquery || red.nodeType ) {
9590
			red = jQuery( red ).css( green );
9591
			green = undefined;
9592
		}
9593
9594
		var inst = this,
9595
			type = jQuery.type( red ),
9596
			rgba = this._rgba = [];
9597
9598
		// more than 1 argument specified - assume ( red, green, blue, alpha )
9599
		if ( green !== undefined ) {
9600
			red = [ red, green, blue, alpha ];
9601
			type = "array";
9602
		}
9603
9604
		if ( type === "string" ) {
9605
			return this.parse( stringParse( red ) || colors._default );
9606
		}
9607
9608
		if ( type === "array" ) {
9609
			each( spaces.rgba.props, function( key, prop ) {
9610
				rgba[ prop.idx ] = clamp( red[ prop.idx ], prop );
9611
			});
9612
			return this;
9613
		}
9614
9615
		if ( type === "object" ) {
9616
			if ( red instanceof color ) {
9617
				each( spaces, function( spaceName, space ) {
9618
					if ( red[ space.cache ] ) {
9619
						inst[ space.cache ] = red[ space.cache ].slice();
9620
					}
9621
				});
9622
			} else {
9623
				each( spaces, function( spaceName, space ) {
9624
					var cache = space.cache;
9625
					each( space.props, function( key, prop ) {
9626
9627
						// if the cache doesn't exist, and we know how to convert
9628
						if ( !inst[ cache ] && space.to ) {
9629
9630
							// if the value was null, we don't need to copy it
9631
							// if the key was alpha, we don't need to copy it either
9632
							if ( key === "alpha" || red[ key ] == null ) {
9633
								return;
9634
							}
9635
							inst[ cache ] = space.to( inst._rgba );
9636
						}
9637
9638
						// this is the only case where we allow nulls for ALL properties.
9639
						// call clamp with alwaysAllowEmpty
9640
						inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true );
9641
					});
9642
9643
					// everything defined but alpha?
9644
					if ( inst[ cache ] && jQuery.inArray( null, inst[ cache ].slice( 0, 3 ) ) < 0 ) {
9645
						// use the default of 1
9646
						inst[ cache ][ 3 ] = 1;
9647
						if ( space.from ) {
9648
							inst._rgba = space.from( inst[ cache ] );
9649
						}
9650
					}
9651
				});
9652
			}
9653
			return this;
9654
		}
9655
	},
9656
	is: function( compare ) {
9657
		var is = color( compare ),
9658
			same = true,
9659
			inst = this;
9660
9661
		each( spaces, function( _, space ) {
9662
			var localCache,
9663
				isCache = is[ space.cache ];
9664
			if (isCache) {
9665
				localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || [];
9666
				each( space.props, function( _, prop ) {
9667
					if ( isCache[ prop.idx ] != null ) {
9668
						same = ( isCache[ prop.idx ] === localCache[ prop.idx ] );
9669
						return same;
9670
					}
9671
				});
9672
			}
9673
			return same;
9674
		});
9675
		return same;
9676
	},
9677
	_space: function() {
9678
		var used = [],
9679
			inst = this;
9680
		each( spaces, function( spaceName, space ) {
9681
			if ( inst[ space.cache ] ) {
9682
				used.push( spaceName );
9683
			}
9684
		});
9685
		return used.pop();
9686
	},
9687
	transition: function( other, distance ) {
9688
		var end = color( other ),
9689
			spaceName = end._space(),
9690
			space = spaces[ spaceName ],
9691
			startColor = this.alpha() === 0 ? color( "transparent" ) : this,
9692
			start = startColor[ space.cache ] || space.to( startColor._rgba ),
9693
			result = start.slice();
9694
9695
		end = end[ space.cache ];
9696
		each( space.props, function( key, prop ) {
9697
			var index = prop.idx,
9698
				startValue = start[ index ],
9699
				endValue = end[ index ],
9700
				type = propTypes[ prop.type ] || {};
9701
9702
			// if null, don't override start value
9703
			if ( endValue === null ) {
9704
				return;
9705
			}
9706
			// if null - use end
9707
			if ( startValue === null ) {
9708
				result[ index ] = endValue;
9709
			} else {
9710
				if ( type.mod ) {
9711
					if ( endValue - startValue > type.mod / 2 ) {
9712
						startValue += type.mod;
9713
					} else if ( startValue - endValue > type.mod / 2 ) {
9714
						startValue -= type.mod;
9715
					}
9716
				}
9717
				result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop );
9718
			}
9719
		});
9720
		return this[ spaceName ]( result );
9721
	},
9722
	blend: function( opaque ) {
9723
		// if we are already opaque - return ourself
9724
		if ( this._rgba[ 3 ] === 1 ) {
9725
			return this;
9726
		}
9727
9728
		var rgb = this._rgba.slice(),
9729
			a = rgb.pop(),
9730
			blend = color( opaque )._rgba;
9731
9732
		return color( jQuery.map( rgb, function( v, i ) {
9733
			return ( 1 - a ) * blend[ i ] + a * v;
9734
		}));
9735
	},
9736
	toRgbaString: function() {
9737
		var prefix = "rgba(",
9738
			rgba = jQuery.map( this._rgba, function( v, i ) {
9739
				return v == null ? ( i > 2 ? 1 : 0 ) : v;
9740
			});
9741
9742
		if ( rgba[ 3 ] === 1 ) {
9743
			rgba.pop();
9744
			prefix = "rgb(";
9745
		}
9746
9747
		return prefix + rgba.join() + ")";
9748
	},
9749
	toHslaString: function() {
9750
		var prefix = "hsla(",
9751
			hsla = jQuery.map( this.hsla(), function( v, i ) {
9752
				if ( v == null ) {
9753
					v = i > 2 ? 1 : 0;
9754
				}
9755
9756
				// catch 1 and 2
9757
				if ( i && i < 3 ) {
9758
					v = Math.round( v * 100 ) + "%";
9759
				}
9760
				return v;
9761
			});
9762
9763
		if ( hsla[ 3 ] === 1 ) {
9764
			hsla.pop();
9765
			prefix = "hsl(";
9766
		}
9767
		return prefix + hsla.join() + ")";
9768
	},
9769
	toHexString: function( includeAlpha ) {
9770
		var rgba = this._rgba.slice(),
9771
			alpha = rgba.pop();
9772
9773
		if ( includeAlpha ) {
9774
			rgba.push( ~~( alpha * 255 ) );
9775
		}
9776
9777
		return "#" + jQuery.map( rgba, function( v ) {
9778
9779
			// default to 0 when nulls exist
9780
			v = ( v || 0 ).toString( 16 );
9781
			return v.length === 1 ? "0" + v : v;
9782
		}).join("");
9783
	},
9784
	toString: function() {
9785
		return this._rgba[ 3 ] === 0 ? "transparent" : this.toRgbaString();
9786
	}
9787
});
9788
color.fn.parse.prototype = color.fn;
9789
9790
// hsla conversions adapted from:
9791
// https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021
9792
9793
function hue2rgb( p, q, h ) {
9794
	h = ( h + 1 ) % 1;
9795
	if ( h * 6 < 1 ) {
9796
		return p + ( q - p ) * h * 6;
9797
	}
9798
	if ( h * 2 < 1) {
9799
		return q;
9800
	}
9801
	if ( h * 3 < 2 ) {
9802
		return p + ( q - p ) * ( ( 2 / 3 ) - h ) * 6;
9803
	}
9804
	return p;
9805
}
9806
9807
spaces.hsla.to = function( rgba ) {
9808
	if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) {
9809
		return [ null, null, null, rgba[ 3 ] ];
9810
	}
9811
	var r = rgba[ 0 ] / 255,
9812
		g = rgba[ 1 ] / 255,
9813
		b = rgba[ 2 ] / 255,
9814
		a = rgba[ 3 ],
9815
		max = Math.max( r, g, b ),
9816
		min = Math.min( r, g, b ),
9817
		diff = max - min,
9818
		add = max + min,
9819
		l = add * 0.5,
9820
		h, s;
9821
9822
	if ( min === max ) {
9823
		h = 0;
9824
	} else if ( r === max ) {
9825
		h = ( 60 * ( g - b ) / diff ) + 360;
9826
	} else if ( g === max ) {
9827
		h = ( 60 * ( b - r ) / diff ) + 120;
9828
	} else {
9829
		h = ( 60 * ( r - g ) / diff ) + 240;
9830
	}
9831
9832
	// chroma (diff) == 0 means greyscale which, by definition, saturation = 0%
9833
	// otherwise, saturation is based on the ratio of chroma (diff) to lightness (add)
9834
	if ( diff === 0 ) {
9835
		s = 0;
9836
	} else if ( l <= 0.5 ) {
9837
		s = diff / add;
9838
	} else {
9839
		s = diff / ( 2 - add );
9840
	}
9841
	return [ Math.round(h) % 360, s, l, a == null ? 1 : a ];
9842
};
9843
9844
spaces.hsla.from = function( hsla ) {
9845
	if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) {
9846
		return [ null, null, null, hsla[ 3 ] ];
9847
	}
9848
	var h = hsla[ 0 ] / 360,
9849
		s = hsla[ 1 ],
9850
		l = hsla[ 2 ],
9851
		a = hsla[ 3 ],
9852
		q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s,
9853
		p = 2 * l - q;
9854
9855
	return [
9856
		Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ),
9857
		Math.round( hue2rgb( p, q, h ) * 255 ),
9858
		Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ),
9859
		a
9860
	];
9861
};
9862
9863
each( spaces, function( spaceName, space ) {
9864
	var props = space.props,
9865
		cache = space.cache,
9866
		to = space.to,
9867
		from = space.from;
9868
9869
	// makes rgba() and hsla()
9870
	color.fn[ spaceName ] = function( value ) {
9871
9872
		// generate a cache for this space if it doesn't exist
9873
		if ( to && !this[ cache ] ) {
9874
			this[ cache ] = to( this._rgba );
9875
		}
9876
		if ( value === undefined ) {
9877
			return this[ cache ].slice();
9878
		}
9879
9880
		var ret,
9881
			type = jQuery.type( value ),
9882
			arr = ( type === "array" || type === "object" ) ? value : arguments,
9883
			local = this[ cache ].slice();
9884
9885
		each( props, function( key, prop ) {
9886
			var val = arr[ type === "object" ? key : prop.idx ];
9887
			if ( val == null ) {
9888
				val = local[ prop.idx ];
9889
			}
9890
			local[ prop.idx ] = clamp( val, prop );
9891
		});
9892
9893
		if ( from ) {
9894
			ret = color( from( local ) );
9895
			ret[ cache ] = local;
9896
			return ret;
9897
		} else {
9898
			return color( local );
9899
		}
9900
	};
9901
9902
	// makes red() green() blue() alpha() hue() saturation() lightness()
9903
	each( props, function( key, prop ) {
9904
		// alpha is included in more than one space
9905
		if ( color.fn[ key ] ) {
9906
			return;
9907
		}
9908
		color.fn[ key ] = function( value ) {
9909
			var vtype = jQuery.type( value ),
9910
				fn = ( key === "alpha" ? ( this._hsla ? "hsla" : "rgba" ) : spaceName ),
9911
				local = this[ fn ](),
9912
				cur = local[ prop.idx ],
9913
				match;
9914
9915
			if ( vtype === "undefined" ) {
9916
				return cur;
9917
			}
9918
9919
			if ( vtype === "function" ) {
9920
				value = value.call( this, cur );
9921
				vtype = jQuery.type( value );
9922
			}
9923
			if ( value == null && prop.empty ) {
9924
				return this;
9925
			}
9926
			if ( vtype === "string" ) {
9927
				match = rplusequals.exec( value );
9928
				if ( match ) {
9929
					value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 );
9930
				}
9931
			}
9932
			local[ prop.idx ] = value;
9933
			return this[ fn ]( local );
9934
		};
9935
	});
9936
});
9937
9938
// add cssHook and .fx.step function for each named hook.
9939
// accept a space separated string of properties
9940
color.hook = function( hook ) {
9941
	var hooks = hook.split( " " );
9942
	each( hooks, function( i, hook ) {
9943
		jQuery.cssHooks[ hook ] = {
9944
			set: function( elem, value ) {
9945
				var parsed, curElem,
9946
					backgroundColor = "";
9947
9948
				if ( value !== "transparent" && ( jQuery.type( value ) !== "string" || ( parsed = stringParse( value ) ) ) ) {
9949
					value = color( parsed || value );
9950
					if ( !support.rgba && value._rgba[ 3 ] !== 1 ) {
9951
						curElem = hook === "backgroundColor" ? elem.parentNode : elem;
9952
						while (
9953
							(backgroundColor === "" || backgroundColor === "transparent") &&
9954
							curElem && curElem.style
9955
						) {
9956
							try {
9957
								backgroundColor = jQuery.css( curElem, "backgroundColor" );
9958
								curElem = curElem.parentNode;
9959
							} catch ( e ) {
9960
							}
9961
						}
9962
9963
						value = value.blend( backgroundColor && backgroundColor !== "transparent" ?
9964
							backgroundColor :
9965
							"_default" );
9966
					}
9967
9968
					value = value.toRgbaString();
9969
				}
9970
				try {
9971
					elem.style[ hook ] = value;
9972
				} catch ( e ) {
9973
					// wrapped to prevent IE from throwing errors on "invalid" values like 'auto' or 'inherit'
9974
				}
9975
			}
9976
		};
9977
		jQuery.fx.step[ hook ] = function( fx ) {
9978
			if ( !fx.colorInit ) {
9979
				fx.start = color( fx.elem, hook );
9980
				fx.end = color( fx.end );
9981
				fx.colorInit = true;
9982
			}
9983
			jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) );
9984
		};
9985
	});
9986
9987
};
9988
9989
color.hook( stepHooks );
9990
9991
jQuery.cssHooks.borderColor = {
9992
	expand: function( value ) {
9993
		var expanded = {};
9994
9995
		each( [ "Top", "Right", "Bottom", "Left" ], function( i, part ) {
9996
			expanded[ "border" + part + "Color" ] = value;
9997
		});
9998
		return expanded;
9999
	}
10000
};
10001
10002
// Basic color names only.
10003
// Usage of any of the other color names requires adding yourself or including
10004
// jquery.color.svg-names.js.
10005
colors = jQuery.Color.names = {
10006
	// 4.1. Basic color keywords
10007
	aqua: "#00ffff",
10008
	black: "#000000",
10009
	blue: "#0000ff",
10010
	fuchsia: "#ff00ff",
10011
	gray: "#808080",
10012
	green: "#008000",
10013
	lime: "#00ff00",
10014
	maroon: "#800000",
10015
	navy: "#000080",
10016
	olive: "#808000",
10017
	purple: "#800080",
10018
	red: "#ff0000",
10019
	silver: "#c0c0c0",
10020
	teal: "#008080",
10021
	white: "#ffffff",
10022
	yellow: "#ffff00",
10023
10024
	// 4.2.3. "transparent" color keyword
10025
	transparent: [ null, null, null, 0 ],
10026
10027
	_default: "#ffffff"
10028
};
10029
10030
})( jQuery );
10031
10032
/******************************************************************************/
10033
/****************************** CLASS ANIMATIONS ******************************/
10034
/******************************************************************************/
10035
(function() {
10036
10037
var classAnimationActions = [ "add", "remove", "toggle" ],
10038
	shorthandStyles = {
10039
		border: 1,
10040
		borderBottom: 1,
10041
		borderColor: 1,
10042
		borderLeft: 1,
10043
		borderRight: 1,
10044
		borderTop: 1,
10045
		borderWidth: 1,
10046
		margin: 1,
10047
		padding: 1
10048
	};
10049
10050
$.each([ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ], function( _, prop ) {
10051
	$.fx.step[ prop ] = function( fx ) {
10052
		if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) {
10053
			jQuery.style( fx.elem, prop, fx.end );
10054
			fx.setAttr = true;
10055
		}
10056
	};
10057
});
10058
10059
function getElementStyles( elem ) {
10060
	var key, len,
10061
		style = elem.ownerDocument.defaultView ?
10062
			elem.ownerDocument.defaultView.getComputedStyle( elem, null ) :
10063
			elem.currentStyle,
10064
		styles = {};
10065
10066
	if ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) {
10067
		len = style.length;
10068
		while ( len-- ) {
10069
			key = style[ len ];
10070
			if ( typeof style[ key ] === "string" ) {
10071
				styles[ $.camelCase( key ) ] = style[ key ];
10072
			}
10073
		}
10074
	// support: Opera, IE <9
10075
	} else {
10076
		for ( key in style ) {
10077
			if ( typeof style[ key ] === "string" ) {
10078
				styles[ key ] = style[ key ];
10079
			}
10080
		}
10081
	}
10082
10083
	return styles;
10084
}
10085
10086
function styleDifference( oldStyle, newStyle ) {
10087
	var diff = {},
10088
		name, value;
10089
10090
	for ( name in newStyle ) {
10091
		value = newStyle[ name ];
10092
		if ( oldStyle[ name ] !== value ) {
10093
			if ( !shorthandStyles[ name ] ) {
10094
				if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) {
10095
					diff[ name ] = value;
10096
				}
10097
			}
10098
		}
10099
	}
10100
10101
	return diff;
10102
}
10103
10104
// support: jQuery <1.8
10105
if ( !$.fn.addBack ) {
10106
	$.fn.addBack = function( selector ) {
10107
		return this.add( selector == null ?
10108
			this.prevObject : this.prevObject.filter( selector )
10109
		);
10110
	};
10111
}
10112
10113
$.effects.animateClass = function( value, duration, easing, callback ) {
10114
	var o = $.speed( duration, easing, callback );
10115
10116
	return this.queue( function() {
10117
		var animated = $( this ),
10118
			baseClass = animated.attr( "class" ) || "",
10119
			applyClassChange,
10120
			allAnimations = o.children ? animated.find( "*" ).addBack() : animated;
10121
10122
		// map the animated objects to store the original styles.
10123
		allAnimations = allAnimations.map(function() {
10124
			var el = $( this );
10125
			return {
10126
				el: el,
10127
				start: getElementStyles( this )
10128
			};
10129
		});
10130
10131
		// apply class change
10132
		applyClassChange = function() {
10133
			$.each( classAnimationActions, function(i, action) {
10134
				if ( value[ action ] ) {
10135
					animated[ action + "Class" ]( value[ action ] );
10136
				}
10137
			});
10138
		};
10139
		applyClassChange();
10140
10141
		// map all animated objects again - calculate new styles and diff
10142
		allAnimations = allAnimations.map(function() {
10143
			this.end = getElementStyles( this.el[ 0 ] );
10144
			this.diff = styleDifference( this.start, this.end );
10145
			return this;
10146
		});
10147
10148
		// apply original class
10149
		animated.attr( "class", baseClass );
10150
10151
		// map all animated objects again - this time collecting a promise
10152
		allAnimations = allAnimations.map(function() {
10153
			var styleInfo = this,
10154
				dfd = $.Deferred(),
10155
				opts = $.extend({}, o, {
10156
					queue: false,
10157
					complete: function() {
10158
						dfd.resolve( styleInfo );
10159
					}
10160
				});
10161
10162
			this.el.animate( this.diff, opts );
10163
			return dfd.promise();
10164
		});
10165
10166
		// once all animations have completed:
10167
		$.when.apply( $, allAnimations.get() ).done(function() {
10168
10169
			// set the final class
10170
			applyClassChange();
10171
10172
			// for each animated element,
10173
			// clear all css properties that were animated
10174
			$.each( arguments, function() {
10175
				var el = this.el;
10176
				$.each( this.diff, function(key) {
10177
					el.css( key, "" );
10178
				});
10179
			});
10180
10181
			// this is guarnteed to be there if you use jQuery.speed()
10182
			// it also handles dequeuing the next anim...
10183
			o.complete.call( animated[ 0 ] );
10184
		});
10185
	});
10186
};
10187
10188
$.fn.extend({
10189
	addClass: (function( orig ) {
10190
		return function( classNames, speed, easing, callback ) {
10191
			return speed ?
10192
				$.effects.animateClass.call( this,
10193
					{ add: classNames }, speed, easing, callback ) :
10194
				orig.apply( this, arguments );
10195
		};
10196
	})( $.fn.addClass ),
10197
10198
	removeClass: (function( orig ) {
10199
		return function( classNames, speed, easing, callback ) {
10200
			return arguments.length > 1 ?
10201
				$.effects.animateClass.call( this,
10202
					{ remove: classNames }, speed, easing, callback ) :
10203
				orig.apply( this, arguments );
10204
		};
10205
	})( $.fn.removeClass ),
10206
10207
	toggleClass: (function( orig ) {
10208
		return function( classNames, force, speed, easing, callback ) {
10209
			if ( typeof force === "boolean" || force === undefined ) {
10210
				if ( !speed ) {
10211
					// without speed parameter
10212
					return orig.apply( this, arguments );
10213
				} else {
10214
					return $.effects.animateClass.call( this,
10215
						(force ? { add: classNames } : { remove: classNames }),
10216
						speed, easing, callback );
10217
				}
10218
			} else {
10219
				// without force parameter
10220
				return $.effects.animateClass.call( this,
10221
					{ toggle: classNames }, force, speed, easing );
10222
			}
10223
		};
10224
	})( $.fn.toggleClass ),
10225
10226
	switchClass: function( remove, add, speed, easing, callback) {
10227
		return $.effects.animateClass.call( this, {
10228
			add: add,
10229
			remove: remove
10230
		}, speed, easing, callback );
10231
	}
10232
});
10233
10234
})();
10235
10236
/******************************************************************************/
10237
/*********************************** EFFECTS **********************************/
10238
/******************************************************************************/
10239
10240
(function() {
10241
10242
$.extend( $.effects, {
10243
	version: "1.11.4",
10244
10245
	// Saves a set of properties in a data storage
10246
	save: function( element, set ) {
10247
		for ( var i = 0; i < set.length; i++ ) {
10248
			if ( set[ i ] !== null ) {
10249
				element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] );
10250
			}
10251
		}
10252
	},
10253
10254
	// Restores a set of previously saved properties from a data storage
10255
	restore: function( element, set ) {
10256
		var val, i;
10257
		for ( i = 0; i < set.length; i++ ) {
10258
			if ( set[ i ] !== null ) {
10259
				val = element.data( dataSpace + set[ i ] );
10260
				// support: jQuery 1.6.2
10261
				// http://bugs.jquery.com/ticket/9917
10262
				// jQuery 1.6.2 incorrectly returns undefined for any falsy value.
10263
				// We can't differentiate between "" and 0 here, so we just assume
10264
				// empty string since it's likely to be a more common value...
10265
				if ( val === undefined ) {
10266
					val = "";
10267
				}
10268
				element.css( set[ i ], val );
10269
			}
10270
		}
10271
	},
10272
10273
	setMode: function( el, mode ) {
10274
		if (mode === "toggle") {
10275
			mode = el.is( ":hidden" ) ? "show" : "hide";
10276
		}
10277
		return mode;
10278
	},
10279
10280
	// Translates a [top,left] array into a baseline value
10281
	// this should be a little more flexible in the future to handle a string & hash
10282
	getBaseline: function( origin, original ) {
10283
		var y, x;
10284
		switch ( origin[ 0 ] ) {
10285
			case "top": y = 0; break;
10286
			case "middle": y = 0.5; break;
10287
			case "bottom": y = 1; break;
10288
			default: y = origin[ 0 ] / original.height;
10289
		}
10290
		switch ( origin[ 1 ] ) {
10291
			case "left": x = 0; break;
10292
			case "center": x = 0.5; break;
10293
			case "right": x = 1; break;
10294
			default: x = origin[ 1 ] / original.width;
10295
		}
10296
		return {
10297
			x: x,
10298
			y: y
10299
		};
10300
	},
10301
10302
	// Wraps the element around a wrapper that copies position properties
10303
	createWrapper: function( element ) {
10304
10305
		// if the element is already wrapped, return it
10306
		if ( element.parent().is( ".ui-effects-wrapper" )) {
10307
			return element.parent();
10308
		}
10309
10310
		// wrap the element
10311
		var props = {
10312
				width: element.outerWidth(true),
10313
				height: element.outerHeight(true),
10314
				"float": element.css( "float" )
10315
			},
10316
			wrapper = $( "<div></div>" )
10317
				.addClass( "ui-effects-wrapper" )
10318
				.css({
10319
					fontSize: "100%",
10320
					background: "transparent",
10321
					border: "none",
10322
					margin: 0,
10323
					padding: 0
10324
				}),
10325
			// Store the size in case width/height are defined in % - Fixes #5245
10326
			size = {
10327
				width: element.width(),
10328
				height: element.height()
10329
			},
10330
			active = document.activeElement;
10331
10332
		// support: Firefox
10333
		// Firefox incorrectly exposes anonymous content
10334
		// https://bugzilla.mozilla.org/show_bug.cgi?id=561664
10335
		try {
10336
			active.id;
10337
		} catch ( e ) {
10338
			active = document.body;
10339
		}
10340
10341
		element.wrap( wrapper );
10342
10343
		// Fixes #7595 - Elements lose focus when wrapped.
10344
		if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
10345
			$( active ).focus();
10346
		}
10347
10348
		wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually lose the reference to the wrapped element
10349
10350
		// transfer positioning properties to the wrapper
10351
		if ( element.css( "position" ) === "static" ) {
10352
			wrapper.css({ position: "relative" });
10353
			element.css({ position: "relative" });
10354
		} else {
10355
			$.extend( props, {
10356
				position: element.css( "position" ),
10357
				zIndex: element.css( "z-index" )
10358
			});
10359
			$.each([ "top", "left", "bottom", "right" ], function(i, pos) {
10360
				props[ pos ] = element.css( pos );
10361
				if ( isNaN( parseInt( props[ pos ], 10 ) ) ) {
10362
					props[ pos ] = "auto";
10363
				}
10364
			});
10365
			element.css({
10366
				position: "relative",
10367
				top: 0,
10368
				left: 0,
10369
				right: "auto",
10370
				bottom: "auto"
10371
			});
10372
		}
10373
		element.css(size);
10374
10375
		return wrapper.css( props ).show();
10376
	},
10377
10378
	removeWrapper: function( element ) {
10379
		var active = document.activeElement;
10380
10381
		if ( element.parent().is( ".ui-effects-wrapper" ) ) {
10382
			element.parent().replaceWith( element );
10383
10384
			// Fixes #7595 - Elements lose focus when wrapped.
10385
			if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
10386
				$( active ).focus();
10387
			}
10388
		}
10389
10390
		return element;
10391
	},
10392
10393
	setTransition: function( element, list, factor, value ) {
10394
		value = value || {};
10395
		$.each( list, function( i, x ) {
10396
			var unit = element.cssUnit( x );
10397
			if ( unit[ 0 ] > 0 ) {
10398
				value[ x ] = unit[ 0 ] * factor + unit[ 1 ];
10399
			}
10400
		});
10401
		return value;
10402
	}
10403
});
10404
10405
// return an effect options object for the given parameters:
10406
function _normalizeArguments( effect, options, speed, callback ) {
10407
10408
	// allow passing all options as the first parameter
10409
	if ( $.isPlainObject( effect ) ) {
10410
		options = effect;
10411
		effect = effect.effect;
10412
	}
10413
10414
	// convert to an object
10415
	effect = { effect: effect };
10416
10417
	// catch (effect, null, ...)
10418
	if ( options == null ) {
10419
		options = {};
10420
	}
10421
10422
	// catch (effect, callback)
10423
	if ( $.isFunction( options ) ) {
10424
		callback = options;
10425
		speed = null;
10426
		options = {};
10427
	}
10428
10429
	// catch (effect, speed, ?)
10430
	if ( typeof options === "number" || $.fx.speeds[ options ] ) {
10431
		callback = speed;
10432
		speed = options;
10433
		options = {};
10434
	}
10435
10436
	// catch (effect, options, callback)
10437
	if ( $.isFunction( speed ) ) {
10438
		callback = speed;
10439
		speed = null;
10440
	}
10441
10442
	// add options to effect
10443
	if ( options ) {
10444
		$.extend( effect, options );
10445
	}
10446
10447
	speed = speed || options.duration;
10448
	effect.duration = $.fx.off ? 0 :
10449
		typeof speed === "number" ? speed :
10450
		speed in $.fx.speeds ? $.fx.speeds[ speed ] :
10451
		$.fx.speeds._default;
10452
10453
	effect.complete = callback || options.complete;
10454
10455
	return effect;
10456
}
10457
10458
function standardAnimationOption( option ) {
10459
	// Valid standard speeds (nothing, number, named speed)
10460
	if ( !option || typeof option === "number" || $.fx.speeds[ option ] ) {
10461
		return true;
10462
	}
10463
10464
	// Invalid strings - treat as "normal" speed
10465
	if ( typeof option === "string" && !$.effects.effect[ option ] ) {
10466
		return true;
10467
	}
10468
10469
	// Complete callback
10470
	if ( $.isFunction( option ) ) {
10471
		return true;
10472
	}
10473
10474
	// Options hash (but not naming an effect)
10475
	if ( typeof option === "object" && !option.effect ) {
10476
		return true;
10477
	}
10478
10479
	// Didn't match any standard API
10480
	return false;
10481
}
10482
10483
$.fn.extend({
10484
	effect: function( /* effect, options, speed, callback */ ) {
10485
		var args = _normalizeArguments.apply( this, arguments ),
10486
			mode = args.mode,
10487
			queue = args.queue,
10488
			effectMethod = $.effects.effect[ args.effect ];
10489
10490
		if ( $.fx.off || !effectMethod ) {
10491
			// delegate to the original method (e.g., .show()) if possible
10492
			if ( mode ) {
10493
				return this[ mode ]( args.duration, args.complete );
10494
			} else {
10495
				return this.each( function() {
10496
					if ( args.complete ) {
10497
						args.complete.call( this );
10498
					}
10499
				});
10500
			}
10501
		}
10502
10503
		function run( next ) {
10504
			var elem = $( this ),
10505
				complete = args.complete,
10506
				mode = args.mode;
10507
10508
			function done() {
10509
				if ( $.isFunction( complete ) ) {
10510
					complete.call( elem[0] );
10511
				}
10512
				if ( $.isFunction( next ) ) {
10513
					next();
10514
				}
10515
			}
10516
10517
			// If the element already has the correct final state, delegate to
10518
			// the core methods so the internal tracking of "olddisplay" works.
10519
			if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) {
10520
				elem[ mode ]();
10521
				done();
10522
			} else {
10523
				effectMethod.call( elem[0], args, done );
10524
			}
10525
		}
10526
10527
		return queue === false ? this.each( run ) : this.queue( queue || "fx", run );
10528
	},
10529
10530
	show: (function( orig ) {
10531
		return function( option ) {
10532
			if ( standardAnimationOption( option ) ) {
10533
				return orig.apply( this, arguments );
10534
			} else {
10535
				var args = _normalizeArguments.apply( this, arguments );
10536
				args.mode = "show";
10537
				return this.effect.call( this, args );
10538
			}
10539
		};
10540
	})( $.fn.show ),
10541
10542
	hide: (function( orig ) {
10543
		return function( option ) {
10544
			if ( standardAnimationOption( option ) ) {
10545
				return orig.apply( this, arguments );
10546
			} else {
10547
				var args = _normalizeArguments.apply( this, arguments );
10548
				args.mode = "hide";
10549
				return this.effect.call( this, args );
10550
			}
10551
		};
10552
	})( $.fn.hide ),
10553
10554
	toggle: (function( orig ) {
10555
		return function( option ) {
10556
			if ( standardAnimationOption( option ) || typeof option === "boolean" ) {
10557
				return orig.apply( this, arguments );
10558
			} else {
10559
				var args = _normalizeArguments.apply( this, arguments );
10560
				args.mode = "toggle";
10561
				return this.effect.call( this, args );
10562
			}
10563
		};
10564
	})( $.fn.toggle ),
10565
10566
	// helper functions
10567
	cssUnit: function(key) {
10568
		var style = this.css( key ),
10569
			val = [];
10570
10571
		$.each( [ "em", "px", "%", "pt" ], function( i, unit ) {
10572
			if ( style.indexOf( unit ) > 0 ) {
10573
				val = [ parseFloat( style ), unit ];
10574
			}
10575
		});
10576
		return val;
10577
	}
10578
});
10579
10580
})();
10581
10582
/******************************************************************************/
10583
/*********************************** EASING ***********************************/
10584
/******************************************************************************/
10585
10586
(function() {
10587
10588
// based on easing equations from Robert Penner (http://www.robertpenner.com/easing)
10589
10590
var baseEasings = {};
10591
10592
$.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) {
10593
	baseEasings[ name ] = function( p ) {
10594
		return Math.pow( p, i + 2 );
10595
	};
10596
});
10597
10598
$.extend( baseEasings, {
10599
	Sine: function( p ) {
10600
		return 1 - Math.cos( p * Math.PI / 2 );
10601
	},
10602
	Circ: function( p ) {
10603
		return 1 - Math.sqrt( 1 - p * p );
10604
	},
10605
	Elastic: function( p ) {
10606
		return p === 0 || p === 1 ? p :
10607
			-Math.pow( 2, 8 * (p - 1) ) * Math.sin( ( (p - 1) * 80 - 7.5 ) * Math.PI / 15 );
10608
	},
10609
	Back: function( p ) {
10610
		return p * p * ( 3 * p - 2 );
10611
	},
10612
	Bounce: function( p ) {
10613
		var pow2,
10614
			bounce = 4;
10615
10616
		while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {}
10617
		return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 );
10618
	}
10619
});
10620
10621
$.each( baseEasings, function( name, easeIn ) {
10622
	$.easing[ "easeIn" + name ] = easeIn;
10623
	$.easing[ "easeOut" + name ] = function( p ) {
10624
		return 1 - easeIn( 1 - p );
10625
	};
10626
	$.easing[ "easeInOut" + name ] = function( p ) {
10627
		return p < 0.5 ?
10628
			easeIn( p * 2 ) / 2 :
10629
			1 - easeIn( p * -2 + 2 ) / 2;
10630
	};
10631
});
10632
10633
})();
10634
10635
var effect = $.effects;
10636
10637
10638
/*!
10639
 * jQuery UI Effects Blind 1.11.4
10640
 * http://jqueryui.com
10641
 *
10642
 * Copyright jQuery Foundation and other contributors
10643
 * Released under the MIT license.
10644
 * http://jquery.org/license
10645
 *
10646
 * http://api.jqueryui.com/blind-effect/
10647
 */
10648
10649
10650
var effectBlind = $.effects.effect.blind = function( o, done ) {
10651
	// Create element
10652
	var el = $( this ),
10653
		rvertical = /up|down|vertical/,
10654
		rpositivemotion = /up|left|vertical|horizontal/,
10655
		props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
10656
		mode = $.effects.setMode( el, o.mode || "hide" ),
10657
		direction = o.direction || "up",
10658
		vertical = rvertical.test( direction ),
10659
		ref = vertical ? "height" : "width",
10660
		ref2 = vertical ? "top" : "left",
10661
		motion = rpositivemotion.test( direction ),
10662
		animation = {},
10663
		show = mode === "show",
10664
		wrapper, distance, margin;
10665
10666
	// if already wrapped, the wrapper's properties are my property. #6245
10667
	if ( el.parent().is( ".ui-effects-wrapper" ) ) {
10668
		$.effects.save( el.parent(), props );
10669
	} else {
10670
		$.effects.save( el, props );
10671
	}
10672
	el.show();
10673
	wrapper = $.effects.createWrapper( el ).css({
10674
		overflow: "hidden"
10675
	});
10676
10677
	distance = wrapper[ ref ]();
10678
	margin = parseFloat( wrapper.css( ref2 ) ) || 0;
10679
10680
	animation[ ref ] = show ? distance : 0;
10681
	if ( !motion ) {
10682
		el
10683
			.css( vertical ? "bottom" : "right", 0 )
10684
			.css( vertical ? "top" : "left", "auto" )
10685
			.css({ position: "absolute" });
10686
10687
		animation[ ref2 ] = show ? margin : distance + margin;
10688
	}
10689
10690
	// start at 0 if we are showing
10691
	if ( show ) {
10692
		wrapper.css( ref, 0 );
10693
		if ( !motion ) {
10694
			wrapper.css( ref2, margin + distance );
10695
		}
10696
	}
10697
10698
	// Animate
10699
	wrapper.animate( animation, {
10700
		duration: o.duration,
10701
		easing: o.easing,
10702
		queue: false,
10703
		complete: function() {
10704
			if ( mode === "hide" ) {
10705
				el.hide();
10706
			}
10707
			$.effects.restore( el, props );
10708
			$.effects.removeWrapper( el );
10709
			done();
10710
		}
10711
	});
10712
};
10713
10714
10715
/*!
10716
 * jQuery UI Effects Bounce 1.11.4
10717
 * http://jqueryui.com
10718
 *
10719
 * Copyright jQuery Foundation and other contributors
10720
 * Released under the MIT license.
10721
 * http://jquery.org/license
10722
 *
10723
 * http://api.jqueryui.com/bounce-effect/
10724
 */
10725
10726
10727
var effectBounce = $.effects.effect.bounce = function( o, done ) {
10728
	var el = $( this ),
10729
		props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
10730
10731
		// defaults:
10732
		mode = $.effects.setMode( el, o.mode || "effect" ),
10733
		hide = mode === "hide",
10734
		show = mode === "show",
10735
		direction = o.direction || "up",
10736
		distance = o.distance,
10737
		times = o.times || 5,
10738
10739
		// number of internal animations
10740
		anims = times * 2 + ( show || hide ? 1 : 0 ),
10741
		speed = o.duration / anims,
10742
		easing = o.easing,
10743
10744
		// utility:
10745
		ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
10746
		motion = ( direction === "up" || direction === "left" ),
10747
		i,
10748
		upAnim,
10749
		downAnim,
10750
10751
		// we will need to re-assemble the queue to stack our animations in place
10752
		queue = el.queue(),
10753
		queuelen = queue.length;
10754
10755
	// Avoid touching opacity to prevent clearType and PNG issues in IE
10756
	if ( show || hide ) {
10757
		props.push( "opacity" );
10758
	}
10759
10760
	$.effects.save( el, props );
10761
	el.show();
10762
	$.effects.createWrapper( el ); // Create Wrapper
10763
10764
	// default distance for the BIGGEST bounce is the outer Distance / 3
10765
	if ( !distance ) {
10766
		distance = el[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3;
10767
	}
10768
10769
	if ( show ) {
10770
		downAnim = { opacity: 1 };
10771
		downAnim[ ref ] = 0;
10772
10773
		// if we are showing, force opacity 0 and set the initial position
10774
		// then do the "first" animation
10775
		el.css( "opacity", 0 )
10776
			.css( ref, motion ? -distance * 2 : distance * 2 )
10777
			.animate( downAnim, speed, easing );
10778
	}
10779
10780
	// start at the smallest distance if we are hiding
10781
	if ( hide ) {
10782
		distance = distance / Math.pow( 2, times - 1 );
10783
	}
10784
10785
	downAnim = {};
10786
	downAnim[ ref ] = 0;
10787
	// Bounces up/down/left/right then back to 0 -- times * 2 animations happen here
10788
	for ( i = 0; i < times; i++ ) {
10789
		upAnim = {};
10790
		upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
10791
10792
		el.animate( upAnim, speed, easing )
10793
			.animate( downAnim, speed, easing );
10794
10795
		distance = hide ? distance * 2 : distance / 2;
10796
	}
10797
10798
	// Last Bounce when Hiding
10799
	if ( hide ) {
10800
		upAnim = { opacity: 0 };
10801
		upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
10802
10803
		el.animate( upAnim, speed, easing );
10804
	}
10805
10806
	el.queue(function() {
10807
		if ( hide ) {
10808
			el.hide();
10809
		}
10810
		$.effects.restore( el, props );
10811
		$.effects.removeWrapper( el );
10812
		done();
10813
	});
10814
10815
	// inject all the animations we just queued to be first in line (after "inprogress")
10816
	if ( queuelen > 1) {
10817
		queue.splice.apply( queue,
10818
			[ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
10819
	}
10820
	el.dequeue();
10821
10822
};
10823
10824
10825
/*!
10826
 * jQuery UI Effects Clip 1.11.4
10827
 * http://jqueryui.com
10828
 *
10829
 * Copyright jQuery Foundation and other contributors
10830
 * Released under the MIT license.
10831
 * http://jquery.org/license
10832
 *
10833
 * http://api.jqueryui.com/clip-effect/
10834
 */
10835
10836
10837
var effectClip = $.effects.effect.clip = function( o, done ) {
10838
	// Create element
10839
	var el = $( this ),
10840
		props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
10841
		mode = $.effects.setMode( el, o.mode || "hide" ),
10842
		show = mode === "show",
10843
		direction = o.direction || "vertical",
10844
		vert = direction === "vertical",
10845
		size = vert ? "height" : "width",
10846
		position = vert ? "top" : "left",
10847
		animation = {},
10848
		wrapper, animate, distance;
10849
10850
	// Save & Show
10851
	$.effects.save( el, props );
10852
	el.show();
10853
10854
	// Create Wrapper
10855
	wrapper = $.effects.createWrapper( el ).css({
10856
		overflow: "hidden"
10857
	});
10858
	animate = ( el[0].tagName === "IMG" ) ? wrapper : el;
10859
	distance = animate[ size ]();
10860
10861
	// Shift
10862
	if ( show ) {
10863
		animate.css( size, 0 );
10864
		animate.css( position, distance / 2 );
10865
	}
10866
10867
	// Create Animation Object:
10868
	animation[ size ] = show ? distance : 0;
10869
	animation[ position ] = show ? 0 : distance / 2;
10870
10871
	// Animate
10872
	animate.animate( animation, {
10873
		queue: false,
10874
		duration: o.duration,
10875
		easing: o.easing,
10876
		complete: function() {
10877
			if ( !show ) {
10878
				el.hide();
10879
			}
10880
			$.effects.restore( el, props );
10881
			$.effects.removeWrapper( el );
10882
			done();
10883
		}
10884
	});
10885
10886
};
10887
10888
10889
/*!
10890
 * jQuery UI Effects Drop 1.11.4
10891
 * http://jqueryui.com
10892
 *
10893
 * Copyright jQuery Foundation and other contributors
10894
 * Released under the MIT license.
10895
 * http://jquery.org/license
10896
 *
10897
 * http://api.jqueryui.com/drop-effect/
10898
 */
10899
10900
10901
var effectDrop = $.effects.effect.drop = function( o, done ) {
10902
10903
	var el = $( this ),
10904
		props = [ "position", "top", "bottom", "left", "right", "opacity", "height", "width" ],
10905
		mode = $.effects.setMode( el, o.mode || "hide" ),
10906
		show = mode === "show",
10907
		direction = o.direction || "left",
10908
		ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
10909
		motion = ( direction === "up" || direction === "left" ) ? "pos" : "neg",
10910
		animation = {
10911
			opacity: show ? 1 : 0
10912
		},
10913
		distance;
10914
10915
	// Adjust
10916
	$.effects.save( el, props );
10917
	el.show();
10918
	$.effects.createWrapper( el );
10919
10920
	distance = o.distance || el[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ) / 2;
10921
10922
	if ( show ) {
10923
		el
10924
			.css( "opacity", 0 )
10925
			.css( ref, motion === "pos" ? -distance : distance );
10926
	}
10927
10928
	// Animation
10929
	animation[ ref ] = ( show ?
10930
		( motion === "pos" ? "+=" : "-=" ) :
10931
		( motion === "pos" ? "-=" : "+=" ) ) +
10932
		distance;
10933
10934
	// Animate
10935
	el.animate( animation, {
10936
		queue: false,
10937
		duration: o.duration,
10938
		easing: o.easing,
10939
		complete: function() {
10940
			if ( mode === "hide" ) {
10941
				el.hide();
10942
			}
10943
			$.effects.restore( el, props );
10944
			$.effects.removeWrapper( el );
10945
			done();
10946
		}
10947
	});
10948
};
10949
10950
10951
/*!
10952
 * jQuery UI Effects Explode 1.11.4
10953
 * http://jqueryui.com
10954
 *
10955
 * Copyright jQuery Foundation and other contributors
10956
 * Released under the MIT license.
10957
 * http://jquery.org/license
10958
 *
10959
 * http://api.jqueryui.com/explode-effect/
10960
 */
10961
10962
10963
var effectExplode = $.effects.effect.explode = function( o, done ) {
10964
10965
	var rows = o.pieces ? Math.round( Math.sqrt( o.pieces ) ) : 3,
10966
		cells = rows,
10967
		el = $( this ),
10968
		mode = $.effects.setMode( el, o.mode || "hide" ),
10969
		show = mode === "show",
10970
10971
		// show and then visibility:hidden the element before calculating offset
10972
		offset = el.show().css( "visibility", "hidden" ).offset(),
10973
10974
		// width and height of a piece
10975
		width = Math.ceil( el.outerWidth() / cells ),
10976
		height = Math.ceil( el.outerHeight() / rows ),
10977
		pieces = [],
10978
10979
		// loop
10980
		i, j, left, top, mx, my;
10981
10982
	// children animate complete:
10983
	function childComplete() {
10984
		pieces.push( this );
10985
		if ( pieces.length === rows * cells ) {
10986
			animComplete();
10987
		}
10988
	}
10989
10990
	// clone the element for each row and cell.
10991
	for ( i = 0; i < rows ; i++ ) { // ===>
10992
		top = offset.top + i * height;
10993
		my = i - ( rows - 1 ) / 2 ;
10994
10995
		for ( j = 0; j < cells ; j++ ) { // |||
10996
			left = offset.left + j * width;
10997
			mx = j - ( cells - 1 ) / 2 ;
10998
10999
			// Create a clone of the now hidden main element that will be absolute positioned
11000
			// within a wrapper div off the -left and -top equal to size of our pieces
11001
			el
11002
				.clone()
11003
				.appendTo( "body" )
11004
				.wrap( "<div></div>" )
11005
				.css({
11006
					position: "absolute",
11007
					visibility: "visible",
11008
					left: -j * width,
11009
					top: -i * height
11010
				})
11011
11012
			// select the wrapper - make it overflow: hidden and absolute positioned based on
11013
			// where the original was located +left and +top equal to the size of pieces
11014
				.parent()
11015
				.addClass( "ui-effects-explode" )
11016
				.css({
11017
					position: "absolute",
11018
					overflow: "hidden",
11019
					width: width,
11020
					height: height,
11021
					left: left + ( show ? mx * width : 0 ),
11022
					top: top + ( show ? my * height : 0 ),
11023
					opacity: show ? 0 : 1
11024
				}).animate({
11025
					left: left + ( show ? 0 : mx * width ),
11026
					top: top + ( show ? 0 : my * height ),
11027
					opacity: show ? 1 : 0
11028
				}, o.duration || 500, o.easing, childComplete );
11029
		}
11030
	}
11031
11032
	function animComplete() {
11033
		el.css({
11034
			visibility: "visible"
11035
		});
11036
		$( pieces ).remove();
11037
		if ( !show ) {
11038
			el.hide();
11039
		}
11040
		done();
11041
	}
11042
};
11043
11044
11045
/*!
11046
 * jQuery UI Effects Fade 1.11.4
11047
 * http://jqueryui.com
11048
 *
11049
 * Copyright jQuery Foundation and other contributors
11050
 * Released under the MIT license.
11051
 * http://jquery.org/license
11052
 *
11053
 * http://api.jqueryui.com/fade-effect/
11054
 */
11055
11056
11057
var effectFade = $.effects.effect.fade = function( o, done ) {
11058
	var el = $( this ),
11059
		mode = $.effects.setMode( el, o.mode || "toggle" );
11060
11061
	el.animate({
11062
		opacity: mode
11063
	}, {
11064
		queue: false,
11065
		duration: o.duration,
11066
		easing: o.easing,
11067
		complete: done
11068
	});
11069
};
11070
11071
11072
/*!
11073
 * jQuery UI Effects Fold 1.11.4
11074
 * http://jqueryui.com
11075
 *
11076
 * Copyright jQuery Foundation and other contributors
11077
 * Released under the MIT license.
11078
 * http://jquery.org/license
11079
 *
11080
 * http://api.jqueryui.com/fold-effect/
11081
 */
11082
11083
11084
var effectFold = $.effects.effect.fold = function( o, done ) {
11085
11086
	// Create element
11087
	var el = $( this ),
11088
		props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
11089
		mode = $.effects.setMode( el, o.mode || "hide" ),
11090
		show = mode === "show",
11091
		hide = mode === "hide",
11092
		size = o.size || 15,
11093
		percent = /([0-9]+)%/.exec( size ),
11094
		horizFirst = !!o.horizFirst,
11095
		widthFirst = show !== horizFirst,
11096
		ref = widthFirst ? [ "width", "height" ] : [ "height", "width" ],
11097
		duration = o.duration / 2,
11098
		wrapper, distance,
11099
		animation1 = {},
11100
		animation2 = {};
11101
11102
	$.effects.save( el, props );
11103
	el.show();
11104
11105
	// Create Wrapper
11106
	wrapper = $.effects.createWrapper( el ).css({
11107
		overflow: "hidden"
11108
	});
11109
	distance = widthFirst ?
11110
		[ wrapper.width(), wrapper.height() ] :
11111
		[ wrapper.height(), wrapper.width() ];
11112
11113
	if ( percent ) {
11114
		size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ];
11115
	}
11116
	if ( show ) {
11117
		wrapper.css( horizFirst ? {
11118
			height: 0,
11119
			width: size
11120
		} : {
11121
			height: size,
11122
			width: 0
11123
		});
11124
	}
11125
11126
	// Animation
11127
	animation1[ ref[ 0 ] ] = show ? distance[ 0 ] : size;
11128
	animation2[ ref[ 1 ] ] = show ? distance[ 1 ] : 0;
11129
11130
	// Animate
11131
	wrapper
11132
		.animate( animation1, duration, o.easing )
11133
		.animate( animation2, duration, o.easing, function() {
11134
			if ( hide ) {
11135
				el.hide();
11136
			}
11137
			$.effects.restore( el, props );
11138
			$.effects.removeWrapper( el );
11139
			done();
11140
		});
11141
11142
};
11143
11144
11145
/*!
11146
 * jQuery UI Effects Highlight 1.11.4
11147
 * http://jqueryui.com
11148
 *
11149
 * Copyright jQuery Foundation and other contributors
11150
 * Released under the MIT license.
11151
 * http://jquery.org/license
11152
 *
11153
 * http://api.jqueryui.com/highlight-effect/
11154
 */
11155
11156
11157
var effectHighlight = $.effects.effect.highlight = function( o, done ) {
11158
	var elem = $( this ),
11159
		props = [ "backgroundImage", "backgroundColor", "opacity" ],
11160
		mode = $.effects.setMode( elem, o.mode || "show" ),
11161
		animation = {
11162
			backgroundColor: elem.css( "backgroundColor" )
11163
		};
11164
11165
	if (mode === "hide") {
11166
		animation.opacity = 0;
11167
	}
11168
11169
	$.effects.save( elem, props );
11170
11171
	elem
11172
		.show()
11173
		.css({
11174
			backgroundImage: "none",
11175
			backgroundColor: o.color || "#ffff99"
11176
		})
11177
		.animate( animation, {
11178
			queue: false,
11179
			duration: o.duration,
11180
			easing: o.easing,
11181
			complete: function() {
11182
				if ( mode === "hide" ) {
11183
					elem.hide();
11184
				}
11185
				$.effects.restore( elem, props );
11186
				done();
11187
			}
11188
		});
11189
};
11190
11191
11192
/*!
11193
 * jQuery UI Effects Size 1.11.4
11194
 * http://jqueryui.com
11195
 *
11196
 * Copyright jQuery Foundation and other contributors
11197
 * Released under the MIT license.
11198
 * http://jquery.org/license
11199
 *
11200
 * http://api.jqueryui.com/size-effect/
11201
 */
11202
11203
11204
var effectSize = $.effects.effect.size = function( o, done ) {
11205
11206
	// Create element
11207
	var original, baseline, factor,
11208
		el = $( this ),
11209
		props0 = [ "position", "top", "bottom", "left", "right", "width", "height", "overflow", "opacity" ],
11210
11211
		// Always restore
11212
		props1 = [ "position", "top", "bottom", "left", "right", "overflow", "opacity" ],
11213
11214
		// Copy for children
11215
		props2 = [ "width", "height", "overflow" ],
11216
		cProps = [ "fontSize" ],
11217
		vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ],
11218
		hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ],
11219
11220
		// Set options
11221
		mode = $.effects.setMode( el, o.mode || "effect" ),
11222
		restore = o.restore || mode !== "effect",
11223
		scale = o.scale || "both",
11224
		origin = o.origin || [ "middle", "center" ],
11225
		position = el.css( "position" ),
11226
		props = restore ? props0 : props1,
11227
		zero = {
11228
			height: 0,
11229
			width: 0,
11230
			outerHeight: 0,
11231
			outerWidth: 0
11232
		};
11233
11234
	if ( mode === "show" ) {
11235
		el.show();
11236
	}
11237
	original = {
11238
		height: el.height(),
11239
		width: el.width(),
11240
		outerHeight: el.outerHeight(),
11241
		outerWidth: el.outerWidth()
11242
	};
11243
11244
	if ( o.mode === "toggle" && mode === "show" ) {
11245
		el.from = o.to || zero;
11246
		el.to = o.from || original;
11247
	} else {
11248
		el.from = o.from || ( mode === "show" ? zero : original );
11249
		el.to = o.to || ( mode === "hide" ? zero : original );
11250
	}
11251
11252
	// Set scaling factor
11253
	factor = {
11254
		from: {
11255
			y: el.from.height / original.height,
11256
			x: el.from.width / original.width
11257
		},
11258
		to: {
11259
			y: el.to.height / original.height,
11260
			x: el.to.width / original.width
11261
		}
11262
	};
11263
11264
	// Scale the css box
11265
	if ( scale === "box" || scale === "both" ) {
11266
11267
		// Vertical props scaling
11268
		if ( factor.from.y !== factor.to.y ) {
11269
			props = props.concat( vProps );
11270
			el.from = $.effects.setTransition( el, vProps, factor.from.y, el.from );
11271
			el.to = $.effects.setTransition( el, vProps, factor.to.y, el.to );
11272
		}
11273
11274
		// Horizontal props scaling
11275
		if ( factor.from.x !== factor.to.x ) {
11276
			props = props.concat( hProps );
11277
			el.from = $.effects.setTransition( el, hProps, factor.from.x, el.from );
11278
			el.to = $.effects.setTransition( el, hProps, factor.to.x, el.to );
11279
		}
11280
	}
11281
11282
	// Scale the content
11283
	if ( scale === "content" || scale === "both" ) {
11284
11285
		// Vertical props scaling
11286
		if ( factor.from.y !== factor.to.y ) {
11287
			props = props.concat( cProps ).concat( props2 );
11288
			el.from = $.effects.setTransition( el, cProps, factor.from.y, el.from );
11289
			el.to = $.effects.setTransition( el, cProps, factor.to.y, el.to );
11290
		}
11291
	}
11292
11293
	$.effects.save( el, props );
11294
	el.show();
11295
	$.effects.createWrapper( el );
11296
	el.css( "overflow", "hidden" ).css( el.from );
11297
11298
	// Adjust
11299
	if (origin) { // Calculate baseline shifts
11300
		baseline = $.effects.getBaseline( origin, original );
11301
		el.from.top = ( original.outerHeight - el.outerHeight() ) * baseline.y;
11302
		el.from.left = ( original.outerWidth - el.outerWidth() ) * baseline.x;
11303
		el.to.top = ( original.outerHeight - el.to.outerHeight ) * baseline.y;
11304
		el.to.left = ( original.outerWidth - el.to.outerWidth ) * baseline.x;
11305
	}
11306
	el.css( el.from ); // set top & left
11307
11308
	// Animate
11309
	if ( scale === "content" || scale === "both" ) { // Scale the children
11310
11311
		// Add margins/font-size
11312
		vProps = vProps.concat([ "marginTop", "marginBottom" ]).concat(cProps);
11313
		hProps = hProps.concat([ "marginLeft", "marginRight" ]);
11314
		props2 = props0.concat(vProps).concat(hProps);
11315
11316
		el.find( "*[width]" ).each( function() {
11317
			var child = $( this ),
11318
				c_original = {
11319
					height: child.height(),
11320
					width: child.width(),
11321
					outerHeight: child.outerHeight(),
11322
					outerWidth: child.outerWidth()
11323
				};
11324
			if (restore) {
11325
				$.effects.save(child, props2);
11326
			}
11327
11328
			child.from = {
11329
				height: c_original.height * factor.from.y,
11330
				width: c_original.width * factor.from.x,
11331
				outerHeight: c_original.outerHeight * factor.from.y,
11332
				outerWidth: c_original.outerWidth * factor.from.x
11333
			};
11334
			child.to = {
11335
				height: c_original.height * factor.to.y,
11336
				width: c_original.width * factor.to.x,
11337
				outerHeight: c_original.height * factor.to.y,
11338
				outerWidth: c_original.width * factor.to.x
11339
			};
11340
11341
			// Vertical props scaling
11342
			if ( factor.from.y !== factor.to.y ) {
11343
				child.from = $.effects.setTransition( child, vProps, factor.from.y, child.from );
11344
				child.to = $.effects.setTransition( child, vProps, factor.to.y, child.to );
11345
			}
11346
11347
			// Horizontal props scaling
11348
			if ( factor.from.x !== factor.to.x ) {
11349
				child.from = $.effects.setTransition( child, hProps, factor.from.x, child.from );
11350
				child.to = $.effects.setTransition( child, hProps, factor.to.x, child.to );
11351
			}
11352
11353
			// Animate children
11354
			child.css( child.from );
11355
			child.animate( child.to, o.duration, o.easing, function() {
11356
11357
				// Restore children
11358
				if ( restore ) {
11359
					$.effects.restore( child, props2 );
11360
				}
11361
			});
11362
		});
11363
	}
11364
11365
	// Animate
11366
	el.animate( el.to, {
11367
		queue: false,
11368
		duration: o.duration,
11369
		easing: o.easing,
11370
		complete: function() {
11371
			if ( el.to.opacity === 0 ) {
11372
				el.css( "opacity", el.from.opacity );
11373
			}
11374
			if ( mode === "hide" ) {
11375
				el.hide();
11376
			}
11377
			$.effects.restore( el, props );
11378
			if ( !restore ) {
11379
11380
				// we need to calculate our new positioning based on the scaling
11381
				if ( position === "static" ) {
11382
					el.css({
11383
						position: "relative",
11384
						top: el.to.top,
11385
						left: el.to.left
11386
					});
11387
				} else {
11388
					$.each([ "top", "left" ], function( idx, pos ) {
11389
						el.css( pos, function( _, str ) {
11390
							var val = parseInt( str, 10 ),
11391
								toRef = idx ? el.to.left : el.to.top;
11392
11393
							// if original was "auto", recalculate the new value from wrapper
11394
							if ( str === "auto" ) {
11395
								return toRef + "px";
11396
							}
11397
11398
							return val + toRef + "px";
11399
						});
11400
					});
11401
				}
11402
			}
11403
11404
			$.effects.removeWrapper( el );
11405
			done();
11406
		}
11407
	});
11408
11409
};
11410
11411
11412
/*!
11413
 * jQuery UI Effects Scale 1.11.4
11414
 * http://jqueryui.com
11415
 *
11416
 * Copyright jQuery Foundation and other contributors
11417
 * Released under the MIT license.
11418
 * http://jquery.org/license
11419
 *
11420
 * http://api.jqueryui.com/scale-effect/
11421
 */
11422
11423
11424
var effectScale = $.effects.effect.scale = function( o, done ) {
11425
11426
	// Create element
11427
	var el = $( this ),
11428
		options = $.extend( true, {}, o ),
11429
		mode = $.effects.setMode( el, o.mode || "effect" ),
11430
		percent = parseInt( o.percent, 10 ) ||
11431
			( parseInt( o.percent, 10 ) === 0 ? 0 : ( mode === "hide" ? 0 : 100 ) ),
11432
		direction = o.direction || "both",
11433
		origin = o.origin,
11434
		original = {
11435
			height: el.height(),
11436
			width: el.width(),
11437
			outerHeight: el.outerHeight(),
11438
			outerWidth: el.outerWidth()
11439
		},
11440
		factor = {
11441
			y: direction !== "horizontal" ? (percent / 100) : 1,
11442
			x: direction !== "vertical" ? (percent / 100) : 1
11443
		};
11444
11445
	// We are going to pass this effect to the size effect:
11446
	options.effect = "size";
11447
	options.queue = false;
11448
	options.complete = done;
11449
11450
	// Set default origin and restore for show/hide
11451
	if ( mode !== "effect" ) {
11452
		options.origin = origin || [ "middle", "center" ];
11453
		options.restore = true;
11454
	}
11455
11456
	options.from = o.from || ( mode === "show" ? {
11457
		height: 0,
11458
		width: 0,
11459
		outerHeight: 0,
11460
		outerWidth: 0
11461
	} : original );
11462
	options.to = {
11463
		height: original.height * factor.y,
11464
		width: original.width * factor.x,
11465
		outerHeight: original.outerHeight * factor.y,
11466
		outerWidth: original.outerWidth * factor.x
11467
	};
11468
11469
	// Fade option to support puff
11470
	if ( options.fade ) {
11471
		if ( mode === "show" ) {
11472
			options.from.opacity = 0;
11473
			options.to.opacity = 1;
11474
		}
11475
		if ( mode === "hide" ) {
11476
			options.from.opacity = 1;
11477
			options.to.opacity = 0;
11478
		}
11479
	}
11480
11481
	// Animate
11482
	el.effect( options );
11483
11484
};
11485
11486
11487
/*!
11488
 * jQuery UI Effects Puff 1.11.4
11489
 * http://jqueryui.com
11490
 *
11491
 * Copyright jQuery Foundation and other contributors
11492
 * Released under the MIT license.
11493
 * http://jquery.org/license
11494
 *
11495
 * http://api.jqueryui.com/puff-effect/
11496
 */
11497
11498
11499
var effectPuff = $.effects.effect.puff = function( o, done ) {
11500
	var elem = $( this ),
11501
		mode = $.effects.setMode( elem, o.mode || "hide" ),
11502
		hide = mode === "hide",
11503
		percent = parseInt( o.percent, 10 ) || 150,
11504
		factor = percent / 100,
11505
		original = {
11506
			height: elem.height(),
11507
			width: elem.width(),
11508
			outerHeight: elem.outerHeight(),
11509
			outerWidth: elem.outerWidth()
11510
		};
11511
11512
	$.extend( o, {
11513
		effect: "scale",
11514
		queue: false,
11515
		fade: true,
11516
		mode: mode,
11517
		complete: done,
11518
		percent: hide ? percent : 100,
11519
		from: hide ?
11520
			original :
11521
			{
11522
				height: original.height * factor,
11523
				width: original.width * factor,
11524
				outerHeight: original.outerHeight * factor,
11525
				outerWidth: original.outerWidth * factor
11526
			}
11527
	});
11528
11529
	elem.effect( o );
11530
};
11531
11532
11533
/*!
11534
 * jQuery UI Effects Pulsate 1.11.4
11535
 * http://jqueryui.com
11536
 *
11537
 * Copyright jQuery Foundation and other contributors
11538
 * Released under the MIT license.
11539
 * http://jquery.org/license
11540
 *
11541
 * http://api.jqueryui.com/pulsate-effect/
11542
 */
11543
11544
11545
var effectPulsate = $.effects.effect.pulsate = function( o, done ) {
11546
	var elem = $( this ),
11547
		mode = $.effects.setMode( elem, o.mode || "show" ),
11548
		show = mode === "show",
11549
		hide = mode === "hide",
11550
		showhide = ( show || mode === "hide" ),
11551
11552
		// showing or hiding leaves of the "last" animation
11553
		anims = ( ( o.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ),
11554
		duration = o.duration / anims,
11555
		animateTo = 0,
11556
		queue = elem.queue(),
11557
		queuelen = queue.length,
11558
		i;
11559
11560
	if ( show || !elem.is(":visible")) {
11561
		elem.css( "opacity", 0 ).show();
11562
		animateTo = 1;
11563
	}
11564
11565
	// anims - 1 opacity "toggles"
11566
	for ( i = 1; i < anims; i++ ) {
11567
		elem.animate({
11568
			opacity: animateTo
11569
		}, duration, o.easing );
11570
		animateTo = 1 - animateTo;
11571
	}
11572
11573
	elem.animate({
11574
		opacity: animateTo
11575
	}, duration, o.easing);
11576
11577
	elem.queue(function() {
11578
		if ( hide ) {
11579
			elem.hide();
11580
		}
11581
		done();
11582
	});
11583
11584
	// We just queued up "anims" animations, we need to put them next in the queue
11585
	if ( queuelen > 1 ) {
11586
		queue.splice.apply( queue,
11587
			[ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
11588
	}
11589
	elem.dequeue();
11590
};
11591
11592
11593
/*!
11594
 * jQuery UI Effects Shake 1.11.4
11595
 * http://jqueryui.com
11596
 *
11597
 * Copyright jQuery Foundation and other contributors
11598
 * Released under the MIT license.
11599
 * http://jquery.org/license
11600
 *
11601
 * http://api.jqueryui.com/shake-effect/
11602
 */
11603
11604
11605
var effectShake = $.effects.effect.shake = function( o, done ) {
11606
11607
	var el = $( this ),
11608
		props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
11609
		mode = $.effects.setMode( el, o.mode || "effect" ),
11610
		direction = o.direction || "left",
11611
		distance = o.distance || 20,
11612
		times = o.times || 3,
11613
		anims = times * 2 + 1,
11614
		speed = Math.round( o.duration / anims ),
11615
		ref = (direction === "up" || direction === "down") ? "top" : "left",
11616
		positiveMotion = (direction === "up" || direction === "left"),
11617
		animation = {},
11618
		animation1 = {},
11619
		animation2 = {},
11620
		i,
11621
11622
		// we will need to re-assemble the queue to stack our animations in place
11623
		queue = el.queue(),
11624
		queuelen = queue.length;
11625
11626
	$.effects.save( el, props );
11627
	el.show();
11628
	$.effects.createWrapper( el );
11629
11630
	// Animation
11631
	animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance;
11632
	animation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2;
11633
	animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2;
11634
11635
	// Animate
11636
	el.animate( animation, speed, o.easing );
11637
11638
	// Shakes
11639
	for ( i = 1; i < times; i++ ) {
11640
		el.animate( animation1, speed, o.easing ).animate( animation2, speed, o.easing );
11641
	}
11642
	el
11643
		.animate( animation1, speed, o.easing )
11644
		.animate( animation, speed / 2, o.easing )
11645
		.queue(function() {
11646
			if ( mode === "hide" ) {
11647
				el.hide();
11648
			}
11649
			$.effects.restore( el, props );
11650
			$.effects.removeWrapper( el );
11651
			done();
11652
		});
11653
11654
	// inject all the animations we just queued to be first in line (after "inprogress")
11655
	if ( queuelen > 1) {
11656
		queue.splice.apply( queue,
11657
			[ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
11658
	}
11659
	el.dequeue();
11660
11661
};
11662
11663
11664
/*!
11665
 * jQuery UI Effects Slide 1.11.4
11666
 * http://jqueryui.com
11667
 *
11668
 * Copyright jQuery Foundation and other contributors
11669
 * Released under the MIT license.
11670
 * http://jquery.org/license
11671
 *
11672
 * http://api.jqueryui.com/slide-effect/
11673
 */
11674
11675
11676
var effectSlide = $.effects.effect.slide = function( o, done ) {
11677
11678
	// Create element
11679
	var el = $( this ),
11680
		props = [ "position", "top", "bottom", "left", "right", "width", "height" ],
11681
		mode = $.effects.setMode( el, o.mode || "show" ),
11682
		show = mode === "show",
11683
		direction = o.direction || "left",
11684
		ref = (direction === "up" || direction === "down") ? "top" : "left",
11685
		positiveMotion = (direction === "up" || direction === "left"),
11686
		distance,
11687
		animation = {};
11688
11689
	// Adjust
11690
	$.effects.save( el, props );
11691
	el.show();
11692
	distance = o.distance || el[ ref === "top" ? "outerHeight" : "outerWidth" ]( true );
11693
11694
	$.effects.createWrapper( el ).css({
11695
		overflow: "hidden"
11696
	});
11697
11698
	if ( show ) {
11699
		el.css( ref, positiveMotion ? (isNaN(distance) ? "-" + distance : -distance) : distance );
11700
	}
11701
11702
	// Animation
11703
	animation[ ref ] = ( show ?
11704
		( positiveMotion ? "+=" : "-=") :
11705
		( positiveMotion ? "-=" : "+=")) +
11706
		distance;
11707
11708
	// Animate
11709
	el.animate( animation, {
11710
		queue: false,
11711
		duration: o.duration,
11712
		easing: o.easing,
11713
		complete: function() {
11714
			if ( mode === "hide" ) {
11715
				el.hide();
11716
			}
11717
			$.effects.restore( el, props );
11718
			$.effects.removeWrapper( el );
11719
			done();
11720
		}
11721
	});
11722
};
11723
11724
11725
/*!
11726
 * jQuery UI Effects Transfer 1.11.4
11727
 * http://jqueryui.com
11728
 *
11729
 * Copyright jQuery Foundation and other contributors
11730
 * Released under the MIT license.
11731
 * http://jquery.org/license
11732
 *
11733
 * http://api.jqueryui.com/transfer-effect/
11734
 */
11735
11736
11737
var effectTransfer = $.effects.effect.transfer = function( o, done ) {
11738
	var elem = $( this ),
11739
		target = $( o.to ),
11740
		targetFixed = target.css( "position" ) === "fixed",
11741
		body = $("body"),
11742
		fixTop = targetFixed ? body.scrollTop() : 0,
11743
		fixLeft = targetFixed ? body.scrollLeft() : 0,
11744
		endPosition = target.offset(),
11745
		animation = {
11746
			top: endPosition.top - fixTop,
11747
			left: endPosition.left - fixLeft,
11748
			height: target.innerHeight(),
11749
			width: target.innerWidth()
11750
		},
11751
		startPosition = elem.offset(),
11752
		transfer = $( "<div class='ui-effects-transfer'></div>" )
11753
			.appendTo( document.body )
11754
			.addClass( o.className )
11755
			.css({
11756
				top: startPosition.top - fixTop,
11757
				left: startPosition.left - fixLeft,
11758
				height: elem.innerHeight(),
11759
				width: elem.innerWidth(),
11760
				position: targetFixed ? "fixed" : "absolute"
11761
			})
11762
			.animate( animation, o.duration, o.easing, function() {
11763
				transfer.remove();
11764
				done();
11765
			});
11766
};
11767
11768
11769
/*!
11770
 * jQuery UI Progressbar 1.11.4
11771
 * http://jqueryui.com
11772
 *
11773
 * Copyright jQuery Foundation and other contributors
11774
 * Released under the MIT license.
11775
 * http://jquery.org/license
11776
 *
11777
 * http://api.jqueryui.com/progressbar/
11778
 */
11779
11780
11781
var progressbar = $.widget( "ui.progressbar", {
11782
	version: "1.11.4",
11783
	options: {
11784
		max: 100,
11785
		value: 0,
11786
11787
		change: null,
11788
		complete: null
11789
	},
11790
11791
	min: 0,
11792
11793
	_create: function() {
11794
		// Constrain initial value
11795
		this.oldValue = this.options.value = this._constrainedValue();
11796
11797
		this.element
11798
			.addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
11799
			.attr({
11800
				// Only set static values, aria-valuenow and aria-valuemax are
11801
				// set inside _refreshValue()
11802
				role: "progressbar",
11803
				"aria-valuemin": this.min
11804
			});
11805
11806
		this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" )
11807
			.appendTo( this.element );
11808
11809
		this._refreshValue();
11810
	},
11811
11812
	_destroy: function() {
11813
		this.element
11814
			.removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
11815
			.removeAttr( "role" )
11816
			.removeAttr( "aria-valuemin" )
11817
			.removeAttr( "aria-valuemax" )
11818
			.removeAttr( "aria-valuenow" );
11819
11820
		this.valueDiv.remove();
11821
	},
11822
11823
	value: function( newValue ) {
11824
		if ( newValue === undefined ) {
11825
			return this.options.value;
11826
		}
11827
11828
		this.options.value = this._constrainedValue( newValue );
11829
		this._refreshValue();
11830
	},
11831
11832
	_constrainedValue: function( newValue ) {
11833
		if ( newValue === undefined ) {
11834
			newValue = this.options.value;
11835
		}
11836
11837
		this.indeterminate = newValue === false;
11838
11839
		// sanitize value
11840
		if ( typeof newValue !== "number" ) {
11841
			newValue = 0;
11842
		}
11843
11844
		return this.indeterminate ? false :
11845
			Math.min( this.options.max, Math.max( this.min, newValue ) );
11846
	},
11847
11848
	_setOptions: function( options ) {
11849
		// Ensure "value" option is set after other values (like max)
11850
		var value = options.value;
11851
		delete options.value;
11852
11853
		this._super( options );
11854
11855
		this.options.value = this._constrainedValue( value );
11856
		this._refreshValue();
11857
	},
11858
11859
	_setOption: function( key, value ) {
11860
		if ( key === "max" ) {
11861
			// Don't allow a max less than min
11862
			value = Math.max( this.min, value );
11863
		}
11864
		if ( key === "disabled" ) {
11865
			this.element
11866
				.toggleClass( "ui-state-disabled", !!value )
11867
				.attr( "aria-disabled", value );
11868
		}
11869
		this._super( key, value );
11870
	},
11871
11872
	_percentage: function() {
11873
		return this.indeterminate ? 100 : 100 * ( this.options.value - this.min ) / ( this.options.max - this.min );
11874
	},
11875
11876
	_refreshValue: function() {
11877
		var value = this.options.value,
11878
			percentage = this._percentage();
11879
11880
		this.valueDiv
11881
			.toggle( this.indeterminate || value > this.min )
11882
			.toggleClass( "ui-corner-right", value === this.options.max )
11883
			.width( percentage.toFixed(0) + "%" );
11884
11885
		this.element.toggleClass( "ui-progressbar-indeterminate", this.indeterminate );
11886
11887
		if ( this.indeterminate ) {
11888
			this.element.removeAttr( "aria-valuenow" );
11889
			if ( !this.overlayDiv ) {
11890
				this.overlayDiv = $( "<div class='ui-progressbar-overlay'></div>" ).appendTo( this.valueDiv );
11891
			}
11892
		} else {
11893
			this.element.attr({
11894
				"aria-valuemax": this.options.max,
11895
				"aria-valuenow": value
11896
			});
11897
			if ( this.overlayDiv ) {
11898
				this.overlayDiv.remove();
11899
				this.overlayDiv = null;
11900
			}
11901
		}
11902
11903
		if ( this.oldValue !== value ) {
11904
			this.oldValue = value;
11905
			this._trigger( "change" );
11906
		}
11907
		if ( value === this.options.max ) {
11908
			this._trigger( "complete" );
11909
		}
11910
	}
11911
});
11912
11913
11914
/*!
11915
 * jQuery UI Selectable 1.11.4
11916
 * http://jqueryui.com
11917
 *
11918
 * Copyright jQuery Foundation and other contributors
11919
 * Released under the MIT license.
11920
 * http://jquery.org/license
11921
 *
11922
 * http://api.jqueryui.com/selectable/
11923
 */
11924
11925
11926
var selectable = $.widget("ui.selectable", $.ui.mouse, {
11927
	version: "1.11.4",
11928
	options: {
11929
		appendTo: "body",
11930
		autoRefresh: true,
11931
		distance: 0,
11932
		filter: "*",
11933
		tolerance: "touch",
11934
11935
		// callbacks
11936
		selected: null,
11937
		selecting: null,
11938
		start: null,
11939
		stop: null,
11940
		unselected: null,
11941
		unselecting: null
11942
	},
11943
	_create: function() {
11944
		var selectees,
11945
			that = this;
11946
11947
		this.element.addClass("ui-selectable");
11948
11949
		this.dragged = false;
11950
11951
		// cache selectee children based on filter
11952
		this.refresh = function() {
11953
			selectees = $(that.options.filter, that.element[0]);
11954
			selectees.addClass("ui-selectee");
11955
			selectees.each(function() {
11956
				var $this = $(this),
11957
					pos = $this.offset();
11958
				$.data(this, "selectable-item", {
11959
					element: this,
11960
					$element: $this,
11961
					left: pos.left,
11962
					top: pos.top,
11963
					right: pos.left + $this.outerWidth(),
11964
					bottom: pos.top + $this.outerHeight(),
11965
					startselected: false,
11966
					selected: $this.hasClass("ui-selected"),
11967
					selecting: $this.hasClass("ui-selecting"),
11968
					unselecting: $this.hasClass("ui-unselecting")
11969
				});
11970
			});
11971
		};
11972
		this.refresh();
11973
11974
		this.selectees = selectees.addClass("ui-selectee");
11975
11976
		this._mouseInit();
11977
11978
		this.helper = $("<div class='ui-selectable-helper'></div>");
11979
	},
11980
11981
	_destroy: function() {
11982
		this.selectees
11983
			.removeClass("ui-selectee")
11984
			.removeData("selectable-item");
11985
		this.element
11986
			.removeClass("ui-selectable ui-selectable-disabled");
11987
		this._mouseDestroy();
11988
	},
11989
11990
	_mouseStart: function(event) {
11991
		var that = this,
11992
			options = this.options;
11993
11994
		this.opos = [ event.pageX, event.pageY ];
11995
11996
		if (this.options.disabled) {
11997
			return;
11998
		}
11999
12000
		this.selectees = $(options.filter, this.element[0]);
12001
12002
		this._trigger("start", event);
12003
12004
		$(options.appendTo).append(this.helper);
12005
		// position helper (lasso)
12006
		this.helper.css({
12007
			"left": event.pageX,
12008
			"top": event.pageY,
12009
			"width": 0,
12010
			"height": 0
12011
		});
12012
12013
		if (options.autoRefresh) {
12014
			this.refresh();
12015
		}
12016
12017
		this.selectees.filter(".ui-selected").each(function() {
12018
			var selectee = $.data(this, "selectable-item");
12019
			selectee.startselected = true;
12020
			if (!event.metaKey && !event.ctrlKey) {
12021
				selectee.$element.removeClass("ui-selected");
12022
				selectee.selected = false;
12023
				selectee.$element.addClass("ui-unselecting");
12024
				selectee.unselecting = true;
12025
				// selectable UNSELECTING callback
12026
				that._trigger("unselecting", event, {
12027
					unselecting: selectee.element
12028
				});
12029
			}
12030
		});
12031
12032
		$(event.target).parents().addBack().each(function() {
12033
			var doSelect,
12034
				selectee = $.data(this, "selectable-item");
12035
			if (selectee) {
12036
				doSelect = (!event.metaKey && !event.ctrlKey) || !selectee.$element.hasClass("ui-selected");
12037
				selectee.$element
12038
					.removeClass(doSelect ? "ui-unselecting" : "ui-selected")
12039
					.addClass(doSelect ? "ui-selecting" : "ui-unselecting");
12040
				selectee.unselecting = !doSelect;
12041
				selectee.selecting = doSelect;
12042
				selectee.selected = doSelect;
12043
				// selectable (UN)SELECTING callback
12044
				if (doSelect) {
12045
					that._trigger("selecting", event, {
12046
						selecting: selectee.element
12047
					});
12048
				} else {
12049
					that._trigger("unselecting", event, {
12050
						unselecting: selectee.element
12051
					});
12052
				}
12053
				return false;
12054
			}
12055
		});
12056
12057
	},
12058
12059
	_mouseDrag: function(event) {
12060
12061
		this.dragged = true;
12062
12063
		if (this.options.disabled) {
12064
			return;
12065
		}
12066
12067
		var tmp,
12068
			that = this,
12069
			options = this.options,
12070
			x1 = this.opos[0],
12071
			y1 = this.opos[1],
12072
			x2 = event.pageX,
12073
			y2 = event.pageY;
12074
12075
		if (x1 > x2) { tmp = x2; x2 = x1; x1 = tmp; }
12076
		if (y1 > y2) { tmp = y2; y2 = y1; y1 = tmp; }
12077
		this.helper.css({ left: x1, top: y1, width: x2 - x1, height: y2 - y1 });
12078
12079
		this.selectees.each(function() {
12080
			var selectee = $.data(this, "selectable-item"),
12081
				hit = false;
12082
12083
			//prevent helper from being selected if appendTo: selectable
12084
			if (!selectee || selectee.element === that.element[0]) {
12085
				return;
12086
			}
12087
12088
			if (options.tolerance === "touch") {
12089
				hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
12090
			} else if (options.tolerance === "fit") {
12091
				hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
12092
			}
12093
12094
			if (hit) {
12095
				// SELECT
12096
				if (selectee.selected) {
12097
					selectee.$element.removeClass("ui-selected");
12098
					selectee.selected = false;
12099
				}
12100
				if (selectee.unselecting) {
12101
					selectee.$element.removeClass("ui-unselecting");
12102
					selectee.unselecting = false;
12103
				}
12104
				if (!selectee.selecting) {
12105
					selectee.$element.addClass("ui-selecting");
12106
					selectee.selecting = true;
12107
					// selectable SELECTING callback
12108
					that._trigger("selecting", event, {
12109
						selecting: selectee.element
12110
					});
12111
				}
12112
			} else {
12113
				// UNSELECT
12114
				if (selectee.selecting) {
12115
					if ((event.metaKey || event.ctrlKey) && selectee.startselected) {
12116
						selectee.$element.removeClass("ui-selecting");
12117
						selectee.selecting = false;
12118
						selectee.$element.addClass("ui-selected");
12119
						selectee.selected = true;
12120
					} else {
12121
						selectee.$element.removeClass("ui-selecting");
12122
						selectee.selecting = false;
12123
						if (selectee.startselected) {
12124
							selectee.$element.addClass("ui-unselecting");
12125
							selectee.unselecting = true;
12126
						}
12127
						// selectable UNSELECTING callback
12128
						that._trigger("unselecting", event, {
12129
							unselecting: selectee.element
12130
						});
12131
					}
12132
				}
12133
				if (selectee.selected) {
12134
					if (!event.metaKey && !event.ctrlKey && !selectee.startselected) {
12135
						selectee.$element.removeClass("ui-selected");
12136
						selectee.selected = false;
12137
12138
						selectee.$element.addClass("ui-unselecting");
12139
						selectee.unselecting = true;
12140
						// selectable UNSELECTING callback
12141
						that._trigger("unselecting", event, {
12142
							unselecting: selectee.element
12143
						});
12144
					}
12145
				}
12146
			}
12147
		});
12148
12149
		return false;
12150
	},
12151
12152
	_mouseStop: function(event) {
12153
		var that = this;
12154
12155
		this.dragged = false;
12156
12157
		$(".ui-unselecting", this.element[0]).each(function() {
12158
			var selectee = $.data(this, "selectable-item");
12159
			selectee.$element.removeClass("ui-unselecting");
12160
			selectee.unselecting = false;
12161
			selectee.startselected = false;
12162
			that._trigger("unselected", event, {
12163
				unselected: selectee.element
12164
			});
12165
		});
12166
		$(".ui-selecting", this.element[0]).each(function() {
12167
			var selectee = $.data(this, "selectable-item");
12168
			selectee.$element.removeClass("ui-selecting").addClass("ui-selected");
12169
			selectee.selecting = false;
12170
			selectee.selected = true;
12171
			selectee.startselected = true;
12172
			that._trigger("selected", event, {
12173
				selected: selectee.element
12174
			});
12175
		});
12176
		this._trigger("stop", event);
12177
12178
		this.helper.remove();
12179
12180
		return false;
12181
	}
12182
12183
});
12184
12185
12186
/*!
12187
 * jQuery UI Selectmenu 1.11.4
12188
 * http://jqueryui.com
12189
 *
12190
 * Copyright jQuery Foundation and other contributors
12191
 * Released under the MIT license.
12192
 * http://jquery.org/license
12193
 *
12194
 * http://api.jqueryui.com/selectmenu
12195
 */
12196
12197
12198
var selectmenu = $.widget( "ui.selectmenu", {
12199
	version: "1.11.4",
12200
	defaultElement: "<select>",
12201
	options: {
12202
		appendTo: null,
12203
		disabled: null,
12204
		icons: {
12205
			button: "ui-icon-triangle-1-s"
12206
		},
12207
		position: {
12208
			my: "left top",
12209
			at: "left bottom",
12210
			collision: "none"
12211
		},
12212
		width: null,
12213
12214
		// callbacks
12215
		change: null,
12216
		close: null,
12217
		focus: null,
12218
		open: null,
12219
		select: null
12220
	},
12221
12222
	_create: function() {
12223
		var selectmenuId = this.element.uniqueId().attr( "id" );
12224
		this.ids = {
12225
			element: selectmenuId,
12226
			button: selectmenuId + "-button",
12227
			menu: selectmenuId + "-menu"
12228
		};
12229
12230
		this._drawButton();
12231
		this._drawMenu();
12232
12233
		if ( this.options.disabled ) {
12234
			this.disable();
12235
		}
12236
	},
12237
12238
	_drawButton: function() {
12239
		var that = this;
12240
12241
		// Associate existing label with the new button
12242
		this.label = $( "label[for='" + this.ids.element + "']" ).attr( "for", this.ids.button );
12243
		this._on( this.label, {
12244
			click: function( event ) {
12245
				this.button.focus();
12246
				event.preventDefault();
12247
			}
12248
		});
12249
12250
		// Hide original select element
12251
		this.element.hide();
12252
12253
		// Create button
12254
		this.button = $( "<span>", {
12255
			"class": "ui-selectmenu-button ui-widget ui-state-default ui-corner-all",
12256
			tabindex: this.options.disabled ? -1 : 0,
12257
			id: this.ids.button,
12258
			role: "combobox",
12259
			"aria-expanded": "false",
12260
			"aria-autocomplete": "list",
12261
			"aria-owns": this.ids.menu,
12262
			"aria-haspopup": "true"
12263
		})
12264
			.insertAfter( this.element );
12265
12266
		$( "<span>", {
12267
			"class": "ui-icon " + this.options.icons.button
12268
		})
12269
			.prependTo( this.button );
12270
12271
		this.buttonText = $( "<span>", {
12272
			"class": "ui-selectmenu-text"
12273
		})
12274
			.appendTo( this.button );
12275
12276
		this._setText( this.buttonText, this.element.find( "option:selected" ).text() );
12277
		this._resizeButton();
12278
12279
		this._on( this.button, this._buttonEvents );
12280
		this.button.one( "focusin", function() {
12281
12282
			// Delay rendering the menu items until the button receives focus.
12283
			// The menu may have already been rendered via a programmatic open.
12284
			if ( !that.menuItems ) {
12285
				that._refreshMenu();
12286
			}
12287
		});
12288
		this._hoverable( this.button );
12289
		this._focusable( this.button );
12290
	},
12291
12292
	_drawMenu: function() {
12293
		var that = this;
12294
12295
		// Create menu
12296
		this.menu = $( "<ul>", {
12297
			"aria-hidden": "true",
12298
			"aria-labelledby": this.ids.button,
12299
			id: this.ids.menu
12300
		});
12301
12302
		// Wrap menu
12303
		this.menuWrap = $( "<div>", {
12304
			"class": "ui-selectmenu-menu ui-front"
12305
		})
12306
			.append( this.menu )
12307
			.appendTo( this._appendTo() );
12308
12309
		// Initialize menu widget
12310
		this.menuInstance = this.menu
12311
			.menu({
12312
				role: "listbox",
12313
				select: function( event, ui ) {
12314
					event.preventDefault();
12315
12316
					// support: IE8
12317
					// If the item was selected via a click, the text selection
12318
					// will be destroyed in IE
12319
					that._setSelection();
12320
12321
					that._select( ui.item.data( "ui-selectmenu-item" ), event );
12322
				},
12323
				focus: function( event, ui ) {
12324
					var item = ui.item.data( "ui-selectmenu-item" );
12325
12326
					// Prevent inital focus from firing and check if its a newly focused item
12327
					if ( that.focusIndex != null && item.index !== that.focusIndex ) {
12328
						that._trigger( "focus", event, { item: item } );
12329
						if ( !that.isOpen ) {
12330
							that._select( item, event );
12331
						}
12332
					}
12333
					that.focusIndex = item.index;
12334
12335
					that.button.attr( "aria-activedescendant",
12336
						that.menuItems.eq( item.index ).attr( "id" ) );
12337
				}
12338
			})
12339
			.menu( "instance" );
12340
12341
		// Adjust menu styles to dropdown
12342
		this.menu
12343
			.addClass( "ui-corner-bottom" )
12344
			.removeClass( "ui-corner-all" );
12345
12346
		// Don't close the menu on mouseleave
12347
		this.menuInstance._off( this.menu, "mouseleave" );
12348
12349
		// Cancel the menu's collapseAll on document click
12350
		this.menuInstance._closeOnDocumentClick = function() {
12351
			return false;
12352
		};
12353
12354
		// Selects often contain empty items, but never contain dividers
12355
		this.menuInstance._isDivider = function() {
12356
			return false;
12357
		};
12358
	},
12359
12360
	refresh: function() {
12361
		this._refreshMenu();
12362
		this._setText( this.buttonText, this._getSelectedItem().text() );
12363
		if ( !this.options.width ) {
12364
			this._resizeButton();
12365
		}
12366
	},
12367
12368
	_refreshMenu: function() {
12369
		this.menu.empty();
12370
12371
		var item,
12372
			options = this.element.find( "option" );
12373
12374
		if ( !options.length ) {
12375
			return;
12376
		}
12377
12378
		this._parseOptions( options );
12379
		this._renderMenu( this.menu, this.items );
12380
12381
		this.menuInstance.refresh();
12382
		this.menuItems = this.menu.find( "li" ).not( ".ui-selectmenu-optgroup" );
12383
12384
		item = this._getSelectedItem();
12385
12386
		// Update the menu to have the correct item focused
12387
		this.menuInstance.focus( null, item );
12388
		this._setAria( item.data( "ui-selectmenu-item" ) );
12389
12390
		// Set disabled state
12391
		this._setOption( "disabled", this.element.prop( "disabled" ) );
12392
	},
12393
12394
	open: function( event ) {
12395
		if ( this.options.disabled ) {
12396
			return;
12397
		}
12398
12399
		// If this is the first time the menu is being opened, render the items
12400
		if ( !this.menuItems ) {
12401
			this._refreshMenu();
12402
		} else {
12403
12404
			// Menu clears focus on close, reset focus to selected item
12405
			this.menu.find( ".ui-state-focus" ).removeClass( "ui-state-focus" );
12406
			this.menuInstance.focus( null, this._getSelectedItem() );
12407
		}
12408
12409
		this.isOpen = true;
12410
		this._toggleAttr();
12411
		this._resizeMenu();
12412
		this._position();
12413
12414
		this._on( this.document, this._documentClick );
12415
12416
		this._trigger( "open", event );
12417
	},
12418
12419
	_position: function() {
12420
		this.menuWrap.position( $.extend( { of: this.button }, this.options.position ) );
12421
	},
12422
12423
	close: function( event ) {
12424
		if ( !this.isOpen ) {
12425
			return;
12426
		}
12427
12428
		this.isOpen = false;
12429
		this._toggleAttr();
12430
12431
		this.range = null;
12432
		this._off( this.document );
12433
12434
		this._trigger( "close", event );
12435
	},
12436
12437
	widget: function() {
12438
		return this.button;
12439
	},
12440
12441
	menuWidget: function() {
12442
		return this.menu;
12443
	},
12444
12445
	_renderMenu: function( ul, items ) {
12446
		var that = this,
12447
			currentOptgroup = "";
12448
12449
		$.each( items, function( index, item ) {
12450
			if ( item.optgroup !== currentOptgroup ) {
12451
				$( "<li>", {
12452
					"class": "ui-selectmenu-optgroup ui-menu-divider" +
12453
						( item.element.parent( "optgroup" ).prop( "disabled" ) ?
12454
							" ui-state-disabled" :
12455
							"" ),
12456
					text: item.optgroup
12457
				})
12458
					.appendTo( ul );
12459
12460
				currentOptgroup = item.optgroup;
12461
			}
12462
12463
			that._renderItemData( ul, item );
12464
		});
12465
	},
12466
12467
	_renderItemData: function( ul, item ) {
12468
		return this._renderItem( ul, item ).data( "ui-selectmenu-item", item );
12469
	},
12470
12471
	_renderItem: function( ul, item ) {
12472
		var li = $( "<li>" );
12473
12474
		if ( item.disabled ) {
12475
			li.addClass( "ui-state-disabled" );
12476
		}
12477
		this._setText( li, item.label );
12478
12479
		return li.appendTo( ul );
12480
	},
12481
12482
	_setText: function( element, value ) {
12483
		if ( value ) {
12484
			element.text( value );
12485
		} else {
12486
			element.html( "&#160;" );
12487
		}
12488
	},
12489
12490
	_move: function( direction, event ) {
12491
		var item, next,
12492
			filter = ".ui-menu-item";
12493
12494
		if ( this.isOpen ) {
12495
			item = this.menuItems.eq( this.focusIndex );
12496
		} else {
12497
			item = this.menuItems.eq( this.element[ 0 ].selectedIndex );
12498
			filter += ":not(.ui-state-disabled)";
12499
		}
12500
12501
		if ( direction === "first" || direction === "last" ) {
12502
			next = item[ direction === "first" ? "prevAll" : "nextAll" ]( filter ).eq( -1 );
12503
		} else {
12504
			next = item[ direction + "All" ]( filter ).eq( 0 );
12505
		}
12506
12507
		if ( next.length ) {
12508
			this.menuInstance.focus( event, next );
12509
		}
12510
	},
12511
12512
	_getSelectedItem: function() {
12513
		return this.menuItems.eq( this.element[ 0 ].selectedIndex );
12514
	},
12515
12516
	_toggle: function( event ) {
12517
		this[ this.isOpen ? "close" : "open" ]( event );
12518
	},
12519
12520
	_setSelection: function() {
12521
		var selection;
12522
12523
		if ( !this.range ) {
12524
			return;
12525
		}
12526
12527
		if ( window.getSelection ) {
12528
			selection = window.getSelection();
12529
			selection.removeAllRanges();
12530
			selection.addRange( this.range );
12531
12532
		// support: IE8
12533
		} else {
12534
			this.range.select();
12535
		}
12536
12537
		// support: IE
12538
		// Setting the text selection kills the button focus in IE, but
12539
		// restoring the focus doesn't kill the selection.
12540
		this.button.focus();
12541
	},
12542
12543
	_documentClick: {
12544
		mousedown: function( event ) {
12545
			if ( !this.isOpen ) {
12546
				return;
12547
			}
12548
12549
			if ( !$( event.target ).closest( ".ui-selectmenu-menu, #" + this.ids.button ).length ) {
12550
				this.close( event );
12551
			}
12552
		}
12553
	},
12554
12555
	_buttonEvents: {
12556
12557
		// Prevent text selection from being reset when interacting with the selectmenu (#10144)
12558
		mousedown: function() {
12559
			var selection;
12560
12561
			if ( window.getSelection ) {
12562
				selection = window.getSelection();
12563
				if ( selection.rangeCount ) {
12564
					this.range = selection.getRangeAt( 0 );
12565
				}
12566
12567
			// support: IE8
12568
			} else {
12569
				this.range = document.selection.createRange();
12570
			}
12571
		},
12572
12573
		click: function( event ) {
12574
			this._setSelection();
12575
			this._toggle( event );
12576
		},
12577
12578
		keydown: function( event ) {
12579
			var preventDefault = true;
12580
			switch ( event.keyCode ) {
12581
				case $.ui.keyCode.TAB:
12582
				case $.ui.keyCode.ESCAPE:
12583
					this.close( event );
12584
					preventDefault = false;
12585
					break;
12586
				case $.ui.keyCode.ENTER:
12587
					if ( this.isOpen ) {
12588
						this._selectFocusedItem( event );
12589
					}
12590
					break;
12591
				case $.ui.keyCode.UP:
12592
					if ( event.altKey ) {
12593
						this._toggle( event );
12594
					} else {
12595
						this._move( "prev", event );
12596
					}
12597
					break;
12598
				case $.ui.keyCode.DOWN:
12599
					if ( event.altKey ) {
12600
						this._toggle( event );
12601
					} else {
12602
						this._move( "next", event );
12603
					}
12604
					break;
12605
				case $.ui.keyCode.SPACE:
12606
					if ( this.isOpen ) {
12607
						this._selectFocusedItem( event );
12608
					} else {
12609
						this._toggle( event );
12610
					}
12611
					break;
12612
				case $.ui.keyCode.LEFT:
12613
					this._move( "prev", event );
12614
					break;
12615
				case $.ui.keyCode.RIGHT:
12616
					this._move( "next", event );
12617
					break;
12618
				case $.ui.keyCode.HOME:
12619
				case $.ui.keyCode.PAGE_UP:
12620
					this._move( "first", event );
12621
					break;
12622
				case $.ui.keyCode.END:
12623
				case $.ui.keyCode.PAGE_DOWN:
12624
					this._move( "last", event );
12625
					break;
12626
				default:
12627
					this.menu.trigger( event );
12628
					preventDefault = false;
12629
			}
12630
12631
			if ( preventDefault ) {
12632
				event.preventDefault();
12633
			}
12634
		}
12635
	},
12636
12637
	_selectFocusedItem: function( event ) {
12638
		var item = this.menuItems.eq( this.focusIndex );
12639
		if ( !item.hasClass( "ui-state-disabled" ) ) {
12640
			this._select( item.data( "ui-selectmenu-item" ), event );
12641
		}
12642
	},
12643
12644
	_select: function( item, event ) {
12645
		var oldIndex = this.element[ 0 ].selectedIndex;
12646
12647
		// Change native select element
12648
		this.element[ 0 ].selectedIndex = item.index;
12649
		this._setText( this.buttonText, item.label );
12650
		this._setAria( item );
12651
		this._trigger( "select", event, { item: item } );
12652
12653
		if ( item.index !== oldIndex ) {
12654
			this._trigger( "change", event, { item: item } );
12655
		}
12656
12657
		this.close( event );
12658
	},
12659
12660
	_setAria: function( item ) {
12661
		var id = this.menuItems.eq( item.index ).attr( "id" );
12662
12663
		this.button.attr({
12664
			"aria-labelledby": id,
12665
			"aria-activedescendant": id
12666
		});
12667
		this.menu.attr( "aria-activedescendant", id );
12668
	},
12669
12670
	_setOption: function( key, value ) {
12671
		if ( key === "icons" ) {
12672
			this.button.find( "span.ui-icon" )
12673
				.removeClass( this.options.icons.button )
12674
				.addClass( value.button );
12675
		}
12676
12677
		this._super( key, value );
12678
12679
		if ( key === "appendTo" ) {
12680
			this.menuWrap.appendTo( this._appendTo() );
12681
		}
12682
12683
		if ( key === "disabled" ) {
12684
			this.menuInstance.option( "disabled", value );
12685
			this.button
12686
				.toggleClass( "ui-state-disabled", value )
12687
				.attr( "aria-disabled", value );
12688
12689
			this.element.prop( "disabled", value );
12690
			if ( value ) {
12691
				this.button.attr( "tabindex", -1 );
12692
				this.close();
12693
			} else {
12694
				this.button.attr( "tabindex", 0 );
12695
			}
12696
		}
12697
12698
		if ( key === "width" ) {
12699
			this._resizeButton();
12700
		}
12701
	},
12702
12703
	_appendTo: function() {
12704
		var element = this.options.appendTo;
12705
12706
		if ( element ) {
12707
			element = element.jquery || element.nodeType ?
12708
				$( element ) :
12709
				this.document.find( element ).eq( 0 );
12710
		}
12711
12712
		if ( !element || !element[ 0 ] ) {
12713
			element = this.element.closest( ".ui-front" );
12714
		}
12715
12716
		if ( !element.length ) {
12717
			element = this.document[ 0 ].body;
12718
		}
12719
12720
		return element;
12721
	},
12722
12723
	_toggleAttr: function() {
12724
		this.button
12725
			.toggleClass( "ui-corner-top", this.isOpen )
12726
			.toggleClass( "ui-corner-all", !this.isOpen )
12727
			.attr( "aria-expanded", this.isOpen );
12728
		this.menuWrap.toggleClass( "ui-selectmenu-open", this.isOpen );
12729
		this.menu.attr( "aria-hidden", !this.isOpen );
12730
	},
12731
12732
	_resizeButton: function() {
12733
		var width = this.options.width;
12734
12735
		if ( !width ) {
12736
			width = this.element.show().outerWidth();
12737
			this.element.hide();
12738
		}
12739
12740
		this.button.outerWidth( width );
12741
	},
12742
12743
	_resizeMenu: function() {
12744
		this.menu.outerWidth( Math.max(
12745
			this.button.outerWidth(),
12746
12747
			// support: IE10
12748
			// IE10 wraps long text (possibly a rounding bug)
12749
			// so we add 1px to avoid the wrapping
12750
			this.menu.width( "" ).outerWidth() + 1
12751
		) );
12752
	},
12753
12754
	_getCreateOptions: function() {
12755
		return { disabled: this.element.prop( "disabled" ) };
12756
	},
12757
12758
	_parseOptions: function( options ) {
12759
		var data = [];
12760
		options.each(function( index, item ) {
12761
			var option = $( item ),
12762
				optgroup = option.parent( "optgroup" );
12763
			data.push({
12764
				element: option,
12765
				index: index,
12766
				value: option.val(),
12767
				label: option.text(),
12768
				optgroup: optgroup.attr( "label" ) || "",
12769
				disabled: optgroup.prop( "disabled" ) || option.prop( "disabled" )
12770
			});
12771
		});
12772
		this.items = data;
12773
	},
12774
12775
	_destroy: function() {
12776
		this.menuWrap.remove();
12777
		this.button.remove();
12778
		this.element.show();
12779
		this.element.removeUniqueId();
12780
		this.label.attr( "for", this.ids.element );
12781
	}
12782
});
12783
12784
12785
/*!
12786
 * jQuery UI Slider 1.11.4
12787
 * http://jqueryui.com
12788
 *
12789
 * Copyright jQuery Foundation and other contributors
12790
 * Released under the MIT license.
12791
 * http://jquery.org/license
12792
 *
12793
 * http://api.jqueryui.com/slider/
12794
 */
12795
12796
12797
var slider = $.widget( "ui.slider", $.ui.mouse, {
12798
	version: "1.11.4",
12799
	widgetEventPrefix: "slide",
12800
12801
	options: {
12802
		animate: false,
12803
		distance: 0,
12804
		max: 100,
12805
		min: 0,
12806
		orientation: "horizontal",
12807
		range: false,
12808
		step: 1,
12809
		value: 0,
12810
		values: null,
12811
12812
		// callbacks
12813
		change: null,
12814
		slide: null,
12815
		start: null,
12816
		stop: null
12817
	},
12818
12819
	// number of pages in a slider
12820
	// (how many times can you page up/down to go through the whole range)
12821
	numPages: 5,
12822
12823
	_create: function() {
12824
		this._keySliding = false;
12825
		this._mouseSliding = false;
12826
		this._animateOff = true;
12827
		this._handleIndex = null;
12828
		this._detectOrientation();
12829
		this._mouseInit();
12830
		this._calculateNewMax();
12831
12832
		this.element
12833
			.addClass( "ui-slider" +
12834
				" ui-slider-" + this.orientation +
12835
				" ui-widget" +
12836
				" ui-widget-content" +
12837
				" ui-corner-all");
12838
12839
		this._refresh();
12840
		this._setOption( "disabled", this.options.disabled );
12841
12842
		this._animateOff = false;
12843
	},
12844
12845
	_refresh: function() {
12846
		this._createRange();
12847
		this._createHandles();
12848
		this._setupEvents();
12849
		this._refreshValue();
12850
	},
12851
12852
	_createHandles: function() {
12853
		var i, handleCount,
12854
			options = this.options,
12855
			existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ),
12856
			handle = "<span class='ui-slider-handle ui-state-default ui-corner-all' tabindex='0'></span>",
12857
			handles = [];
12858
12859
		handleCount = ( options.values && options.values.length ) || 1;
12860
12861
		if ( existingHandles.length > handleCount ) {
12862
			existingHandles.slice( handleCount ).remove();
12863
			existingHandles = existingHandles.slice( 0, handleCount );
12864
		}
12865
12866
		for ( i = existingHandles.length; i < handleCount; i++ ) {
12867
			handles.push( handle );
12868
		}
12869
12870
		this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) );
12871
12872
		this.handle = this.handles.eq( 0 );
12873
12874
		this.handles.each(function( i ) {
12875
			$( this ).data( "ui-slider-handle-index", i );
12876
		});
12877
	},
12878
12879
	_createRange: function() {
12880
		var options = this.options,
12881
			classes = "";
12882
12883
		if ( options.range ) {
12884
			if ( options.range === true ) {
12885
				if ( !options.values ) {
12886
					options.values = [ this._valueMin(), this._valueMin() ];
12887
				} else if ( options.values.length && options.values.length !== 2 ) {
12888
					options.values = [ options.values[0], options.values[0] ];
12889
				} else if ( $.isArray( options.values ) ) {
12890
					options.values = options.values.slice(0);
12891
				}
12892
			}
12893
12894
			if ( !this.range || !this.range.length ) {
12895
				this.range = $( "<div></div>" )
12896
					.appendTo( this.element );
12897
12898
				classes = "ui-slider-range" +
12899
				// note: this isn't the most fittingly semantic framework class for this element,
12900
				// but worked best visually with a variety of themes
12901
				" ui-widget-header ui-corner-all";
12902
			} else {
12903
				this.range.removeClass( "ui-slider-range-min ui-slider-range-max" )
12904
					// Handle range switching from true to min/max
12905
					.css({
12906
						"left": "",
12907
						"bottom": ""
12908
					});
12909
			}
12910
12911
			this.range.addClass( classes +
12912
				( ( options.range === "min" || options.range === "max" ) ? " ui-slider-range-" + options.range : "" ) );
12913
		} else {
12914
			if ( this.range ) {
12915
				this.range.remove();
12916
			}
12917
			this.range = null;
12918
		}
12919
	},
12920
12921
	_setupEvents: function() {
12922
		this._off( this.handles );
12923
		this._on( this.handles, this._handleEvents );
12924
		this._hoverable( this.handles );
12925
		this._focusable( this.handles );
12926
	},
12927
12928
	_destroy: function() {
12929
		this.handles.remove();
12930
		if ( this.range ) {
12931
			this.range.remove();
12932
		}
12933
12934
		this.element
12935
			.removeClass( "ui-slider" +
12936
				" ui-slider-horizontal" +
12937
				" ui-slider-vertical" +
12938
				" ui-widget" +
12939
				" ui-widget-content" +
12940
				" ui-corner-all" );
12941
12942
		this._mouseDestroy();
12943
	},
12944
12945
	_mouseCapture: function( event ) {
12946
		var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle,
12947
			that = this,
12948
			o = this.options;
12949
12950
		if ( o.disabled ) {
12951
			return false;
12952
		}
12953
12954
		this.elementSize = {
12955
			width: this.element.outerWidth(),
12956
			height: this.element.outerHeight()
12957
		};
12958
		this.elementOffset = this.element.offset();
12959
12960
		position = { x: event.pageX, y: event.pageY };
12961
		normValue = this._normValueFromMouse( position );
12962
		distance = this._valueMax() - this._valueMin() + 1;
12963
		this.handles.each(function( i ) {
12964
			var thisDistance = Math.abs( normValue - that.values(i) );
12965
			if (( distance > thisDistance ) ||
12966
				( distance === thisDistance &&
12967
					(i === that._lastChangedValue || that.values(i) === o.min ))) {
12968
				distance = thisDistance;
12969
				closestHandle = $( this );
12970
				index = i;
12971
			}
12972
		});
12973
12974
		allowed = this._start( event, index );
12975
		if ( allowed === false ) {
12976
			return false;
12977
		}
12978
		this._mouseSliding = true;
12979
12980
		this._handleIndex = index;
12981
12982
		closestHandle
12983
			.addClass( "ui-state-active" )
12984
			.focus();
12985
12986
		offset = closestHandle.offset();
12987
		mouseOverHandle = !$( event.target ).parents().addBack().is( ".ui-slider-handle" );
12988
		this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
12989
			left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
12990
			top: event.pageY - offset.top -
12991
				( closestHandle.height() / 2 ) -
12992
				( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
12993
				( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
12994
				( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
12995
		};
12996
12997
		if ( !this.handles.hasClass( "ui-state-hover" ) ) {
12998
			this._slide( event, index, normValue );
12999
		}
13000
		this._animateOff = true;
13001
		return true;
13002
	},
13003
13004
	_mouseStart: function() {
13005
		return true;
13006
	},
13007
13008
	_mouseDrag: function( event ) {
13009
		var position = { x: event.pageX, y: event.pageY },
13010
			normValue = this._normValueFromMouse( position );
13011
13012
		this._slide( event, this._handleIndex, normValue );
13013
13014
		return false;
13015
	},
13016
13017
	_mouseStop: function( event ) {
13018
		this.handles.removeClass( "ui-state-active" );
13019
		this._mouseSliding = false;
13020
13021
		this._stop( event, this._handleIndex );
13022
		this._change( event, this._handleIndex );
13023
13024
		this._handleIndex = null;
13025
		this._clickOffset = null;
13026
		this._animateOff = false;
13027
13028
		return false;
13029
	},
13030
13031
	_detectOrientation: function() {
13032
		this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
13033
	},
13034
13035
	_normValueFromMouse: function( position ) {
13036
		var pixelTotal,
13037
			pixelMouse,
13038
			percentMouse,
13039
			valueTotal,
13040
			valueMouse;
13041
13042
		if ( this.orientation === "horizontal" ) {
13043
			pixelTotal = this.elementSize.width;
13044
			pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
13045
		} else {
13046
			pixelTotal = this.elementSize.height;
13047
			pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
13048
		}
13049
13050
		percentMouse = ( pixelMouse / pixelTotal );
13051
		if ( percentMouse > 1 ) {
13052
			percentMouse = 1;
13053
		}
13054
		if ( percentMouse < 0 ) {
13055
			percentMouse = 0;
13056
		}
13057
		if ( this.orientation === "vertical" ) {
13058
			percentMouse = 1 - percentMouse;
13059
		}
13060
13061
		valueTotal = this._valueMax() - this._valueMin();
13062
		valueMouse = this._valueMin() + percentMouse * valueTotal;
13063
13064
		return this._trimAlignValue( valueMouse );
13065
	},
13066
13067
	_start: function( event, index ) {
13068
		var uiHash = {
13069
			handle: this.handles[ index ],
13070
			value: this.value()
13071
		};
13072
		if ( this.options.values && this.options.values.length ) {
13073
			uiHash.value = this.values( index );
13074
			uiHash.values = this.values();
13075
		}
13076
		return this._trigger( "start", event, uiHash );
13077
	},
13078
13079
	_slide: function( event, index, newVal ) {
13080
		var otherVal,
13081
			newValues,
13082
			allowed;
13083
13084
		if ( this.options.values && this.options.values.length ) {
13085
			otherVal = this.values( index ? 0 : 1 );
13086
13087
			if ( ( this.options.values.length === 2 && this.options.range === true ) &&
13088
					( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
13089
				) {
13090
				newVal = otherVal;
13091
			}
13092
13093
			if ( newVal !== this.values( index ) ) {
13094
				newValues = this.values();
13095
				newValues[ index ] = newVal;
13096
				// A slide can be canceled by returning false from the slide callback
13097
				allowed = this._trigger( "slide", event, {
13098
					handle: this.handles[ index ],
13099
					value: newVal,
13100
					values: newValues
13101
				} );
13102
				otherVal = this.values( index ? 0 : 1 );
13103
				if ( allowed !== false ) {
13104
					this.values( index, newVal );
13105
				}
13106
			}
13107
		} else {
13108
			if ( newVal !== this.value() ) {
13109
				// A slide can be canceled by returning false from the slide callback
13110
				allowed = this._trigger( "slide", event, {
13111
					handle: this.handles[ index ],
13112
					value: newVal
13113
				} );
13114
				if ( allowed !== false ) {
13115
					this.value( newVal );
13116
				}
13117
			}
13118
		}
13119
	},
13120
13121
	_stop: function( event, index ) {
13122
		var uiHash = {
13123
			handle: this.handles[ index ],
13124
			value: this.value()
13125
		};
13126
		if ( this.options.values && this.options.values.length ) {
13127
			uiHash.value = this.values( index );
13128
			uiHash.values = this.values();
13129
		}
13130
13131
		this._trigger( "stop", event, uiHash );
13132
	},
13133
13134
	_change: function( event, index ) {
13135
		if ( !this._keySliding && !this._mouseSliding ) {
13136
			var uiHash = {
13137
				handle: this.handles[ index ],
13138
				value: this.value()
13139
			};
13140
			if ( this.options.values && this.options.values.length ) {
13141
				uiHash.value = this.values( index );
13142
				uiHash.values = this.values();
13143
			}
13144
13145
			//store the last changed value index for reference when handles overlap
13146
			this._lastChangedValue = index;
13147
13148
			this._trigger( "change", event, uiHash );
13149
		}
13150
	},
13151
13152
	value: function( newValue ) {
13153
		if ( arguments.length ) {
13154
			this.options.value = this._trimAlignValue( newValue );
13155
			this._refreshValue();
13156
			this._change( null, 0 );
13157
			return;
13158
		}
13159
13160
		return this._value();
13161
	},
13162
13163
	values: function( index, newValue ) {
13164
		var vals,
13165
			newValues,
13166
			i;
13167
13168
		if ( arguments.length > 1 ) {
13169
			this.options.values[ index ] = this._trimAlignValue( newValue );
13170
			this._refreshValue();
13171
			this._change( null, index );
13172
			return;
13173
		}
13174
13175
		if ( arguments.length ) {
13176
			if ( $.isArray( arguments[ 0 ] ) ) {
13177
				vals = this.options.values;
13178
				newValues = arguments[ 0 ];
13179
				for ( i = 0; i < vals.length; i += 1 ) {
13180
					vals[ i ] = this._trimAlignValue( newValues[ i ] );
13181
					this._change( null, i );
13182
				}
13183
				this._refreshValue();
13184
			} else {
13185
				if ( this.options.values && this.options.values.length ) {
13186
					return this._values( index );
13187
				} else {
13188
					return this.value();
13189
				}
13190
			}
13191
		} else {
13192
			return this._values();
13193
		}
13194
	},
13195
13196
	_setOption: function( key, value ) {
13197
		var i,
13198
			valsLength = 0;
13199
13200
		if ( key === "range" && this.options.range === true ) {
13201
			if ( value === "min" ) {
13202
				this.options.value = this._values( 0 );
13203
				this.options.values = null;
13204
			} else if ( value === "max" ) {
13205
				this.options.value = this._values( this.options.values.length - 1 );
13206
				this.options.values = null;
13207
			}
13208
		}
13209
13210
		if ( $.isArray( this.options.values ) ) {
13211
			valsLength = this.options.values.length;
13212
		}
13213
13214
		if ( key === "disabled" ) {
13215
			this.element.toggleClass( "ui-state-disabled", !!value );
13216
		}
13217
13218
		this._super( key, value );
13219
13220
		switch ( key ) {
13221
			case "orientation":
13222
				this._detectOrientation();
13223
				this.element
13224
					.removeClass( "ui-slider-horizontal ui-slider-vertical" )
13225
					.addClass( "ui-slider-" + this.orientation );
13226
				this._refreshValue();
13227
13228
				// Reset positioning from previous orientation
13229
				this.handles.css( value === "horizontal" ? "bottom" : "left", "" );
13230
				break;
13231
			case "value":
13232
				this._animateOff = true;
13233
				this._refreshValue();
13234
				this._change( null, 0 );
13235
				this._animateOff = false;
13236
				break;
13237
			case "values":
13238
				this._animateOff = true;
13239
				this._refreshValue();
13240
				for ( i = 0; i < valsLength; i += 1 ) {
13241
					this._change( null, i );
13242
				}
13243
				this._animateOff = false;
13244
				break;
13245
			case "step":
13246
			case "min":
13247
			case "max":
13248
				this._animateOff = true;
13249
				this._calculateNewMax();
13250
				this._refreshValue();
13251
				this._animateOff = false;
13252
				break;
13253
			case "range":
13254
				this._animateOff = true;
13255
				this._refresh();
13256
				this._animateOff = false;
13257
				break;
13258
		}
13259
	},
13260
13261
	//internal value getter
13262
	// _value() returns value trimmed by min and max, aligned by step
13263
	_value: function() {
13264
		var val = this.options.value;
13265
		val = this._trimAlignValue( val );
13266
13267
		return val;
13268
	},
13269
13270
	//internal values getter
13271
	// _values() returns array of values trimmed by min and max, aligned by step
13272
	// _values( index ) returns single value trimmed by min and max, aligned by step
13273
	_values: function( index ) {
13274
		var val,
13275
			vals,
13276
			i;
13277
13278
		if ( arguments.length ) {
13279
			val = this.options.values[ index ];
13280
			val = this._trimAlignValue( val );
13281
13282
			return val;
13283
		} else if ( this.options.values && this.options.values.length ) {
13284
			// .slice() creates a copy of the array
13285
			// this copy gets trimmed by min and max and then returned
13286
			vals = this.options.values.slice();
13287
			for ( i = 0; i < vals.length; i += 1) {
13288
				vals[ i ] = this._trimAlignValue( vals[ i ] );
13289
			}
13290
13291
			return vals;
13292
		} else {
13293
			return [];
13294
		}
13295
	},
13296
13297
	// returns the step-aligned value that val is closest to, between (inclusive) min and max
13298
	_trimAlignValue: function( val ) {
13299
		if ( val <= this._valueMin() ) {
13300
			return this._valueMin();
13301
		}
13302
		if ( val >= this._valueMax() ) {
13303
			return this._valueMax();
13304
		}
13305
		var step = ( this.options.step > 0 ) ? this.options.step : 1,
13306
			valModStep = (val - this._valueMin()) % step,
13307
			alignValue = val - valModStep;
13308
13309
		if ( Math.abs(valModStep) * 2 >= step ) {
13310
			alignValue += ( valModStep > 0 ) ? step : ( -step );
13311
		}
13312
13313
		// Since JavaScript has problems with large floats, round
13314
		// the final value to 5 digits after the decimal point (see #4124)
13315
		return parseFloat( alignValue.toFixed(5) );
13316
	},
13317
13318
	_calculateNewMax: function() {
13319
		var max = this.options.max,
13320
			min = this._valueMin(),
13321
			step = this.options.step,
13322
			aboveMin = Math.floor( ( +( max - min ).toFixed( this._precision() ) ) / step ) * step;
13323
		max = aboveMin + min;
13324
		this.max = parseFloat( max.toFixed( this._precision() ) );
13325
	},
13326
13327
	_precision: function() {
13328
		var precision = this._precisionOf( this.options.step );
13329
		if ( this.options.min !== null ) {
13330
			precision = Math.max( precision, this._precisionOf( this.options.min ) );
13331
		}
13332
		return precision;
13333
	},
13334
13335
	_precisionOf: function( num ) {
13336
		var str = num.toString(),
13337
			decimal = str.indexOf( "." );
13338
		return decimal === -1 ? 0 : str.length - decimal - 1;
13339
	},
13340
13341
	_valueMin: function() {
13342
		return this.options.min;
13343
	},
13344
13345
	_valueMax: function() {
13346
		return this.max;
13347
	},
13348
13349
	_refreshValue: function() {
13350
		var lastValPercent, valPercent, value, valueMin, valueMax,
13351
			oRange = this.options.range,
13352
			o = this.options,
13353
			that = this,
13354
			animate = ( !this._animateOff ) ? o.animate : false,
13355
			_set = {};
13356
13357
		if ( this.options.values && this.options.values.length ) {
13358
			this.handles.each(function( i ) {
13359
				valPercent = ( that.values(i) - that._valueMin() ) / ( that._valueMax() - that._valueMin() ) * 100;
13360
				_set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
13361
				$( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
13362
				if ( that.options.range === true ) {
13363
					if ( that.orientation === "horizontal" ) {
13364
						if ( i === 0 ) {
13365
							that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
13366
						}
13367
						if ( i === 1 ) {
13368
							that.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
13369
						}
13370
					} else {
13371
						if ( i === 0 ) {
13372
							that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
13373
						}
13374
						if ( i === 1 ) {
13375
							that.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
13376
						}
13377
					}
13378
				}
13379
				lastValPercent = valPercent;
13380
			});
13381
		} else {
13382
			value = this.value();
13383
			valueMin = this._valueMin();
13384
			valueMax = this._valueMax();
13385
			valPercent = ( valueMax !== valueMin ) ?
13386
					( value - valueMin ) / ( valueMax - valueMin ) * 100 :
13387
					0;
13388
			_set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
13389
			this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
13390
13391
			if ( oRange === "min" && this.orientation === "horizontal" ) {
13392
				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );
13393
			}
13394
			if ( oRange === "max" && this.orientation === "horizontal" ) {
13395
				this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
13396
			}
13397
			if ( oRange === "min" && this.orientation === "vertical" ) {
13398
				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );
13399
			}
13400
			if ( oRange === "max" && this.orientation === "vertical" ) {
13401
				this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
13402
			}
13403
		}
13404
	},
13405
13406
	_handleEvents: {
13407
		keydown: function( event ) {
13408
			var allowed, curVal, newVal, step,
13409
				index = $( event.target ).data( "ui-slider-handle-index" );
13410
13411
			switch ( event.keyCode ) {
13412
				case $.ui.keyCode.HOME:
13413
				case $.ui.keyCode.END:
13414
				case $.ui.keyCode.PAGE_UP:
13415
				case $.ui.keyCode.PAGE_DOWN:
13416
				case $.ui.keyCode.UP:
13417
				case $.ui.keyCode.RIGHT:
13418
				case $.ui.keyCode.DOWN:
13419
				case $.ui.keyCode.LEFT:
13420
					event.preventDefault();
13421
					if ( !this._keySliding ) {
13422
						this._keySliding = true;
13423
						$( event.target ).addClass( "ui-state-active" );
13424
						allowed = this._start( event, index );
13425
						if ( allowed === false ) {
13426
							return;
13427
						}
13428
					}
13429
					break;
13430
			}
13431
13432
			step = this.options.step;
13433
			if ( this.options.values && this.options.values.length ) {
13434
				curVal = newVal = this.values( index );
13435
			} else {
13436
				curVal = newVal = this.value();
13437
			}
13438
13439
			switch ( event.keyCode ) {
13440
				case $.ui.keyCode.HOME:
13441
					newVal = this._valueMin();
13442
					break;
13443
				case $.ui.keyCode.END:
13444
					newVal = this._valueMax();
13445
					break;
13446
				case $.ui.keyCode.PAGE_UP:
13447
					newVal = this._trimAlignValue(
13448
						curVal + ( ( this._valueMax() - this._valueMin() ) / this.numPages )
13449
					);
13450
					break;
13451
				case $.ui.keyCode.PAGE_DOWN:
13452
					newVal = this._trimAlignValue(
13453
						curVal - ( (this._valueMax() - this._valueMin()) / this.numPages ) );
13454
					break;
13455
				case $.ui.keyCode.UP:
13456
				case $.ui.keyCode.RIGHT:
13457
					if ( curVal === this._valueMax() ) {
13458
						return;
13459
					}
13460
					newVal = this._trimAlignValue( curVal + step );
13461
					break;
13462
				case $.ui.keyCode.DOWN:
13463
				case $.ui.keyCode.LEFT:
13464
					if ( curVal === this._valueMin() ) {
13465
						return;
13466
					}
13467
					newVal = this._trimAlignValue( curVal - step );
13468
					break;
13469
			}
13470
13471
			this._slide( event, index, newVal );
13472
		},
13473
		keyup: function( event ) {
13474
			var index = $( event.target ).data( "ui-slider-handle-index" );
13475
13476
			if ( this._keySliding ) {
13477
				this._keySliding = false;
13478
				this._stop( event, index );
13479
				this._change( event, index );
13480
				$( event.target ).removeClass( "ui-state-active" );
13481
			}
13482
		}
13483
	}
13484
});
13485
13486
13487
/*!
13488
 * jQuery UI Sortable 1.11.4
13489
 * http://jqueryui.com
13490
 *
13491
 * Copyright jQuery Foundation and other contributors
13492
 * Released under the MIT license.
13493
 * http://jquery.org/license
13494
 *
13495
 * http://api.jqueryui.com/sortable/
13496
 */
13497
13498
13499
var sortable = $.widget("ui.sortable", $.ui.mouse, {
13500
	version: "1.11.4",
13501
	widgetEventPrefix: "sort",
13502
	ready: false,
13503
	options: {
13504
		appendTo: "parent",
13505
		axis: false,
13506
		connectWith: false,
13507
		containment: false,
13508
		cursor: "auto",
13509
		cursorAt: false,
13510
		dropOnEmpty: true,
13511
		forcePlaceholderSize: false,
13512
		forceHelperSize: false,
13513
		grid: false,
13514
		handle: false,
13515
		helper: "original",
13516
		items: "> *",
13517
		opacity: false,
13518
		placeholder: false,
13519
		revert: false,
13520
		scroll: true,
13521
		scrollSensitivity: 20,
13522
		scrollSpeed: 20,
13523
		scope: "default",
13524
		tolerance: "intersect",
13525
		zIndex: 1000,
13526
13527
		// callbacks
13528
		activate: null,
13529
		beforeStop: null,
13530
		change: null,
13531
		deactivate: null,
13532
		out: null,
13533
		over: null,
13534
		receive: null,
13535
		remove: null,
13536
		sort: null,
13537
		start: null,
13538
		stop: null,
13539
		update: null
13540
	},
13541
13542
	_isOverAxis: function( x, reference, size ) {
13543
		return ( x >= reference ) && ( x < ( reference + size ) );
13544
	},
13545
13546
	_isFloating: function( item ) {
13547
		return (/left|right/).test(item.css("float")) || (/inline|table-cell/).test(item.css("display"));
13548
	},
13549
13550
	_create: function() {
13551
		this.containerCache = {};
13552
		this.element.addClass("ui-sortable");
13553
13554
		//Get the items
13555
		this.refresh();
13556
13557
		//Let's determine the parent's offset
13558
		this.offset = this.element.offset();
13559
13560
		//Initialize mouse events for interaction
13561
		this._mouseInit();
13562
13563
		this._setHandleClassName();
13564
13565
		//We're ready to go
13566
		this.ready = true;
13567
13568
	},
13569
13570
	_setOption: function( key, value ) {
13571
		this._super( key, value );
13572
13573
		if ( key === "handle" ) {
13574
			this._setHandleClassName();
13575
		}
13576
	},
13577
13578
	_setHandleClassName: function() {
13579
		this.element.find( ".ui-sortable-handle" ).removeClass( "ui-sortable-handle" );
13580
		$.each( this.items, function() {
13581
			( this.instance.options.handle ?
13582
				this.item.find( this.instance.options.handle ) : this.item )
13583
				.addClass( "ui-sortable-handle" );
13584
		});
13585
	},
13586
13587
	_destroy: function() {
13588
		this.element
13589
			.removeClass( "ui-sortable ui-sortable-disabled" )
13590
			.find( ".ui-sortable-handle" )
13591
				.removeClass( "ui-sortable-handle" );
13592
		this._mouseDestroy();
13593
13594
		for ( var i = this.items.length - 1; i >= 0; i-- ) {
13595
			this.items[i].item.removeData(this.widgetName + "-item");
13596
		}
13597
13598
		return this;
13599
	},
13600
13601
	_mouseCapture: function(event, overrideHandle) {
13602
		var currentItem = null,
13603
			validHandle = false,
13604
			that = this;
13605
13606
		if (this.reverting) {
13607
			return false;
13608
		}
13609
13610
		if(this.options.disabled || this.options.type === "static") {
13611
			return false;
13612
		}
13613
13614
		//We have to refresh the items data once first
13615
		this._refreshItems(event);
13616
13617
		//Find out if the clicked node (or one of its parents) is a actual item in this.items
13618
		$(event.target).parents().each(function() {
13619
			if($.data(this, that.widgetName + "-item") === that) {
13620
				currentItem = $(this);
13621
				return false;
13622
			}
13623
		});
13624
		if($.data(event.target, that.widgetName + "-item") === that) {
13625
			currentItem = $(event.target);
13626
		}
13627
13628
		if(!currentItem) {
13629
			return false;
13630
		}
13631
		if(this.options.handle && !overrideHandle) {
13632
			$(this.options.handle, currentItem).find("*").addBack().each(function() {
13633
				if(this === event.target) {
13634
					validHandle = true;
13635
				}
13636
			});
13637
			if(!validHandle) {
13638
				return false;
13639
			}
13640
		}
13641
13642
		this.currentItem = currentItem;
13643
		this._removeCurrentsFromItems();
13644
		return true;
13645
13646
	},
13647
13648
	_mouseStart: function(event, overrideHandle, noActivation) {
13649
13650
		var i, body,
13651
			o = this.options;
13652
13653
		this.currentContainer = this;
13654
13655
		//We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
13656
		this.refreshPositions();
13657
13658
		//Create and append the visible helper
13659
		this.helper = this._createHelper(event);
13660
13661
		//Cache the helper size
13662
		this._cacheHelperProportions();
13663
13664
		/*
13665
		 * - Position generation -
13666
		 * This block generates everything position related - it's the core of draggables.
13667
		 */
13668
13669
		//Cache the margins of the original element
13670
		this._cacheMargins();
13671
13672
		//Get the next scrolling parent
13673
		this.scrollParent = this.helper.scrollParent();
13674
13675
		//The element's absolute position on the page minus margins
13676
		this.offset = this.currentItem.offset();
13677
		this.offset = {
13678
			top: this.offset.top - this.margins.top,
13679
			left: this.offset.left - this.margins.left
13680
		};
13681
13682
		$.extend(this.offset, {
13683
			click: { //Where the click happened, relative to the element
13684
				left: event.pageX - this.offset.left,
13685
				top: event.pageY - this.offset.top
13686
			},
13687
			parent: this._getParentOffset(),
13688
			relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
13689
		});
13690
13691
		// Only after we got the offset, we can change the helper's position to absolute
13692
		// TODO: Still need to figure out a way to make relative sorting possible
13693
		this.helper.css("position", "absolute");
13694
		this.cssPosition = this.helper.css("position");
13695
13696
		//Generate the original position
13697
		this.originalPosition = this._generatePosition(event);
13698
		this.originalPageX = event.pageX;
13699
		this.originalPageY = event.pageY;
13700
13701
		//Adjust the mouse offset relative to the helper if "cursorAt" is supplied
13702
		(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
13703
13704
		//Cache the former DOM position
13705
		this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };
13706
13707
		//If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way
13708
		if(this.helper[0] !== this.currentItem[0]) {
13709
			this.currentItem.hide();
13710
		}
13711
13712
		//Create the placeholder
13713
		this._createPlaceholder();
13714
13715
		//Set a containment if given in the options
13716
		if(o.containment) {
13717
			this._setContainment();
13718
		}
13719
13720
		if( o.cursor && o.cursor !== "auto" ) { // cursor option
13721
			body = this.document.find( "body" );
13722
13723
			// support: IE
13724
			this.storedCursor = body.css( "cursor" );
13725
			body.css( "cursor", o.cursor );
13726
13727
			this.storedStylesheet = $( "<style>*{ cursor: "+o.cursor+" !important; }</style>" ).appendTo( body );
13728
		}
13729
13730
		if(o.opacity) { // opacity option
13731
			if (this.helper.css("opacity")) {
13732
				this._storedOpacity = this.helper.css("opacity");
13733
			}
13734
			this.helper.css("opacity", o.opacity);
13735
		}
13736
13737
		if(o.zIndex) { // zIndex option
13738
			if (this.helper.css("zIndex")) {
13739
				this._storedZIndex = this.helper.css("zIndex");
13740
			}
13741
			this.helper.css("zIndex", o.zIndex);
13742
		}
13743
13744
		//Prepare scrolling
13745
		if(this.scrollParent[0] !== this.document[0] && this.scrollParent[0].tagName !== "HTML") {
13746
			this.overflowOffset = this.scrollParent.offset();
13747
		}
13748
13749
		//Call callbacks
13750
		this._trigger("start", event, this._uiHash());
13751
13752
		//Recache the helper size
13753
		if(!this._preserveHelperProportions) {
13754
			this._cacheHelperProportions();
13755
		}
13756
13757
13758
		//Post "activate" events to possible containers
13759
		if( !noActivation ) {
13760
			for ( i = this.containers.length - 1; i >= 0; i-- ) {
13761
				this.containers[ i ]._trigger( "activate", event, this._uiHash( this ) );
13762
			}
13763
		}
13764
13765
		//Prepare possible droppables
13766
		if($.ui.ddmanager) {
13767
			$.ui.ddmanager.current = this;
13768
		}
13769
13770
		if ($.ui.ddmanager && !o.dropBehaviour) {
13771
			$.ui.ddmanager.prepareOffsets(this, event);
13772
		}
13773
13774
		this.dragging = true;
13775
13776
		this.helper.addClass("ui-sortable-helper");
13777
		this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
13778
		return true;
13779
13780
	},
13781
13782
	_mouseDrag: function(event) {
13783
		var i, item, itemElement, intersection,
13784
			o = this.options,
13785
			scrolled = false;
13786
13787
		//Compute the helpers position
13788
		this.position = this._generatePosition(event);
13789
		this.positionAbs = this._convertPositionTo("absolute");
13790
13791
		if (!this.lastPositionAbs) {
13792
			this.lastPositionAbs = this.positionAbs;
13793
		}
13794
13795
		//Do scrolling
13796
		if(this.options.scroll) {
13797
			if(this.scrollParent[0] !== this.document[0] && this.scrollParent[0].tagName !== "HTML") {
13798
13799
				if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) {
13800
					this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
13801
				} else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity) {
13802
					this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
13803
				}
13804
13805
				if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) {
13806
					this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
13807
				} else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity) {
13808
					this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
13809
				}
13810
13811
			} else {
13812
13813
				if(event.pageY - this.document.scrollTop() < o.scrollSensitivity) {
13814
					scrolled = this.document.scrollTop(this.document.scrollTop() - o.scrollSpeed);
13815
				} else if(this.window.height() - (event.pageY - this.document.scrollTop()) < o.scrollSensitivity) {
13816
					scrolled = this.document.scrollTop(this.document.scrollTop() + o.scrollSpeed);
13817
				}
13818
13819
				if(event.pageX - this.document.scrollLeft() < o.scrollSensitivity) {
13820
					scrolled = this.document.scrollLeft(this.document.scrollLeft() - o.scrollSpeed);
13821
				} else if(this.window.width() - (event.pageX - this.document.scrollLeft()) < o.scrollSensitivity) {
13822
					scrolled = this.document.scrollLeft(this.document.scrollLeft() + o.scrollSpeed);
13823
				}
13824
13825
			}
13826
13827
			if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) {
13828
				$.ui.ddmanager.prepareOffsets(this, event);
13829
			}
13830
		}
13831
13832
		//Regenerate the absolute position used for position checks
13833
		this.positionAbs = this._convertPositionTo("absolute");
13834
13835
		//Set the helper position
13836
		if(!this.options.axis || this.options.axis !== "y") {
13837
			this.helper[0].style.left = this.position.left+"px";
13838
		}
13839
		if(!this.options.axis || this.options.axis !== "x") {
13840
			this.helper[0].style.top = this.position.top+"px";
13841
		}
13842
13843
		//Rearrange
13844
		for (i = this.items.length - 1; i >= 0; i--) {
13845
13846
			//Cache variables and intersection, continue if no intersection
13847
			item = this.items[i];
13848
			itemElement = item.item[0];
13849
			intersection = this._intersectsWithPointer(item);
13850
			if (!intersection) {
13851
				continue;
13852
			}
13853
13854
			// Only put the placeholder inside the current Container, skip all
13855
			// items from other containers. This works because when moving
13856
			// an item from one container to another the
13857
			// currentContainer is switched before the placeholder is moved.
13858
			//
13859
			// Without this, moving items in "sub-sortables" can cause
13860
			// the placeholder to jitter between the outer and inner container.
13861
			if (item.instance !== this.currentContainer) {
13862
				continue;
13863
			}
13864
13865
			// cannot intersect with itself
13866
			// no useless actions that have been done before
13867
			// no action if the item moved is the parent of the item checked
13868
			if (itemElement !== this.currentItem[0] &&
13869
				this.placeholder[intersection === 1 ? "next" : "prev"]()[0] !== itemElement &&
13870
				!$.contains(this.placeholder[0], itemElement) &&
13871
				(this.options.type === "semi-dynamic" ? !$.contains(this.element[0], itemElement) : true)
13872
			) {
13873
13874
				this.direction = intersection === 1 ? "down" : "up";
13875
13876
				if (this.options.tolerance === "pointer" || this._intersectsWithSides(item)) {
13877
					this._rearrange(event, item);
13878
				} else {
13879
					break;
13880
				}
13881
13882
				this._trigger("change", event, this._uiHash());
13883
				break;
13884
			}
13885
		}
13886
13887
		//Post events to containers
13888
		this._contactContainers(event);
13889
13890
		//Interconnect with droppables
13891
		if($.ui.ddmanager) {
13892
			$.ui.ddmanager.drag(this, event);
13893
		}
13894
13895
		//Call callbacks
13896
		this._trigger("sort", event, this._uiHash());
13897
13898
		this.lastPositionAbs = this.positionAbs;
13899
		return false;
13900
13901
	},
13902
13903
	_mouseStop: function(event, noPropagation) {
13904
13905
		if(!event) {
13906
			return;
13907
		}
13908
13909
		//If we are using droppables, inform the manager about the drop
13910
		if ($.ui.ddmanager && !this.options.dropBehaviour) {
13911
			$.ui.ddmanager.drop(this, event);
13912
		}
13913
13914
		if(this.options.revert) {
13915
			var that = this,
13916
				cur = this.placeholder.offset(),
13917
				axis = this.options.axis,
13918
				animation = {};
13919
13920
			if ( !axis || axis === "x" ) {
13921
				animation.left = cur.left - this.offset.parent.left - this.margins.left + (this.offsetParent[0] === this.document[0].body ? 0 : this.offsetParent[0].scrollLeft);
13922
			}
13923
			if ( !axis || axis === "y" ) {
13924
				animation.top = cur.top - this.offset.parent.top - this.margins.top + (this.offsetParent[0] === this.document[0].body ? 0 : this.offsetParent[0].scrollTop);
13925
			}
13926
			this.reverting = true;
13927
			$(this.helper).animate( animation, parseInt(this.options.revert, 10) || 500, function() {
13928
				that._clear(event);
13929
			});
13930
		} else {
13931
			this._clear(event, noPropagation);
13932
		}
13933
13934
		return false;
13935
13936
	},
13937
13938
	cancel: function() {
13939
13940
		if(this.dragging) {
13941
13942
			this._mouseUp({ target: null });
13943
13944
			if(this.options.helper === "original") {
13945
				this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
13946
			} else {
13947
				this.currentItem.show();
13948
			}
13949
13950
			//Post deactivating events to containers
13951
			for (var i = this.containers.length - 1; i >= 0; i--){
13952
				this.containers[i]._trigger("deactivate", null, this._uiHash(this));
13953
				if(this.containers[i].containerCache.over) {
13954
					this.containers[i]._trigger("out", null, this._uiHash(this));
13955
					this.containers[i].containerCache.over = 0;
13956
				}
13957
			}
13958
13959
		}
13960
13961
		if (this.placeholder) {
13962
			//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
13963
			if(this.placeholder[0].parentNode) {
13964
				this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
13965
			}
13966
			if(this.options.helper !== "original" && this.helper && this.helper[0].parentNode) {
13967
				this.helper.remove();
13968
			}
13969
13970
			$.extend(this, {
13971
				helper: null,
13972
				dragging: false,
13973
				reverting: false,
13974
				_noFinalSort: null
13975
			});
13976
13977
			if(this.domPosition.prev) {
13978
				$(this.domPosition.prev).after(this.currentItem);
13979
			} else {
13980
				$(this.domPosition.parent).prepend(this.currentItem);
13981
			}
13982
		}
13983
13984
		return this;
13985
13986
	},
13987
13988
	serialize: function(o) {
13989
13990
		var items = this._getItemsAsjQuery(o && o.connected),
13991
			str = [];
13992
		o = o || {};
13993
13994
		$(items).each(function() {
13995
			var res = ($(o.item || this).attr(o.attribute || "id") || "").match(o.expression || (/(.+)[\-=_](.+)/));
13996
			if (res) {
13997
				str.push((o.key || res[1]+"[]")+"="+(o.key && o.expression ? res[1] : res[2]));
13998
			}
13999
		});
14000
14001
		if(!str.length && o.key) {
14002
			str.push(o.key + "=");
14003
		}
14004
14005
		return str.join("&");
14006
14007
	},
14008
14009
	toArray: function(o) {
14010
14011
		var items = this._getItemsAsjQuery(o && o.connected),
14012
			ret = [];
14013
14014
		o = o || {};
14015
14016
		items.each(function() { ret.push($(o.item || this).attr(o.attribute || "id") || ""); });
14017
		return ret;
14018
14019
	},
14020
14021
	/* Be careful with the following core functions */
14022
	_intersectsWith: function(item) {
14023
14024
		var x1 = this.positionAbs.left,
14025
			x2 = x1 + this.helperProportions.width,
14026
			y1 = this.positionAbs.top,
14027
			y2 = y1 + this.helperProportions.height,
14028
			l = item.left,
14029
			r = l + item.width,
14030
			t = item.top,
14031
			b = t + item.height,
14032
			dyClick = this.offset.click.top,
14033
			dxClick = this.offset.click.left,
14034
			isOverElementHeight = ( this.options.axis === "x" ) || ( ( y1 + dyClick ) > t && ( y1 + dyClick ) < b ),
14035
			isOverElementWidth = ( this.options.axis === "y" ) || ( ( x1 + dxClick ) > l && ( x1 + dxClick ) < r ),
14036
			isOverElement = isOverElementHeight && isOverElementWidth;
14037
14038
		if ( this.options.tolerance === "pointer" ||
14039
			this.options.forcePointerForContainers ||
14040
			(this.options.tolerance !== "pointer" && this.helperProportions[this.floating ? "width" : "height"] > item[this.floating ? "width" : "height"])
14041
		) {
14042
			return isOverElement;
14043
		} else {
14044
14045
			return (l < x1 + (this.helperProportions.width / 2) && // Right Half
14046
				x2 - (this.helperProportions.width / 2) < r && // Left Half
14047
				t < y1 + (this.helperProportions.height / 2) && // Bottom Half
14048
				y2 - (this.helperProportions.height / 2) < b ); // Top Half
14049
14050
		}
14051
	},
14052
14053
	_intersectsWithPointer: function(item) {
14054
14055
		var isOverElementHeight = (this.options.axis === "x") || this._isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
14056
			isOverElementWidth = (this.options.axis === "y") || this._isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
14057
			isOverElement = isOverElementHeight && isOverElementWidth,
14058
			verticalDirection = this._getDragVerticalDirection(),
14059
			horizontalDirection = this._getDragHorizontalDirection();
14060
14061
		if (!isOverElement) {
14062
			return false;
14063
		}
14064
14065
		return this.floating ?
14066
			( ((horizontalDirection && horizontalDirection === "right") || verticalDirection === "down") ? 2 : 1 )
14067
			: ( verticalDirection && (verticalDirection === "down" ? 2 : 1) );
14068
14069
	},
14070
14071
	_intersectsWithSides: function(item) {
14072
14073
		var isOverBottomHalf = this._isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),
14074
			isOverRightHalf = this._isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
14075
			verticalDirection = this._getDragVerticalDirection(),
14076
			horizontalDirection = this._getDragHorizontalDirection();
14077
14078
		if (this.floating && horizontalDirection) {
14079
			return ((horizontalDirection === "right" && isOverRightHalf) || (horizontalDirection === "left" && !isOverRightHalf));
14080
		} else {
14081
			return verticalDirection && ((verticalDirection === "down" && isOverBottomHalf) || (verticalDirection === "up" && !isOverBottomHalf));
14082
		}
14083
14084
	},
14085
14086
	_getDragVerticalDirection: function() {
14087
		var delta = this.positionAbs.top - this.lastPositionAbs.top;
14088
		return delta !== 0 && (delta > 0 ? "down" : "up");
14089
	},
14090
14091
	_getDragHorizontalDirection: function() {
14092
		var delta = this.positionAbs.left - this.lastPositionAbs.left;
14093
		return delta !== 0 && (delta > 0 ? "right" : "left");
14094
	},
14095
14096
	refresh: function(event) {
14097
		this._refreshItems(event);
14098
		this._setHandleClassName();
14099
		this.refreshPositions();
14100
		return this;
14101
	},
14102
14103
	_connectWith: function() {
14104
		var options = this.options;
14105
		return options.connectWith.constructor === String ? [options.connectWith] : options.connectWith;
14106
	},
14107
14108
	_getItemsAsjQuery: function(connected) {
14109
14110
		var i, j, cur, inst,
14111
			items = [],
14112
			queries = [],
14113
			connectWith = this._connectWith();
14114
14115
		if(connectWith && connected) {
14116
			for (i = connectWith.length - 1; i >= 0; i--){
14117
				cur = $(connectWith[i], this.document[0]);
14118
				for ( j = cur.length - 1; j >= 0; j--){
14119
					inst = $.data(cur[j], this.widgetFullName);
14120
					if(inst && inst !== this && !inst.options.disabled) {
14121
						queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"), inst]);
14122
					}
14123
				}
14124
			}
14125
		}
14126
14127
		queries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"), this]);
14128
14129
		function addItems() {
14130
			items.push( this );
14131
		}
14132
		for (i = queries.length - 1; i >= 0; i--){
14133
			queries[i][0].each( addItems );
14134
		}
14135
14136
		return $(items);
14137
14138
	},
14139
14140
	_removeCurrentsFromItems: function() {
14141
14142
		var list = this.currentItem.find(":data(" + this.widgetName + "-item)");
14143
14144
		this.items = $.grep(this.items, function (item) {
14145
			for (var j=0; j < list.length; j++) {
14146
				if(list[j] === item.item[0]) {
14147
					return false;
14148
				}
14149
			}
14150
			return true;
14151
		});
14152
14153
	},
14154
14155
	_refreshItems: function(event) {
14156
14157
		this.items = [];
14158
		this.containers = [this];
14159
14160
		var i, j, cur, inst, targetData, _queries, item, queriesLength,
14161
			items = this.items,
14162
			queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]],
14163
			connectWith = this._connectWith();
14164
14165
		if(connectWith && this.ready) { //Shouldn't be run the first time through due to massive slow-down
14166
			for (i = connectWith.length - 1; i >= 0; i--){
14167
				cur = $(connectWith[i], this.document[0]);
14168
				for (j = cur.length - 1; j >= 0; j--){
14169
					inst = $.data(cur[j], this.widgetFullName);
14170
					if(inst && inst !== this && !inst.options.disabled) {
14171
						queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
14172
						this.containers.push(inst);
14173
					}
14174
				}
14175
			}
14176
		}
14177
14178
		for (i = queries.length - 1; i >= 0; i--) {
14179
			targetData = queries[i][1];
14180
			_queries = queries[i][0];
14181
14182
			for (j=0, queriesLength = _queries.length; j < queriesLength; j++) {
14183
				item = $(_queries[j]);
14184
14185
				item.data(this.widgetName + "-item", targetData); // Data for target checking (mouse manager)
14186
14187
				items.push({
14188
					item: item,
14189
					instance: targetData,
14190
					width: 0, height: 0,
14191
					left: 0, top: 0
14192
				});
14193
			}
14194
		}
14195
14196
	},
14197
14198
	refreshPositions: function(fast) {
14199
14200
		// Determine whether items are being displayed horizontally
14201
		this.floating = this.items.length ?
14202
			this.options.axis === "x" || this._isFloating( this.items[ 0 ].item ) :
14203
			false;
14204
14205
		//This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
14206
		if(this.offsetParent && this.helper) {
14207
			this.offset.parent = this._getParentOffset();
14208
		}
14209
14210
		var i, item, t, p;
14211
14212
		for (i = this.items.length - 1; i >= 0; i--){
14213
			item = this.items[i];
14214
14215
			//We ignore calculating positions of all connected containers when we're not over them
14216
			if(item.instance !== this.currentContainer && this.currentContainer && item.item[0] !== this.currentItem[0]) {
14217
				continue;
14218
			}
14219
14220
			t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
14221
14222
			if (!fast) {
14223
				item.width = t.outerWidth();
14224
				item.height = t.outerHeight();
14225
			}
14226
14227
			p = t.offset();
14228
			item.left = p.left;
14229
			item.top = p.top;
14230
		}
14231
14232
		if(this.options.custom && this.options.custom.refreshContainers) {
14233
			this.options.custom.refreshContainers.call(this);
14234
		} else {
14235
			for (i = this.containers.length - 1; i >= 0; i--){
14236
				p = this.containers[i].element.offset();
14237
				this.containers[i].containerCache.left = p.left;
14238
				this.containers[i].containerCache.top = p.top;
14239
				this.containers[i].containerCache.width = this.containers[i].element.outerWidth();
14240
				this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
14241
			}
14242
		}
14243
14244
		return this;
14245
	},
14246
14247
	_createPlaceholder: function(that) {
14248
		that = that || this;
14249
		var className,
14250
			o = that.options;
14251
14252
		if(!o.placeholder || o.placeholder.constructor === String) {
14253
			className = o.placeholder;
14254
			o.placeholder = {
14255
				element: function() {
14256
14257
					var nodeName = that.currentItem[0].nodeName.toLowerCase(),
14258
						element = $( "<" + nodeName + ">", that.document[0] )
14259
							.addClass(className || that.currentItem[0].className+" ui-sortable-placeholder")
14260
							.removeClass("ui-sortable-helper");
14261
14262
					if ( nodeName === "tbody" ) {
14263
						that._createTrPlaceholder(
14264
							that.currentItem.find( "tr" ).eq( 0 ),
14265
							$( "<tr>", that.document[ 0 ] ).appendTo( element )
14266
						);
14267
					} else if ( nodeName === "tr" ) {
14268
						that._createTrPlaceholder( that.currentItem, element );
14269
					} else if ( nodeName === "img" ) {
14270
						element.attr( "src", that.currentItem.attr( "src" ) );
14271
					}
14272
14273
					if ( !className ) {
14274
						element.css( "visibility", "hidden" );
14275
					}
14276
14277
					return element;
14278
				},
14279
				update: function(container, p) {
14280
14281
					// 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
14282
					// 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
14283
					if(className && !o.forcePlaceholderSize) {
14284
						return;
14285
					}
14286
14287
					//If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item
14288
					if(!p.height()) { p.height(that.currentItem.innerHeight() - parseInt(that.currentItem.css("paddingTop")||0, 10) - parseInt(that.currentItem.css("paddingBottom")||0, 10)); }
14289
					if(!p.width()) { p.width(that.currentItem.innerWidth() - parseInt(that.currentItem.css("paddingLeft")||0, 10) - parseInt(that.currentItem.css("paddingRight")||0, 10)); }
14290
				}
14291
			};
14292
		}
14293
14294
		//Create the placeholder
14295
		that.placeholder = $(o.placeholder.element.call(that.element, that.currentItem));
14296
14297
		//Append it after the actual current item
14298
		that.currentItem.after(that.placeholder);
14299
14300
		//Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
14301
		o.placeholder.update(that, that.placeholder);
14302
14303
	},
14304
14305
	_createTrPlaceholder: function( sourceTr, targetTr ) {
14306
		var that = this;
14307
14308
		sourceTr.children().each(function() {
14309
			$( "<td>&#160;</td>", that.document[ 0 ] )
14310
				.attr( "colspan", $( this ).attr( "colspan" ) || 1 )
14311
				.appendTo( targetTr );
14312
		});
14313
	},
14314
14315
	_contactContainers: function(event) {
14316
		var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, cur, nearBottom, floating, axis,
14317
			innermostContainer = null,
14318
			innermostIndex = null;
14319
14320
		// get innermost container that intersects with item
14321
		for (i = this.containers.length - 1; i >= 0; i--) {
14322
14323
			// never consider a container that's located within the item itself
14324
			if($.contains(this.currentItem[0], this.containers[i].element[0])) {
14325
				continue;
14326
			}
14327
14328
			if(this._intersectsWith(this.containers[i].containerCache)) {
14329
14330
				// if we've already found a container and it's more "inner" than this, then continue
14331
				if(innermostContainer && $.contains(this.containers[i].element[0], innermostContainer.element[0])) {
14332
					continue;
14333
				}
14334
14335
				innermostContainer = this.containers[i];
14336
				innermostIndex = i;
14337
14338
			} else {
14339
				// container doesn't intersect. trigger "out" event if necessary
14340
				if(this.containers[i].containerCache.over) {
14341
					this.containers[i]._trigger("out", event, this._uiHash(this));
14342
					this.containers[i].containerCache.over = 0;
14343
				}
14344
			}
14345
14346
		}
14347
14348
		// if no intersecting containers found, return
14349
		if(!innermostContainer) {
14350
			return;
14351
		}
14352
14353
		// move the item into the container if it's not there already
14354
		if(this.containers.length === 1) {
14355
			if (!this.containers[innermostIndex].containerCache.over) {
14356
				this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
14357
				this.containers[innermostIndex].containerCache.over = 1;
14358
			}
14359
		} else {
14360
14361
			//When entering a new container, we will find the item with the least distance and append our item near it
14362
			dist = 10000;
14363
			itemWithLeastDistance = null;
14364
			floating = innermostContainer.floating || this._isFloating(this.currentItem);
14365
			posProperty = floating ? "left" : "top";
14366
			sizeProperty = floating ? "width" : "height";
14367
			axis = floating ? "clientX" : "clientY";
14368
14369
			for (j = this.items.length - 1; j >= 0; j--) {
14370
				if(!$.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) {
14371
					continue;
14372
				}
14373
				if(this.items[j].item[0] === this.currentItem[0]) {
14374
					continue;
14375
				}
14376
14377
				cur = this.items[j].item.offset()[posProperty];
14378
				nearBottom = false;
14379
				if ( event[ axis ] - cur > this.items[ j ][ sizeProperty ] / 2 ) {
14380
					nearBottom = true;
14381
				}
14382
14383
				if ( Math.abs( event[ axis ] - cur ) < dist ) {
14384
					dist = Math.abs( event[ axis ] - cur );
14385
					itemWithLeastDistance = this.items[ j ];
14386
					this.direction = nearBottom ? "up": "down";
14387
				}
14388
			}
14389
14390
			//Check if dropOnEmpty is enabled
14391
			if(!itemWithLeastDistance && !this.options.dropOnEmpty) {
14392
				return;
14393
			}
14394
14395
			if(this.currentContainer === this.containers[innermostIndex]) {
14396
				if ( !this.currentContainer.containerCache.over ) {
14397
					this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash() );
14398
					this.currentContainer.containerCache.over = 1;
14399
				}
14400
				return;
14401
			}
14402
14403
			itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true);
14404
			this._trigger("change", event, this._uiHash());
14405
			this.containers[innermostIndex]._trigger("change", event, this._uiHash(this));
14406
			this.currentContainer = this.containers[innermostIndex];
14407
14408
			//Update the placeholder
14409
			this.options.placeholder.update(this.currentContainer, this.placeholder);
14410
14411
			this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
14412
			this.containers[innermostIndex].containerCache.over = 1;
14413
		}
14414
14415
14416
	},
14417
14418
	_createHelper: function(event) {
14419
14420
		var o = this.options,
14421
			helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper === "clone" ? this.currentItem.clone() : this.currentItem);
14422
14423
		//Add the helper to the DOM if that didn't happen already
14424
		if(!helper.parents("body").length) {
14425
			$(o.appendTo !== "parent" ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);
14426
		}
14427
14428
		if(helper[0] === this.currentItem[0]) {
14429
			this._storedCSS = { width: this.currentItem[0].style.width, height: this.currentItem[0].style.height, position: this.currentItem.css("position"), top: this.currentItem.css("top"), left: this.currentItem.css("left") };
14430
		}
14431
14432
		if(!helper[0].style.width || o.forceHelperSize) {
14433
			helper.width(this.currentItem.width());
14434
		}
14435
		if(!helper[0].style.height || o.forceHelperSize) {
14436
			helper.height(this.currentItem.height());
14437
		}
14438
14439
		return helper;
14440
14441
	},
14442
14443
	_adjustOffsetFromHelper: function(obj) {
14444
		if (typeof obj === "string") {
14445
			obj = obj.split(" ");
14446
		}
14447
		if ($.isArray(obj)) {
14448
			obj = {left: +obj[0], top: +obj[1] || 0};
14449
		}
14450
		if ("left" in obj) {
14451
			this.offset.click.left = obj.left + this.margins.left;
14452
		}
14453
		if ("right" in obj) {
14454
			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
14455
		}
14456
		if ("top" in obj) {
14457
			this.offset.click.top = obj.top + this.margins.top;
14458
		}
14459
		if ("bottom" in obj) {
14460
			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
14461
		}
14462
	},
14463
14464
	_getParentOffset: function() {
14465
14466
14467
		//Get the offsetParent and cache its position
14468
		this.offsetParent = this.helper.offsetParent();
14469
		var po = this.offsetParent.offset();
14470
14471
		// This is a special case where we need to modify a offset calculated on start, since the following happened:
14472
		// 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
14473
		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
14474
		//    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
14475
		if(this.cssPosition === "absolute" && this.scrollParent[0] !== this.document[0] && $.contains(this.scrollParent[0], this.offsetParent[0])) {
14476
			po.left += this.scrollParent.scrollLeft();
14477
			po.top += this.scrollParent.scrollTop();
14478
		}
14479
14480
		// This needs to be actually done for all browsers, since pageX/pageY includes this information
14481
		// with an ugly IE fix
14482
		if( this.offsetParent[0] === this.document[0].body || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie)) {
14483
			po = { top: 0, left: 0 };
14484
		}
14485
14486
		return {
14487
			top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
14488
			left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
14489
		};
14490
14491
	},
14492
14493
	_getRelativeOffset: function() {
14494
14495
		if(this.cssPosition === "relative") {
14496
			var p = this.currentItem.position();
14497
			return {
14498
				top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
14499
				left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
14500
			};
14501
		} else {
14502
			return { top: 0, left: 0 };
14503
		}
14504
14505
	},
14506
14507
	_cacheMargins: function() {
14508
		this.margins = {
14509
			left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),
14510
			top: (parseInt(this.currentItem.css("marginTop"),10) || 0)
14511
		};
14512
	},
14513
14514
	_cacheHelperProportions: function() {
14515
		this.helperProportions = {
14516
			width: this.helper.outerWidth(),
14517
			height: this.helper.outerHeight()
14518
		};
14519
	},
14520
14521
	_setContainment: function() {
14522
14523
		var ce, co, over,
14524
			o = this.options;
14525
		if(o.containment === "parent") {
14526
			o.containment = this.helper[0].parentNode;
14527
		}
14528
		if(o.containment === "document" || o.containment === "window") {
14529
			this.containment = [
14530
				0 - this.offset.relative.left - this.offset.parent.left,
14531
				0 - this.offset.relative.top - this.offset.parent.top,
14532
				o.containment === "document" ? this.document.width() : this.window.width() - this.helperProportions.width - this.margins.left,
14533
				(o.containment === "document" ? this.document.width() : this.window.height() || this.document[0].body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
14534
			];
14535
		}
14536
14537
		if(!(/^(document|window|parent)$/).test(o.containment)) {
14538
			ce = $(o.containment)[0];
14539
			co = $(o.containment).offset();
14540
			over = ($(ce).css("overflow") !== "hidden");
14541
14542
			this.containment = [
14543
				co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
14544
				co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
14545
				co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left,
14546
				co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top
14547
			];
14548
		}
14549
14550
	},
14551
14552
	_convertPositionTo: function(d, pos) {
14553
14554
		if(!pos) {
14555
			pos = this.position;
14556
		}
14557
		var mod = d === "absolute" ? 1 : -1,
14558
			scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== this.document[0] && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent,
14559
			scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
14560
14561
		return {
14562
			top: (
14563
				pos.top	+																// The absolute mouse position
14564
				this.offset.relative.top * mod +										// Only for relative positioned nodes: Relative offset from element to offset parent
14565
				this.offset.parent.top * mod -											// The offsetParent's offset without borders (offset + border)
14566
				( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
14567
			),
14568
			left: (
14569
				pos.left +																// The absolute mouse position
14570
				this.offset.relative.left * mod +										// Only for relative positioned nodes: Relative offset from element to offset parent
14571
				this.offset.parent.left * mod	-										// The offsetParent's offset without borders (offset + border)
14572
				( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
14573
			)
14574
		};
14575
14576
	},
14577
14578
	_generatePosition: function(event) {
14579
14580
		var top, left,
14581
			o = this.options,
14582
			pageX = event.pageX,
14583
			pageY = event.pageY,
14584
			scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== this.document[0] && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
14585
14586
		// This is another very weird special case that only happens for relative elements:
14587
		// 1. If the css position is relative
14588
		// 2. and the scroll parent is the document or similar to the offset parent
14589
		// we have to refresh the relative offset during the scroll so there are no jumps
14590
		if(this.cssPosition === "relative" && !(this.scrollParent[0] !== this.document[0] && this.scrollParent[0] !== this.offsetParent[0])) {
14591
			this.offset.relative = this._getRelativeOffset();
14592
		}
14593
14594
		/*
14595
		 * - Position constraining -
14596
		 * Constrain the position to a mix of grid, containment.
14597
		 */
14598
14599
		if(this.originalPosition) { //If we are not dragging yet, we won't check for options
14600
14601
			if(this.containment) {
14602
				if(event.pageX - this.offset.click.left < this.containment[0]) {
14603
					pageX = this.containment[0] + this.offset.click.left;
14604
				}
14605
				if(event.pageY - this.offset.click.top < this.containment[1]) {
14606
					pageY = this.containment[1] + this.offset.click.top;
14607
				}
14608
				if(event.pageX - this.offset.click.left > this.containment[2]) {
14609
					pageX = this.containment[2] + this.offset.click.left;
14610
				}
14611
				if(event.pageY - this.offset.click.top > this.containment[3]) {
14612
					pageY = this.containment[3] + this.offset.click.top;
14613
				}
14614
			}
14615
14616
			if(o.grid) {
14617
				top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
14618
				pageY = this.containment ? ( (top - this.offset.click.top >= this.containment[1] && top - this.offset.click.top <= this.containment[3]) ? top : ((top - this.offset.click.top >= this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
14619
14620
				left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
14621
				pageX = this.containment ? ( (left - this.offset.click.left >= this.containment[0] && left - this.offset.click.left <= this.containment[2]) ? left : ((left - this.offset.click.left >= this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
14622
			}
14623
14624
		}
14625
14626
		return {
14627
			top: (
14628
				pageY -																// The absolute mouse position
14629
				this.offset.click.top -													// Click offset (relative to the element)
14630
				this.offset.relative.top	-											// Only for relative positioned nodes: Relative offset from element to offset parent
14631
				this.offset.parent.top +												// The offsetParent's offset without borders (offset + border)
14632
				( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
14633
			),
14634
			left: (
14635
				pageX -																// The absolute mouse position
14636
				this.offset.click.left -												// Click offset (relative to the element)
14637
				this.offset.relative.left	-											// Only for relative positioned nodes: Relative offset from element to offset parent
14638
				this.offset.parent.left +												// The offsetParent's offset without borders (offset + border)
14639
				( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
14640
			)
14641
		};
14642
14643
	},
14644
14645
	_rearrange: function(event, i, a, hardRefresh) {
14646
14647
		a ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction === "down" ? i.item[0] : i.item[0].nextSibling));
14648
14649
		//Various things done here to improve the performance:
14650
		// 1. we create a setTimeout, that calls refreshPositions
14651
		// 2. on the instance, we have a counter variable, that get's higher after every append
14652
		// 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
14653
		// 4. this lets only the last addition to the timeout stack through
14654
		this.counter = this.counter ? ++this.counter : 1;
14655
		var counter = this.counter;
14656
14657
		this._delay(function() {
14658
			if(counter === this.counter) {
14659
				this.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
14660
			}
14661
		});
14662
14663
	},
14664
14665
	_clear: function(event, noPropagation) {
14666
14667
		this.reverting = false;
14668
		// We delay all events that have to be triggered to after the point where the placeholder has been removed and
14669
		// everything else normalized again
14670
		var i,
14671
			delayedTriggers = [];
14672
14673
		// We first have to update the dom position of the actual currentItem
14674
		// Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
14675
		if(!this._noFinalSort && this.currentItem.parent().length) {
14676
			this.placeholder.before(this.currentItem);
14677
		}
14678
		this._noFinalSort = null;
14679
14680
		if(this.helper[0] === this.currentItem[0]) {
14681
			for(i in this._storedCSS) {
14682
				if(this._storedCSS[i] === "auto" || this._storedCSS[i] === "static") {
14683
					this._storedCSS[i] = "";
14684
				}
14685
			}
14686
			this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
14687
		} else {
14688
			this.currentItem.show();
14689
		}
14690
14691
		if(this.fromOutside && !noPropagation) {
14692
			delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });
14693
		}
14694
		if((this.fromOutside || this.domPosition.prev !== this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent !== this.currentItem.parent()[0]) && !noPropagation) {
14695
			delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed
14696
		}
14697
14698
		// Check if the items Container has Changed and trigger appropriate
14699
		// events.
14700
		if (this !== this.currentContainer) {
14701
			if(!noPropagation) {
14702
				delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
14703
				delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); };  }).call(this, this.currentContainer));
14704
				delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this));  }; }).call(this, this.currentContainer));
14705
			}
14706
		}
14707
14708
14709
		//Post events to containers
14710
		function delayEvent( type, instance, container ) {
14711
			return function( event ) {
14712
				container._trigger( type, event, instance._uiHash( instance ) );
14713
			};
14714
		}
14715
		for (i = this.containers.length - 1; i >= 0; i--){
14716
			if (!noPropagation) {
14717
				delayedTriggers.push( delayEvent( "deactivate", this, this.containers[ i ] ) );
14718
			}
14719
			if(this.containers[i].containerCache.over) {
14720
				delayedTriggers.push( delayEvent( "out", this, this.containers[ i ] ) );
14721
				this.containers[i].containerCache.over = 0;
14722
			}
14723
		}
14724
14725
		//Do what was originally in plugins
14726
		if ( this.storedCursor ) {
14727
			this.document.find( "body" ).css( "cursor", this.storedCursor );
14728
			this.storedStylesheet.remove();
14729
		}
14730
		if(this._storedOpacity) {
14731
			this.helper.css("opacity", this._storedOpacity);
14732
		}
14733
		if(this._storedZIndex) {
14734
			this.helper.css("zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex);
14735
		}
14736
14737
		this.dragging = false;
14738
14739
		if(!noPropagation) {
14740
			this._trigger("beforeStop", event, this._uiHash());
14741
		}
14742
14743
		//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
14744
		this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
14745
14746
		if ( !this.cancelHelperRemoval ) {
14747
			if ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) {
14748
				this.helper.remove();
14749
			}
14750
			this.helper = null;
14751
		}
14752
14753
		if(!noPropagation) {
14754
			for (i=0; i < delayedTriggers.length; i++) {
14755
				delayedTriggers[i].call(this, event);
14756
			} //Trigger all delayed events
14757
			this._trigger("stop", event, this._uiHash());
14758
		}
14759
14760
		this.fromOutside = false;
14761
		return !this.cancelHelperRemoval;
14762
14763
	},
14764
14765
	_trigger: function() {
14766
		if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
14767
			this.cancel();
14768
		}
14769
	},
14770
14771
	_uiHash: function(_inst) {
14772
		var inst = _inst || this;
14773
		return {
14774
			helper: inst.helper,
14775
			placeholder: inst.placeholder || $([]),
14776
			position: inst.position,
14777
			originalPosition: inst.originalPosition,
14778
			offset: inst.positionAbs,
14779
			item: inst.currentItem,
14780
			sender: _inst ? _inst.element : null
14781
		};
14782
	}
14783
14784
});
14785
14786
14787
/*!
14788
 * jQuery UI Spinner 1.11.4
14789
 * http://jqueryui.com
14790
 *
14791
 * Copyright jQuery Foundation and other contributors
14792
 * Released under the MIT license.
14793
 * http://jquery.org/license
14794
 *
14795
 * http://api.jqueryui.com/spinner/
14796
 */
14797
14798
14799
function spinner_modifier( fn ) {
14800
	return function() {
14801
		var previous = this.element.val();
14802
		fn.apply( this, arguments );
14803
		this._refresh();
14804
		if ( previous !== this.element.val() ) {
14805
			this._trigger( "change" );
14806
		}
14807
	};
14808
}
14809
14810
var spinner = $.widget( "ui.spinner", {
14811
	version: "1.11.4",
14812
	defaultElement: "<input>",
14813
	widgetEventPrefix: "spin",
14814
	options: {
14815
		culture: null,
14816
		icons: {
14817
			down: "ui-icon-triangle-1-s",
14818
			up: "ui-icon-triangle-1-n"
14819
		},
14820
		incremental: true,
14821
		max: null,
14822
		min: null,
14823
		numberFormat: null,
14824
		page: 10,
14825
		step: 1,
14826
14827
		change: null,
14828
		spin: null,
14829
		start: null,
14830
		stop: null
14831
	},
14832
14833
	_create: function() {
14834
		// handle string values that need to be parsed
14835
		this._setOption( "max", this.options.max );
14836
		this._setOption( "min", this.options.min );
14837
		this._setOption( "step", this.options.step );
14838
14839
		// Only format if there is a value, prevents the field from being marked
14840
		// as invalid in Firefox, see #9573.
14841
		if ( this.value() !== "" ) {
14842
			// Format the value, but don't constrain.
14843
			this._value( this.element.val(), true );
14844
		}
14845
14846
		this._draw();
14847
		this._on( this._events );
14848
		this._refresh();
14849
14850
		// turning off autocomplete prevents the browser from remembering the
14851
		// value when navigating through history, so we re-enable autocomplete
14852
		// if the page is unloaded before the widget is destroyed. #7790
14853
		this._on( this.window, {
14854
			beforeunload: function() {
14855
				this.element.removeAttr( "autocomplete" );
14856
			}
14857
		});
14858
	},
14859
14860
	_getCreateOptions: function() {
14861
		var options = {},
14862
			element = this.element;
14863
14864
		$.each( [ "min", "max", "step" ], function( i, option ) {
14865
			var value = element.attr( option );
14866
			if ( value !== undefined && value.length ) {
14867
				options[ option ] = value;
14868
			}
14869
		});
14870
14871
		return options;
14872
	},
14873
14874
	_events: {
14875
		keydown: function( event ) {
14876
			if ( this._start( event ) && this._keydown( event ) ) {
14877
				event.preventDefault();
14878
			}
14879
		},
14880
		keyup: "_stop",
14881
		focus: function() {
14882
			this.previous = this.element.val();
14883
		},
14884
		blur: function( event ) {
14885
			if ( this.cancelBlur ) {
14886
				delete this.cancelBlur;
14887
				return;
14888
			}
14889
14890
			this._stop();
14891
			this._refresh();
14892
			if ( this.previous !== this.element.val() ) {
14893
				this._trigger( "change", event );
14894
			}
14895
		},
14896
		mousewheel: function( event, delta ) {
14897
			if ( !delta ) {
14898
				return;
14899
			}
14900
			if ( !this.spinning && !this._start( event ) ) {
14901
				return false;
14902
			}
14903
14904
			this._spin( (delta > 0 ? 1 : -1) * this.options.step, event );
14905
			clearTimeout( this.mousewheelTimer );
14906
			this.mousewheelTimer = this._delay(function() {
14907
				if ( this.spinning ) {
14908
					this._stop( event );
14909
				}
14910
			}, 100 );
14911
			event.preventDefault();
14912
		},
14913
		"mousedown .ui-spinner-button": function( event ) {
14914
			var previous;
14915
14916
			// We never want the buttons to have focus; whenever the user is
14917
			// interacting with the spinner, the focus should be on the input.
14918
			// If the input is focused then this.previous is properly set from
14919
			// when the input first received focus. If the input is not focused
14920
			// then we need to set this.previous based on the value before spinning.
14921
			previous = this.element[0] === this.document[0].activeElement ?
14922
				this.previous : this.element.val();
14923
			function checkFocus() {
14924
				var isActive = this.element[0] === this.document[0].activeElement;
14925
				if ( !isActive ) {
14926
					this.element.focus();
14927
					this.previous = previous;
14928
					// support: IE
14929
					// IE sets focus asynchronously, so we need to check if focus
14930
					// moved off of the input because the user clicked on the button.
14931
					this._delay(function() {
14932
						this.previous = previous;
14933
					});
14934
				}
14935
			}
14936
14937
			// ensure focus is on (or stays on) the text field
14938
			event.preventDefault();
14939
			checkFocus.call( this );
14940
14941
			// support: IE
14942
			// IE doesn't prevent moving focus even with event.preventDefault()
14943
			// so we set a flag to know when we should ignore the blur event
14944
			// and check (again) if focus moved off of the input.
14945
			this.cancelBlur = true;
14946
			this._delay(function() {
14947
				delete this.cancelBlur;
14948
				checkFocus.call( this );
14949
			});
14950
14951
			if ( this._start( event ) === false ) {
14952
				return;
14953
			}
14954
14955
			this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event );
14956
		},
14957
		"mouseup .ui-spinner-button": "_stop",
14958
		"mouseenter .ui-spinner-button": function( event ) {
14959
			// button will add ui-state-active if mouse was down while mouseleave and kept down
14960
			if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) {
14961
				return;
14962
			}
14963
14964
			if ( this._start( event ) === false ) {
14965
				return false;
14966
			}
14967
			this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event );
14968
		},
14969
		// TODO: do we really want to consider this a stop?
14970
		// shouldn't we just stop the repeater and wait until mouseup before
14971
		// we trigger the stop event?
14972
		"mouseleave .ui-spinner-button": "_stop"
14973
	},
14974
14975
	_draw: function() {
14976
		var uiSpinner = this.uiSpinner = this.element
14977
			.addClass( "ui-spinner-input" )
14978
			.attr( "autocomplete", "off" )
14979
			.wrap( this._uiSpinnerHtml() )
14980
			.parent()
14981
				// add buttons
14982
				.append( this._buttonHtml() );
14983
14984
		this.element.attr( "role", "spinbutton" );
14985
14986
		// button bindings
14987
		this.buttons = uiSpinner.find( ".ui-spinner-button" )
14988
			.attr( "tabIndex", -1 )
14989
			.button()
14990
			.removeClass( "ui-corner-all" );
14991
14992
		// IE 6 doesn't understand height: 50% for the buttons
14993
		// unless the wrapper has an explicit height
14994
		if ( this.buttons.height() > Math.ceil( uiSpinner.height() * 0.5 ) &&
14995
				uiSpinner.height() > 0 ) {
14996
			uiSpinner.height( uiSpinner.height() );
14997
		}
14998
14999
		// disable spinner if element was already disabled
15000
		if ( this.options.disabled ) {
15001
			this.disable();
15002
		}
15003
	},
15004
15005
	_keydown: function( event ) {
15006
		var options = this.options,
15007
			keyCode = $.ui.keyCode;
15008
15009
		switch ( event.keyCode ) {
15010
		case keyCode.UP:
15011
			this._repeat( null, 1, event );
15012
			return true;
15013
		case keyCode.DOWN:
15014
			this._repeat( null, -1, event );
15015
			return true;
15016
		case keyCode.PAGE_UP:
15017
			this._repeat( null, options.page, event );
15018
			return true;
15019
		case keyCode.PAGE_DOWN:
15020
			this._repeat( null, -options.page, event );
15021
			return true;
15022
		}
15023
15024
		return false;
15025
	},
15026
15027
	_uiSpinnerHtml: function() {
15028
		return "<span class='ui-spinner ui-widget ui-widget-content ui-corner-all'></span>";
15029
	},
15030
15031
	_buttonHtml: function() {
15032
		return "" +
15033
			"<a class='ui-spinner-button ui-spinner-up ui-corner-tr'>" +
15034
				"<span class='ui-icon " + this.options.icons.up + "'>&#9650;</span>" +
15035
			"</a>" +
15036
			"<a class='ui-spinner-button ui-spinner-down ui-corner-br'>" +
15037
				"<span class='ui-icon " + this.options.icons.down + "'>&#9660;</span>" +
15038
			"</a>";
15039
	},
15040
15041
	_start: function( event ) {
15042
		if ( !this.spinning && this._trigger( "start", event ) === false ) {
15043
			return false;
15044
		}
15045
15046
		if ( !this.counter ) {
15047
			this.counter = 1;
15048
		}
15049
		this.spinning = true;
15050
		return true;
15051
	},
15052
15053
	_repeat: function( i, steps, event ) {
15054
		i = i || 500;
15055
15056
		clearTimeout( this.timer );
15057
		this.timer = this._delay(function() {
15058
			this._repeat( 40, steps, event );
15059
		}, i );
15060
15061
		this._spin( steps * this.options.step, event );
15062
	},
15063
15064
	_spin: function( step, event ) {
15065
		var value = this.value() || 0;
15066
15067
		if ( !this.counter ) {
15068
			this.counter = 1;
15069
		}
15070
15071
		value = this._adjustValue( value + step * this._increment( this.counter ) );
15072
15073
		if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false) {
15074
			this._value( value );
15075
			this.counter++;
15076
		}
15077
	},
15078
15079
	_increment: function( i ) {
15080
		var incremental = this.options.incremental;
15081
15082
		if ( incremental ) {
15083
			return $.isFunction( incremental ) ?
15084
				incremental( i ) :
15085
				Math.floor( i * i * i / 50000 - i * i / 500 + 17 * i / 200 + 1 );
15086
		}
15087
15088
		return 1;
15089
	},
15090
15091
	_precision: function() {
15092
		var precision = this._precisionOf( this.options.step );
15093
		if ( this.options.min !== null ) {
15094
			precision = Math.max( precision, this._precisionOf( this.options.min ) );
15095
		}
15096
		return precision;
15097
	},
15098
15099
	_precisionOf: function( num ) {
15100
		var str = num.toString(),
15101
			decimal = str.indexOf( "." );
15102
		return decimal === -1 ? 0 : str.length - decimal - 1;
15103
	},
15104
15105
	_adjustValue: function( value ) {
15106
		var base, aboveMin,
15107
			options = this.options;
15108
15109
		// make sure we're at a valid step
15110
		// - find out where we are relative to the base (min or 0)
15111
		base = options.min !== null ? options.min : 0;
15112
		aboveMin = value - base;
15113
		// - round to the nearest step
15114
		aboveMin = Math.round(aboveMin / options.step) * options.step;
15115
		// - rounding is based on 0, so adjust back to our base
15116
		value = base + aboveMin;
15117
15118
		// fix precision from bad JS floating point math
15119
		value = parseFloat( value.toFixed( this._precision() ) );
15120
15121
		// clamp the value
15122
		if ( options.max !== null && value > options.max) {
15123
			return options.max;
15124
		}
15125
		if ( options.min !== null && value < options.min ) {
15126
			return options.min;
15127
		}
15128
15129
		return value;
15130
	},
15131
15132
	_stop: function( event ) {
15133
		if ( !this.spinning ) {
15134
			return;
15135
		}
15136
15137
		clearTimeout( this.timer );
15138
		clearTimeout( this.mousewheelTimer );
15139
		this.counter = 0;
15140
		this.spinning = false;
15141
		this._trigger( "stop", event );
15142
	},
15143
15144
	_setOption: function( key, value ) {
15145
		if ( key === "culture" || key === "numberFormat" ) {
15146
			var prevValue = this._parse( this.element.val() );
15147
			this.options[ key ] = value;
15148
			this.element.val( this._format( prevValue ) );
15149
			return;
15150
		}
15151
15152
		if ( key === "max" || key === "min" || key === "step" ) {
15153
			if ( typeof value === "string" ) {
15154
				value = this._parse( value );
15155
			}
15156
		}
15157
		if ( key === "icons" ) {
15158
			this.buttons.first().find( ".ui-icon" )
15159
				.removeClass( this.options.icons.up )
15160
				.addClass( value.up );
15161
			this.buttons.last().find( ".ui-icon" )
15162
				.removeClass( this.options.icons.down )
15163
				.addClass( value.down );
15164
		}
15165
15166
		this._super( key, value );
15167
15168
		if ( key === "disabled" ) {
15169
			this.widget().toggleClass( "ui-state-disabled", !!value );
15170
			this.element.prop( "disabled", !!value );
15171
			this.buttons.button( value ? "disable" : "enable" );
15172
		}
15173
	},
15174
15175
	_setOptions: spinner_modifier(function( options ) {
15176
		this._super( options );
15177
	}),
15178
15179
	_parse: function( val ) {
15180
		if ( typeof val === "string" && val !== "" ) {
15181
			val = window.Globalize && this.options.numberFormat ?
15182
				Globalize.parseFloat( val, 10, this.options.culture ) : +val;
15183
		}
15184
		return val === "" || isNaN( val ) ? null : val;
15185
	},
15186
15187
	_format: function( value ) {
15188
		if ( value === "" ) {
15189
			return "";
15190
		}
15191
		return window.Globalize && this.options.numberFormat ?
15192
			Globalize.format( value, this.options.numberFormat, this.options.culture ) :
15193
			value;
15194
	},
15195
15196
	_refresh: function() {
15197
		this.element.attr({
15198
			"aria-valuemin": this.options.min,
15199
			"aria-valuemax": this.options.max,
15200
			// TODO: what should we do with values that can't be parsed?
15201
			"aria-valuenow": this._parse( this.element.val() )
15202
		});
15203
	},
15204
15205
	isValid: function() {
15206
		var value = this.value();
15207
15208
		// null is invalid
15209
		if ( value === null ) {
15210
			return false;
15211
		}
15212
15213
		// if value gets adjusted, it's invalid
15214
		return value === this._adjustValue( value );
15215
	},
15216
15217
	// update the value without triggering change
15218
	_value: function( value, allowAny ) {
15219
		var parsed;
15220
		if ( value !== "" ) {
15221
			parsed = this._parse( value );
15222
			if ( parsed !== null ) {
15223
				if ( !allowAny ) {
15224
					parsed = this._adjustValue( parsed );
15225
				}
15226
				value = this._format( parsed );
15227
			}
15228
		}
15229
		this.element.val( value );
15230
		this._refresh();
15231
	},
15232
15233
	_destroy: function() {
15234
		this.element
15235
			.removeClass( "ui-spinner-input" )
15236
			.prop( "disabled", false )
15237
			.removeAttr( "autocomplete" )
15238
			.removeAttr( "role" )
15239
			.removeAttr( "aria-valuemin" )
15240
			.removeAttr( "aria-valuemax" )
15241
			.removeAttr( "aria-valuenow" );
15242
		this.uiSpinner.replaceWith( this.element );
15243
	},
15244
15245
	stepUp: spinner_modifier(function( steps ) {
15246
		this._stepUp( steps );
15247
	}),
15248
	_stepUp: function( steps ) {
15249
		if ( this._start() ) {
15250
			this._spin( (steps || 1) * this.options.step );
15251
			this._stop();
15252
		}
15253
	},
15254
15255
	stepDown: spinner_modifier(function( steps ) {
15256
		this._stepDown( steps );
15257
	}),
15258
	_stepDown: function( steps ) {
15259
		if ( this._start() ) {
15260
			this._spin( (steps || 1) * -this.options.step );
15261
			this._stop();
15262
		}
15263
	},
15264
15265
	pageUp: spinner_modifier(function( pages ) {
15266
		this._stepUp( (pages || 1) * this.options.page );
15267
	}),
15268
15269
	pageDown: spinner_modifier(function( pages ) {
15270
		this._stepDown( (pages || 1) * this.options.page );
15271
	}),
15272
15273
	value: function( newVal ) {
15274
		if ( !arguments.length ) {
15275
			return this._parse( this.element.val() );
15276
		}
15277
		spinner_modifier( this._value ).call( this, newVal );
15278
	},
15279
15280
	widget: function() {
15281
		return this.uiSpinner;
15282
	}
15283
});
15284
15285
15286
/*!
15287
 * jQuery UI Tabs 1.11.4
15288
 * http://jqueryui.com
15289
 *
15290
 * Copyright jQuery Foundation and other contributors
15291
 * Released under the MIT license.
15292
 * http://jquery.org/license
15293
 *
15294
 * http://api.jqueryui.com/tabs/
15295
 */
15296
15297
15298
var tabs = $.widget( "ui.tabs", {
15299
	version: "1.11.4",
15300
	delay: 300,
15301
	options: {
15302
		active: null,
15303
		collapsible: false,
15304
		event: "click",
15305
		heightStyle: "content",
15306
		hide: null,
15307
		show: null,
15308
15309
		// callbacks
15310
		activate: null,
15311
		beforeActivate: null,
15312
		beforeLoad: null,
15313
		load: null
15314
	},
15315
15316
	_isLocal: (function() {
15317
		var rhash = /#.*$/;
15318
15319
		return function( anchor ) {
15320
			var anchorUrl, locationUrl;
15321
15322
			// support: IE7
15323
			// IE7 doesn't normalize the href property when set via script (#9317)
15324
			anchor = anchor.cloneNode( false );
15325
15326
			anchorUrl = anchor.href.replace( rhash, "" );
15327
			locationUrl = location.href.replace( rhash, "" );
15328
15329
			// decoding may throw an error if the URL isn't UTF-8 (#9518)
15330
			try {
15331
				anchorUrl = decodeURIComponent( anchorUrl );
15332
			} catch ( error ) {}
15333
			try {
15334
				locationUrl = decodeURIComponent( locationUrl );
15335
			} catch ( error ) {}
15336
15337
			return anchor.hash.length > 1 && anchorUrl === locationUrl;
15338
		};
15339
	})(),
15340
15341
	_create: function() {
15342
		var that = this,
15343
			options = this.options;
15344
15345
		this.running = false;
15346
15347
		this.element
15348
			.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" )
15349
			.toggleClass( "ui-tabs-collapsible", options.collapsible );
15350
15351
		this._processTabs();
15352
		options.active = this._initialActive();
15353
15354
		// Take disabling tabs via class attribute from HTML
15355
		// into account and update option properly.
15356
		if ( $.isArray( options.disabled ) ) {
15357
			options.disabled = $.unique( options.disabled.concat(
15358
				$.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) {
15359
					return that.tabs.index( li );
15360
				})
15361
			) ).sort();
15362
		}
15363
15364
		// check for length avoids error when initializing empty list
15365
		if ( this.options.active !== false && this.anchors.length ) {
15366
			this.active = this._findActive( options.active );
15367
		} else {
15368
			this.active = $();
15369
		}
15370
15371
		this._refresh();
15372
15373
		if ( this.active.length ) {
15374
			this.load( options.active );
15375
		}
15376
	},
15377
15378
	_initialActive: function() {
15379
		var active = this.options.active,
15380
			collapsible = this.options.collapsible,
15381
			locationHash = location.hash.substring( 1 );
15382
15383
		if ( active === null ) {
15384
			// check the fragment identifier in the URL
15385
			if ( locationHash ) {
15386
				this.tabs.each(function( i, tab ) {
15387
					if ( $( tab ).attr( "aria-controls" ) === locationHash ) {
15388
						active = i;
15389
						return false;
15390
					}
15391
				});
15392
			}
15393
15394
			// check for a tab marked active via a class
15395
			if ( active === null ) {
15396
				active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) );
15397
			}
15398
15399
			// no active tab, set to false
15400
			if ( active === null || active === -1 ) {
15401
				active = this.tabs.length ? 0 : false;
15402
			}
15403
		}
15404
15405
		// handle numbers: negative, out of range
15406
		if ( active !== false ) {
15407
			active = this.tabs.index( this.tabs.eq( active ) );
15408
			if ( active === -1 ) {
15409
				active = collapsible ? false : 0;
15410
			}
15411
		}
15412
15413
		// don't allow collapsible: false and active: false
15414
		if ( !collapsible && active === false && this.anchors.length ) {
15415
			active = 0;
15416
		}
15417
15418
		return active;
15419
	},
15420
15421
	_getCreateEventData: function() {
15422
		return {
15423
			tab: this.active,
15424
			panel: !this.active.length ? $() : this._getPanelForTab( this.active )
15425
		};
15426
	},
15427
15428
	_tabKeydown: function( event ) {
15429
		var focusedTab = $( this.document[0].activeElement ).closest( "li" ),
15430
			selectedIndex = this.tabs.index( focusedTab ),
15431
			goingForward = true;
15432
15433
		if ( this._handlePageNav( event ) ) {
15434
			return;
15435
		}
15436
15437
		switch ( event.keyCode ) {
15438
			case $.ui.keyCode.RIGHT:
15439
			case $.ui.keyCode.DOWN:
15440
				selectedIndex++;
15441
				break;
15442
			case $.ui.keyCode.UP:
15443
			case $.ui.keyCode.LEFT:
15444
				goingForward = false;
15445
				selectedIndex--;
15446
				break;
15447
			case $.ui.keyCode.END:
15448
				selectedIndex = this.anchors.length - 1;
15449
				break;
15450
			case $.ui.keyCode.HOME:
15451
				selectedIndex = 0;
15452
				break;
15453
			case $.ui.keyCode.SPACE:
15454
				// Activate only, no collapsing
15455
				event.preventDefault();
15456
				clearTimeout( this.activating );
15457
				this._activate( selectedIndex );
15458
				return;
15459
			case $.ui.keyCode.ENTER:
15460
				// Toggle (cancel delayed activation, allow collapsing)
15461
				event.preventDefault();
15462
				clearTimeout( this.activating );
15463
				// Determine if we should collapse or activate
15464
				this._activate( selectedIndex === this.options.active ? false : selectedIndex );
15465
				return;
15466
			default:
15467
				return;
15468
		}
15469
15470
		// Focus the appropriate tab, based on which key was pressed
15471
		event.preventDefault();
15472
		clearTimeout( this.activating );
15473
		selectedIndex = this._focusNextTab( selectedIndex, goingForward );
15474
15475
		// Navigating with control/command key will prevent automatic activation
15476
		if ( !event.ctrlKey && !event.metaKey ) {
15477
15478
			// Update aria-selected immediately so that AT think the tab is already selected.
15479
			// Otherwise AT may confuse the user by stating that they need to activate the tab,
15480
			// but the tab will already be activated by the time the announcement finishes.
15481
			focusedTab.attr( "aria-selected", "false" );
15482
			this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" );
15483
15484
			this.activating = this._delay(function() {
15485
				this.option( "active", selectedIndex );
15486
			}, this.delay );
15487
		}
15488
	},
15489
15490
	_panelKeydown: function( event ) {
15491
		if ( this._handlePageNav( event ) ) {
15492
			return;
15493
		}
15494
15495
		// Ctrl+up moves focus to the current tab
15496
		if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) {
15497
			event.preventDefault();
15498
			this.active.focus();
15499
		}
15500
	},
15501
15502
	// Alt+page up/down moves focus to the previous/next tab (and activates)
15503
	_handlePageNav: function( event ) {
15504
		if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) {
15505
			this._activate( this._focusNextTab( this.options.active - 1, false ) );
15506
			return true;
15507
		}
15508
		if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) {
15509
			this._activate( this._focusNextTab( this.options.active + 1, true ) );
15510
			return true;
15511
		}
15512
	},
15513
15514
	_findNextTab: function( index, goingForward ) {
15515
		var lastTabIndex = this.tabs.length - 1;
15516
15517
		function constrain() {
15518
			if ( index > lastTabIndex ) {
15519
				index = 0;
15520
			}
15521
			if ( index < 0 ) {
15522
				index = lastTabIndex;
15523
			}
15524
			return index;
15525
		}
15526
15527
		while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) {
15528
			index = goingForward ? index + 1 : index - 1;
15529
		}
15530
15531
		return index;
15532
	},
15533
15534
	_focusNextTab: function( index, goingForward ) {
15535
		index = this._findNextTab( index, goingForward );
15536
		this.tabs.eq( index ).focus();
15537
		return index;
15538
	},
15539
15540
	_setOption: function( key, value ) {
15541
		if ( key === "active" ) {
15542
			// _activate() will handle invalid values and update this.options
15543
			this._activate( value );
15544
			return;
15545
		}
15546
15547
		if ( key === "disabled" ) {
15548
			// don't use the widget factory's disabled handling
15549
			this._setupDisabled( value );
15550
			return;
15551
		}
15552
15553
		this._super( key, value);
15554
15555
		if ( key === "collapsible" ) {
15556
			this.element.toggleClass( "ui-tabs-collapsible", value );
15557
			// Setting collapsible: false while collapsed; open first panel
15558
			if ( !value && this.options.active === false ) {
15559
				this._activate( 0 );
15560
			}
15561
		}
15562
15563
		if ( key === "event" ) {
15564
			this._setupEvents( value );
15565
		}
15566
15567
		if ( key === "heightStyle" ) {
15568
			this._setupHeightStyle( value );
15569
		}
15570
	},
15571
15572
	_sanitizeSelector: function( hash ) {
15573
		return hash ? hash.replace( /[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&" ) : "";
15574
	},
15575
15576
	refresh: function() {
15577
		var options = this.options,
15578
			lis = this.tablist.children( ":has(a[href])" );
15579
15580
		// get disabled tabs from class attribute from HTML
15581
		// this will get converted to a boolean if needed in _refresh()
15582
		options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) {
15583
			return lis.index( tab );
15584
		});
15585
15586
		this._processTabs();
15587
15588
		// was collapsed or no tabs
15589
		if ( options.active === false || !this.anchors.length ) {
15590
			options.active = false;
15591
			this.active = $();
15592
		// was active, but active tab is gone
15593
		} else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) {
15594
			// all remaining tabs are disabled
15595
			if ( this.tabs.length === options.disabled.length ) {
15596
				options.active = false;
15597
				this.active = $();
15598
			// activate previous tab
15599
			} else {
15600
				this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) );
15601
			}
15602
		// was active, active tab still exists
15603
		} else {
15604
			// make sure active index is correct
15605
			options.active = this.tabs.index( this.active );
15606
		}
15607
15608
		this._refresh();
15609
	},
15610
15611
	_refresh: function() {
15612
		this._setupDisabled( this.options.disabled );
15613
		this._setupEvents( this.options.event );
15614
		this._setupHeightStyle( this.options.heightStyle );
15615
15616
		this.tabs.not( this.active ).attr({
15617
			"aria-selected": "false",
15618
			"aria-expanded": "false",
15619
			tabIndex: -1
15620
		});
15621
		this.panels.not( this._getPanelForTab( this.active ) )
15622
			.hide()
15623
			.attr({
15624
				"aria-hidden": "true"
15625
			});
15626
15627
		// Make sure one tab is in the tab order
15628
		if ( !this.active.length ) {
15629
			this.tabs.eq( 0 ).attr( "tabIndex", 0 );
15630
		} else {
15631
			this.active
15632
				.addClass( "ui-tabs-active ui-state-active" )
15633
				.attr({
15634
					"aria-selected": "true",
15635
					"aria-expanded": "true",
15636
					tabIndex: 0
15637
				});
15638
			this._getPanelForTab( this.active )
15639
				.show()
15640
				.attr({
15641
					"aria-hidden": "false"
15642
				});
15643
		}
15644
	},
15645
15646
	_processTabs: function() {
15647
		var that = this,
15648
			prevTabs = this.tabs,
15649
			prevAnchors = this.anchors,
15650
			prevPanels = this.panels;
15651
15652
		this.tablist = this._getList()
15653
			.addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" )
15654
			.attr( "role", "tablist" )
15655
15656
			// Prevent users from focusing disabled tabs via click
15657
			.delegate( "> li", "mousedown" + this.eventNamespace, function( event ) {
15658
				if ( $( this ).is( ".ui-state-disabled" ) ) {
15659
					event.preventDefault();
15660
				}
15661
			})
15662
15663
			// support: IE <9
15664
			// Preventing the default action in mousedown doesn't prevent IE
15665
			// from focusing the element, so if the anchor gets focused, blur.
15666
			// We don't have to worry about focusing the previously focused
15667
			// element since clicking on a non-focusable element should focus
15668
			// the body anyway.
15669
			.delegate( ".ui-tabs-anchor", "focus" + this.eventNamespace, function() {
15670
				if ( $( this ).closest( "li" ).is( ".ui-state-disabled" ) ) {
15671
					this.blur();
15672
				}
15673
			});
15674
15675
		this.tabs = this.tablist.find( "> li:has(a[href])" )
15676
			.addClass( "ui-state-default ui-corner-top" )
15677
			.attr({
15678
				role: "tab",
15679
				tabIndex: -1
15680
			});
15681
15682
		this.anchors = this.tabs.map(function() {
15683
				return $( "a", this )[ 0 ];
15684
			})
15685
			.addClass( "ui-tabs-anchor" )
15686
			.attr({
15687
				role: "presentation",
15688
				tabIndex: -1
15689
			});
15690
15691
		this.panels = $();
15692
15693
		this.anchors.each(function( i, anchor ) {
15694
			var selector, panel, panelId,
15695
				anchorId = $( anchor ).uniqueId().attr( "id" ),
15696
				tab = $( anchor ).closest( "li" ),
15697
				originalAriaControls = tab.attr( "aria-controls" );
15698
15699
			// inline tab
15700
			if ( that._isLocal( anchor ) ) {
15701
				selector = anchor.hash;
15702
				panelId = selector.substring( 1 );
15703
				panel = that.element.find( that._sanitizeSelector( selector ) );
15704
			// remote tab
15705
			} else {
15706
				// If the tab doesn't already have aria-controls,
15707
				// generate an id by using a throw-away element
15708
				panelId = tab.attr( "aria-controls" ) || $( {} ).uniqueId()[ 0 ].id;
15709
				selector = "#" + panelId;
15710
				panel = that.element.find( selector );
15711
				if ( !panel.length ) {
15712
					panel = that._createPanel( panelId );
15713
					panel.insertAfter( that.panels[ i - 1 ] || that.tablist );
15714
				}
15715
				panel.attr( "aria-live", "polite" );
15716
			}
15717
15718
			if ( panel.length) {
15719
				that.panels = that.panels.add( panel );
15720
			}
15721
			if ( originalAriaControls ) {
15722
				tab.data( "ui-tabs-aria-controls", originalAriaControls );
15723
			}
15724
			tab.attr({
15725
				"aria-controls": panelId,
15726
				"aria-labelledby": anchorId
15727
			});
15728
			panel.attr( "aria-labelledby", anchorId );
15729
		});
15730
15731
		this.panels
15732
			.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
15733
			.attr( "role", "tabpanel" );
15734
15735
		// Avoid memory leaks (#10056)
15736
		if ( prevTabs ) {
15737
			this._off( prevTabs.not( this.tabs ) );
15738
			this._off( prevAnchors.not( this.anchors ) );
15739
			this._off( prevPanels.not( this.panels ) );
15740
		}
15741
	},
15742
15743
	// allow overriding how to find the list for rare usage scenarios (#7715)
15744
	_getList: function() {
15745
		return this.tablist || this.element.find( "ol,ul" ).eq( 0 );
15746
	},
15747
15748
	_createPanel: function( id ) {
15749
		return $( "<div>" )
15750
			.attr( "id", id )
15751
			.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
15752
			.data( "ui-tabs-destroy", true );
15753
	},
15754
15755
	_setupDisabled: function( disabled ) {
15756
		if ( $.isArray( disabled ) ) {
15757
			if ( !disabled.length ) {
15758
				disabled = false;
15759
			} else if ( disabled.length === this.anchors.length ) {
15760
				disabled = true;
15761
			}
15762
		}
15763
15764
		// disable tabs
15765
		for ( var i = 0, li; ( li = this.tabs[ i ] ); i++ ) {
15766
			if ( disabled === true || $.inArray( i, disabled ) !== -1 ) {
15767
				$( li )
15768
					.addClass( "ui-state-disabled" )
15769
					.attr( "aria-disabled", "true" );
15770
			} else {
15771
				$( li )
15772
					.removeClass( "ui-state-disabled" )
15773
					.removeAttr( "aria-disabled" );
15774
			}
15775
		}
15776
15777
		this.options.disabled = disabled;
15778
	},
15779
15780
	_setupEvents: function( event ) {
15781
		var events = {};
15782
		if ( event ) {
15783
			$.each( event.split(" "), function( index, eventName ) {
15784
				events[ eventName ] = "_eventHandler";
15785
			});
15786
		}
15787
15788
		this._off( this.anchors.add( this.tabs ).add( this.panels ) );
15789
		// Always prevent the default action, even when disabled
15790
		this._on( true, this.anchors, {
15791
			click: function( event ) {
15792
				event.preventDefault();
15793
			}
15794
		});
15795
		this._on( this.anchors, events );
15796
		this._on( this.tabs, { keydown: "_tabKeydown" } );
15797
		this._on( this.panels, { keydown: "_panelKeydown" } );
15798
15799
		this._focusable( this.tabs );
15800
		this._hoverable( this.tabs );
15801
	},
15802
15803
	_setupHeightStyle: function( heightStyle ) {
15804
		var maxHeight,
15805
			parent = this.element.parent();
15806
15807
		if ( heightStyle === "fill" ) {
15808
			maxHeight = parent.height();
15809
			maxHeight -= this.element.outerHeight() - this.element.height();
15810
15811
			this.element.siblings( ":visible" ).each(function() {
15812
				var elem = $( this ),
15813
					position = elem.css( "position" );
15814
15815
				if ( position === "absolute" || position === "fixed" ) {
15816
					return;
15817
				}
15818
				maxHeight -= elem.outerHeight( true );
15819
			});
15820
15821
			this.element.children().not( this.panels ).each(function() {
15822
				maxHeight -= $( this ).outerHeight( true );
15823
			});
15824
15825
			this.panels.each(function() {
15826
				$( this ).height( Math.max( 0, maxHeight -
15827
					$( this ).innerHeight() + $( this ).height() ) );
15828
			})
15829
			.css( "overflow", "auto" );
15830
		} else if ( heightStyle === "auto" ) {
15831
			maxHeight = 0;
15832
			this.panels.each(function() {
15833
				maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
15834
			}).height( maxHeight );
15835
		}
15836
	},
15837
15838
	_eventHandler: function( event ) {
15839
		var options = this.options,
15840
			active = this.active,
15841
			anchor = $( event.currentTarget ),
15842
			tab = anchor.closest( "li" ),
15843
			clickedIsActive = tab[ 0 ] === active[ 0 ],
15844
			collapsing = clickedIsActive && options.collapsible,
15845
			toShow = collapsing ? $() : this._getPanelForTab( tab ),
15846
			toHide = !active.length ? $() : this._getPanelForTab( active ),
15847
			eventData = {
15848
				oldTab: active,
15849
				oldPanel: toHide,
15850
				newTab: collapsing ? $() : tab,
15851
				newPanel: toShow
15852
			};
15853
15854
		event.preventDefault();
15855
15856
		if ( tab.hasClass( "ui-state-disabled" ) ||
15857
				// tab is already loading
15858
				tab.hasClass( "ui-tabs-loading" ) ||
15859
				// can't switch durning an animation
15860
				this.running ||
15861
				// click on active header, but not collapsible
15862
				( clickedIsActive && !options.collapsible ) ||
15863
				// allow canceling activation
15864
				( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
15865
			return;
15866
		}
15867
15868
		options.active = collapsing ? false : this.tabs.index( tab );
15869
15870
		this.active = clickedIsActive ? $() : tab;
15871
		if ( this.xhr ) {
15872
			this.xhr.abort();
15873
		}
15874
15875
		if ( !toHide.length && !toShow.length ) {
15876
			$.error( "jQuery UI Tabs: Mismatching fragment identifier." );
15877
		}
15878
15879
		if ( toShow.length ) {
15880
			this.load( this.tabs.index( tab ), event );
15881
		}
15882
		this._toggle( event, eventData );
15883
	},
15884
15885
	// handles show/hide for selecting tabs
15886
	_toggle: function( event, eventData ) {
15887
		var that = this,
15888
			toShow = eventData.newPanel,
15889
			toHide = eventData.oldPanel;
15890
15891
		this.running = true;
15892
15893
		function complete() {
15894
			that.running = false;
15895
			that._trigger( "activate", event, eventData );
15896
		}
15897
15898
		function show() {
15899
			eventData.newTab.closest( "li" ).addClass( "ui-tabs-active ui-state-active" );
15900
15901
			if ( toShow.length && that.options.show ) {
15902
				that._show( toShow, that.options.show, complete );
15903
			} else {
15904
				toShow.show();
15905
				complete();
15906
			}
15907
		}
15908
15909
		// start out by hiding, then showing, then completing
15910
		if ( toHide.length && this.options.hide ) {
15911
			this._hide( toHide, this.options.hide, function() {
15912
				eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
15913
				show();
15914
			});
15915
		} else {
15916
			eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
15917
			toHide.hide();
15918
			show();
15919
		}
15920
15921
		toHide.attr( "aria-hidden", "true" );
15922
		eventData.oldTab.attr({
15923
			"aria-selected": "false",
15924
			"aria-expanded": "false"
15925
		});
15926
		// If we're switching tabs, remove the old tab from the tab order.
15927
		// If we're opening from collapsed state, remove the previous tab from the tab order.
15928
		// If we're collapsing, then keep the collapsing tab in the tab order.
15929
		if ( toShow.length && toHide.length ) {
15930
			eventData.oldTab.attr( "tabIndex", -1 );
15931
		} else if ( toShow.length ) {
15932
			this.tabs.filter(function() {
15933
				return $( this ).attr( "tabIndex" ) === 0;
15934
			})
15935
			.attr( "tabIndex", -1 );
15936
		}
15937
15938
		toShow.attr( "aria-hidden", "false" );
15939
		eventData.newTab.attr({
15940
			"aria-selected": "true",
15941
			"aria-expanded": "true",
15942
			tabIndex: 0
15943
		});
15944
	},
15945
15946
	_activate: function( index ) {
15947
		var anchor,
15948
			active = this._findActive( index );
15949
15950
		// trying to activate the already active panel
15951
		if ( active[ 0 ] === this.active[ 0 ] ) {
15952
			return;
15953
		}
15954
15955
		// trying to collapse, simulate a click on the current active header
15956
		if ( !active.length ) {
15957
			active = this.active;
15958
		}
15959
15960
		anchor = active.find( ".ui-tabs-anchor" )[ 0 ];
15961
		this._eventHandler({
15962
			target: anchor,
15963
			currentTarget: anchor,
15964
			preventDefault: $.noop
15965
		});
15966
	},
15967
15968
	_findActive: function( index ) {
15969
		return index === false ? $() : this.tabs.eq( index );
15970
	},
15971
15972
	_getIndex: function( index ) {
15973
		// meta-function to give users option to provide a href string instead of a numerical index.
15974
		if ( typeof index === "string" ) {
15975
			index = this.anchors.index( this.anchors.filter( "[href$='" + index + "']" ) );
15976
		}
15977
15978
		return index;
15979
	},
15980
15981
	_destroy: function() {
15982
		if ( this.xhr ) {
15983
			this.xhr.abort();
15984
		}
15985
15986
		this.element.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" );
15987
15988
		this.tablist
15989
			.removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" )
15990
			.removeAttr( "role" );
15991
15992
		this.anchors
15993
			.removeClass( "ui-tabs-anchor" )
15994
			.removeAttr( "role" )
15995
			.removeAttr( "tabIndex" )
15996
			.removeUniqueId();
15997
15998
		this.tablist.unbind( this.eventNamespace );
15999
16000
		this.tabs.add( this.panels ).each(function() {
16001
			if ( $.data( this, "ui-tabs-destroy" ) ) {
16002
				$( this ).remove();
16003
			} else {
16004
				$( this )
16005
					.removeClass( "ui-state-default ui-state-active ui-state-disabled " +
16006
						"ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel" )
16007
					.removeAttr( "tabIndex" )
16008
					.removeAttr( "aria-live" )
16009
					.removeAttr( "aria-busy" )
16010
					.removeAttr( "aria-selected" )
16011
					.removeAttr( "aria-labelledby" )
16012
					.removeAttr( "aria-hidden" )
16013
					.removeAttr( "aria-expanded" )
16014
					.removeAttr( "role" );
16015
			}
16016
		});
16017
16018
		this.tabs.each(function() {
16019
			var li = $( this ),
16020
				prev = li.data( "ui-tabs-aria-controls" );
16021
			if ( prev ) {
16022
				li
16023
					.attr( "aria-controls", prev )
16024
					.removeData( "ui-tabs-aria-controls" );
16025
			} else {
16026
				li.removeAttr( "aria-controls" );
16027
			}
16028
		});
16029
16030
		this.panels.show();
16031
16032
		if ( this.options.heightStyle !== "content" ) {
16033
			this.panels.css( "height", "" );
16034
		}
16035
	},
16036
16037
	enable: function( index ) {
16038
		var disabled = this.options.disabled;
16039
		if ( disabled === false ) {
16040
			return;
16041
		}
16042
16043
		if ( index === undefined ) {
16044
			disabled = false;
16045
		} else {
16046
			index = this._getIndex( index );
16047
			if ( $.isArray( disabled ) ) {
16048
				disabled = $.map( disabled, function( num ) {
16049
					return num !== index ? num : null;
16050
				});
16051
			} else {
16052
				disabled = $.map( this.tabs, function( li, num ) {
16053
					return num !== index ? num : null;
16054
				});
16055
			}
16056
		}
16057
		this._setupDisabled( disabled );
16058
	},
16059
16060
	disable: function( index ) {
16061
		var disabled = this.options.disabled;
16062
		if ( disabled === true ) {
16063
			return;
16064
		}
16065
16066
		if ( index === undefined ) {
16067
			disabled = true;
16068
		} else {
16069
			index = this._getIndex( index );
16070
			if ( $.inArray( index, disabled ) !== -1 ) {
16071
				return;
16072
			}
16073
			if ( $.isArray( disabled ) ) {
16074
				disabled = $.merge( [ index ], disabled ).sort();
16075
			} else {
16076
				disabled = [ index ];
16077
			}
16078
		}
16079
		this._setupDisabled( disabled );
16080
	},
16081
16082
	load: function( index, event ) {
16083
		index = this._getIndex( index );
16084
		var that = this,
16085
			tab = this.tabs.eq( index ),
16086
			anchor = tab.find( ".ui-tabs-anchor" ),
16087
			panel = this._getPanelForTab( tab ),
16088
			eventData = {
16089
				tab: tab,
16090
				panel: panel
16091
			},
16092
			complete = function( jqXHR, status ) {
16093
				if ( status === "abort" ) {
16094
					that.panels.stop( false, true );
16095
				}
16096
16097
				tab.removeClass( "ui-tabs-loading" );
16098
				panel.removeAttr( "aria-busy" );
16099
16100
				if ( jqXHR === that.xhr ) {
16101
					delete that.xhr;
16102
				}
16103
			};
16104
16105
		// not remote
16106
		if ( this._isLocal( anchor[ 0 ] ) ) {
16107
			return;
16108
		}
16109
16110
		this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) );
16111
16112
		// support: jQuery <1.8
16113
		// jQuery <1.8 returns false if the request is canceled in beforeSend,
16114
		// but as of 1.8, $.ajax() always returns a jqXHR object.
16115
		if ( this.xhr && this.xhr.statusText !== "canceled" ) {
16116
			tab.addClass( "ui-tabs-loading" );
16117
			panel.attr( "aria-busy", "true" );
16118
16119
			this.xhr
16120
				.done(function( response, status, jqXHR ) {
16121
					// support: jQuery <1.8
16122
					// http://bugs.jquery.com/ticket/11778
16123
					setTimeout(function() {
16124
						panel.html( response );
16125
						that._trigger( "load", event, eventData );
16126
16127
						complete( jqXHR, status );
16128
					}, 1 );
16129
				})
16130
				.fail(function( jqXHR, status ) {
16131
					// support: jQuery <1.8
16132
					// http://bugs.jquery.com/ticket/11778
16133
					setTimeout(function() {
16134
						complete( jqXHR, status );
16135
					}, 1 );
16136
				});
16137
		}
16138
	},
16139
16140
	_ajaxSettings: function( anchor, event, eventData ) {
16141
		var that = this;
16142
		return {
16143
			url: anchor.attr( "href" ),
16144
			beforeSend: function( jqXHR, settings ) {
16145
				return that._trigger( "beforeLoad", event,
16146
					$.extend( { jqXHR: jqXHR, ajaxSettings: settings }, eventData ) );
16147
			}
16148
		};
16149
	},
16150
16151
	_getPanelForTab: function( tab ) {
16152
		var id = $( tab ).attr( "aria-controls" );
16153
		return this.element.find( this._sanitizeSelector( "#" + id ) );
16154
	}
16155
});
16156
16157
16158
/*!
16159
 * jQuery UI Tooltip 1.11.4
16160
 * http://jqueryui.com
16161
 *
16162
 * Copyright jQuery Foundation and other contributors
16163
 * Released under the MIT license.
16164
 * http://jquery.org/license
16165
 *
16166
 * http://api.jqueryui.com/tooltip/
16167
 */
16168
16169
16170
var tooltip = $.widget( "ui.tooltip", {
16171
	version: "1.11.4",
16172
	options: {
16173
		content: function() {
16174
			// support: IE<9, Opera in jQuery <1.7
16175
			// .text() can't accept undefined, so coerce to a string
16176
			var title = $( this ).attr( "title" ) || "";
16177
			// Escape title, since we're going from an attribute to raw HTML
16178
			return $( "<a>" ).text( title ).html();
16179
		},
16180
		hide: true,
16181
		// Disabled elements have inconsistent behavior across browsers (#8661)
16182
		items: "[title]:not([disabled])",
16183
		position: {
16184
			my: "left top+15",
16185
			at: "left bottom",
16186
			collision: "flipfit flip"
16187
		},
16188
		show: true,
16189
		tooltipClass: null,
16190
		track: false,
16191
16192
		// callbacks
16193
		close: null,
16194
		open: null
16195
	},
16196
16197
	_addDescribedBy: function( elem, id ) {
16198
		var describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ );
16199
		describedby.push( id );
16200
		elem
16201
			.data( "ui-tooltip-id", id )
16202
			.attr( "aria-describedby", $.trim( describedby.join( " " ) ) );
16203
	},
16204
16205
	_removeDescribedBy: function( elem ) {
16206
		var id = elem.data( "ui-tooltip-id" ),
16207
			describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ ),
16208
			index = $.inArray( id, describedby );
16209
16210
		if ( index !== -1 ) {
16211
			describedby.splice( index, 1 );
16212
		}
16213
16214
		elem.removeData( "ui-tooltip-id" );
16215
		describedby = $.trim( describedby.join( " " ) );
16216
		if ( describedby ) {
16217
			elem.attr( "aria-describedby", describedby );
16218
		} else {
16219
			elem.removeAttr( "aria-describedby" );
16220
		}
16221
	},
16222
16223
	_create: function() {
16224
		this._on({
16225
			mouseover: "open",
16226
			focusin: "open"
16227
		});
16228
16229
		// IDs of generated tooltips, needed for destroy
16230
		this.tooltips = {};
16231
16232
		// IDs of parent tooltips where we removed the title attribute
16233
		this.parents = {};
16234
16235
		if ( this.options.disabled ) {
16236
			this._disable();
16237
		}
16238
16239
		// Append the aria-live region so tooltips announce correctly
16240
		this.liveRegion = $( "<div>" )
16241
			.attr({
16242
				role: "log",
16243
				"aria-live": "assertive",
16244
				"aria-relevant": "additions"
16245
			})
16246
			.addClass( "ui-helper-hidden-accessible" )
16247
			.appendTo( this.document[ 0 ].body );
16248
	},
16249
16250
	_setOption: function( key, value ) {
16251
		var that = this;
16252
16253
		if ( key === "disabled" ) {
16254
			this[ value ? "_disable" : "_enable" ]();
16255
			this.options[ key ] = value;
16256
			// disable element style changes
16257
			return;
16258
		}
16259
16260
		this._super( key, value );
16261
16262
		if ( key === "content" ) {
16263
			$.each( this.tooltips, function( id, tooltipData ) {
16264
				that._updateContent( tooltipData.element );
16265
			});
16266
		}
16267
	},
16268
16269
	_disable: function() {
16270
		var that = this;
16271
16272
		// close open tooltips
16273
		$.each( this.tooltips, function( id, tooltipData ) {
16274
			var event = $.Event( "blur" );
16275
			event.target = event.currentTarget = tooltipData.element[ 0 ];
16276
			that.close( event, true );
16277
		});
16278
16279
		// remove title attributes to prevent native tooltips
16280
		this.element.find( this.options.items ).addBack().each(function() {
16281
			var element = $( this );
16282
			if ( element.is( "[title]" ) ) {
16283
				element
16284
					.data( "ui-tooltip-title", element.attr( "title" ) )
16285
					.removeAttr( "title" );
16286
			}
16287
		});
16288
	},
16289
16290
	_enable: function() {
16291
		// restore title attributes
16292
		this.element.find( this.options.items ).addBack().each(function() {
16293
			var element = $( this );
16294
			if ( element.data( "ui-tooltip-title" ) ) {
16295
				element.attr( "title", element.data( "ui-tooltip-title" ) );
16296
			}
16297
		});
16298
	},
16299
16300
	open: function( event ) {
16301
		var that = this,
16302
			target = $( event ? event.target : this.element )
16303
				// we need closest here due to mouseover bubbling,
16304
				// but always pointing at the same event target
16305
				.closest( this.options.items );
16306
16307
		// No element to show a tooltip for or the tooltip is already open
16308
		if ( !target.length || target.data( "ui-tooltip-id" ) ) {
16309
			return;
16310
		}
16311
16312
		if ( target.attr( "title" ) ) {
16313
			target.data( "ui-tooltip-title", target.attr( "title" ) );
16314
		}
16315
16316
		target.data( "ui-tooltip-open", true );
16317
16318
		// kill parent tooltips, custom or native, for hover
16319
		if ( event && event.type === "mouseover" ) {
16320
			target.parents().each(function() {
16321
				var parent = $( this ),
16322
					blurEvent;
16323
				if ( parent.data( "ui-tooltip-open" ) ) {
16324
					blurEvent = $.Event( "blur" );
16325
					blurEvent.target = blurEvent.currentTarget = this;
16326
					that.close( blurEvent, true );
16327
				}
16328
				if ( parent.attr( "title" ) ) {
16329
					parent.uniqueId();
16330
					that.parents[ this.id ] = {
16331
						element: this,
16332
						title: parent.attr( "title" )
16333
					};
16334
					parent.attr( "title", "" );
16335
				}
16336
			});
16337
		}
16338
16339
		this._registerCloseHandlers( event, target );
16340
		this._updateContent( target, event );
16341
	},
16342
16343
	_updateContent: function( target, event ) {
16344
		var content,
16345
			contentOption = this.options.content,
16346
			that = this,
16347
			eventType = event ? event.type : null;
16348
16349
		if ( typeof contentOption === "string" ) {
16350
			return this._open( event, target, contentOption );
16351
		}
16352
16353
		content = contentOption.call( target[0], function( response ) {
16354
16355
			// IE may instantly serve a cached response for ajax requests
16356
			// delay this call to _open so the other call to _open runs first
16357
			that._delay(function() {
16358
16359
				// Ignore async response if tooltip was closed already
16360
				if ( !target.data( "ui-tooltip-open" ) ) {
16361
					return;
16362
				}
16363
16364
				// jQuery creates a special event for focusin when it doesn't
16365
				// exist natively. To improve performance, the native event
16366
				// object is reused and the type is changed. Therefore, we can't
16367
				// rely on the type being correct after the event finished
16368
				// bubbling, so we set it back to the previous value. (#8740)
16369
				if ( event ) {
16370
					event.type = eventType;
16371
				}
16372
				this._open( event, target, response );
16373
			});
16374
		});
16375
		if ( content ) {
16376
			this._open( event, target, content );
16377
		}
16378
	},
16379
16380
	_open: function( event, target, content ) {
16381
		var tooltipData, tooltip, delayedShow, a11yContent,
16382
			positionOption = $.extend( {}, this.options.position );
16383
16384
		if ( !content ) {
16385
			return;
16386
		}
16387
16388
		// Content can be updated multiple times. If the tooltip already
16389
		// exists, then just update the content and bail.
16390
		tooltipData = this._find( target );
16391
		if ( tooltipData ) {
16392
			tooltipData.tooltip.find( ".ui-tooltip-content" ).html( content );
16393
			return;
16394
		}
16395
16396
		// if we have a title, clear it to prevent the native tooltip
16397
		// we have to check first to avoid defining a title if none exists
16398
		// (we don't want to cause an element to start matching [title])
16399
		//
16400
		// We use removeAttr only for key events, to allow IE to export the correct
16401
		// accessible attributes. For mouse events, set to empty string to avoid
16402
		// native tooltip showing up (happens only when removing inside mouseover).
16403
		if ( target.is( "[title]" ) ) {
16404
			if ( event && event.type === "mouseover" ) {
16405
				target.attr( "title", "" );
16406
			} else {
16407
				target.removeAttr( "title" );
16408
			}
16409
		}
16410
16411
		tooltipData = this._tooltip( target );
16412
		tooltip = tooltipData.tooltip;
16413
		this._addDescribedBy( target, tooltip.attr( "id" ) );
16414
		tooltip.find( ".ui-tooltip-content" ).html( content );
16415
16416
		// Support: Voiceover on OS X, JAWS on IE <= 9
16417
		// JAWS announces deletions even when aria-relevant="additions"
16418
		// Voiceover will sometimes re-read the entire log region's contents from the beginning
16419
		this.liveRegion.children().hide();
16420
		if ( content.clone ) {
16421
			a11yContent = content.clone();
16422
			a11yContent.removeAttr( "id" ).find( "[id]" ).removeAttr( "id" );
16423
		} else {
16424
			a11yContent = content;
16425
		}
16426
		$( "<div>" ).html( a11yContent ).appendTo( this.liveRegion );
16427
16428
		function position( event ) {
16429
			positionOption.of = event;
16430
			if ( tooltip.is( ":hidden" ) ) {
16431
				return;
16432
			}
16433
			tooltip.position( positionOption );
16434
		}
16435
		if ( this.options.track && event && /^mouse/.test( event.type ) ) {
16436
			this._on( this.document, {
16437
				mousemove: position
16438
			});
16439
			// trigger once to override element-relative positioning
16440
			position( event );
16441
		} else {
16442
			tooltip.position( $.extend({
16443
				of: target
16444
			}, this.options.position ) );
16445
		}
16446
16447
		tooltip.hide();
16448
16449
		this._show( tooltip, this.options.show );
16450
		// Handle tracking tooltips that are shown with a delay (#8644). As soon
16451
		// as the tooltip is visible, position the tooltip using the most recent
16452
		// event.
16453
		if ( this.options.show && this.options.show.delay ) {
16454
			delayedShow = this.delayedShow = setInterval(function() {
16455
				if ( tooltip.is( ":visible" ) ) {
16456
					position( positionOption.of );
16457
					clearInterval( delayedShow );
16458
				}
16459
			}, $.fx.interval );
16460
		}
16461
16462
		this._trigger( "open", event, { tooltip: tooltip } );
16463
	},
16464
16465
	_registerCloseHandlers: function( event, target ) {
16466
		var events = {
16467
			keyup: function( event ) {
16468
				if ( event.keyCode === $.ui.keyCode.ESCAPE ) {
16469
					var fakeEvent = $.Event(event);
16470
					fakeEvent.currentTarget = target[0];
16471
					this.close( fakeEvent, true );
16472
				}
16473
			}
16474
		};
16475
16476
		// Only bind remove handler for delegated targets. Non-delegated
16477
		// tooltips will handle this in destroy.
16478
		if ( target[ 0 ] !== this.element[ 0 ] ) {
16479
			events.remove = function() {
16480
				this._removeTooltip( this._find( target ).tooltip );
16481
			};
16482
		}
16483
16484
		if ( !event || event.type === "mouseover" ) {
16485
			events.mouseleave = "close";
16486
		}
16487
		if ( !event || event.type === "focusin" ) {
16488
			events.focusout = "close";
16489
		}
16490
		this._on( true, target, events );
16491
	},
16492
16493
	close: function( event ) {
16494
		var tooltip,
16495
			that = this,
16496
			target = $( event ? event.currentTarget : this.element ),
16497
			tooltipData = this._find( target );
16498
16499
		// The tooltip may already be closed
16500
		if ( !tooltipData ) {
16501
16502
			// We set ui-tooltip-open immediately upon open (in open()), but only set the
16503
			// additional data once there's actually content to show (in _open()). So even if the
16504
			// tooltip doesn't have full data, we always remove ui-tooltip-open in case we're in
16505
			// the period between open() and _open().
16506
			target.removeData( "ui-tooltip-open" );
16507
			return;
16508
		}
16509
16510
		tooltip = tooltipData.tooltip;
16511
16512
		// disabling closes the tooltip, so we need to track when we're closing
16513
		// to avoid an infinite loop in case the tooltip becomes disabled on close
16514
		if ( tooltipData.closing ) {
16515
			return;
16516
		}
16517
16518
		// Clear the interval for delayed tracking tooltips
16519
		clearInterval( this.delayedShow );
16520
16521
		// only set title if we had one before (see comment in _open())
16522
		// If the title attribute has changed since open(), don't restore
16523
		if ( target.data( "ui-tooltip-title" ) && !target.attr( "title" ) ) {
16524
			target.attr( "title", target.data( "ui-tooltip-title" ) );
16525
		}
16526
16527
		this._removeDescribedBy( target );
16528
16529
		tooltipData.hiding = true;
16530
		tooltip.stop( true );
16531
		this._hide( tooltip, this.options.hide, function() {
16532
			that._removeTooltip( $( this ) );
16533
		});
16534
16535
		target.removeData( "ui-tooltip-open" );
16536
		this._off( target, "mouseleave focusout keyup" );
16537
16538
		// Remove 'remove' binding only on delegated targets
16539
		if ( target[ 0 ] !== this.element[ 0 ] ) {
16540
			this._off( target, "remove" );
16541
		}
16542
		this._off( this.document, "mousemove" );
16543
16544
		if ( event && event.type === "mouseleave" ) {
16545
			$.each( this.parents, function( id, parent ) {
16546
				$( parent.element ).attr( "title", parent.title );
16547
				delete that.parents[ id ];
16548
			});
16549
		}
16550
16551
		tooltipData.closing = true;
16552
		this._trigger( "close", event, { tooltip: tooltip } );
16553
		if ( !tooltipData.hiding ) {
16554
			tooltipData.closing = false;
16555
		}
16556
	},
16557
16558
	_tooltip: function( element ) {
16559
		var tooltip = $( "<div>" )
16560
				.attr( "role", "tooltip" )
16561
				.addClass( "ui-tooltip ui-widget ui-corner-all ui-widget-content " +
16562
					( this.options.tooltipClass || "" ) ),
16563
			id = tooltip.uniqueId().attr( "id" );
16564
16565
		$( "<div>" )
16566
			.addClass( "ui-tooltip-content" )
16567
			.appendTo( tooltip );
16568
16569
		tooltip.appendTo( this.document[0].body );
16570
16571
		return this.tooltips[ id ] = {
16572
			element: element,
16573
			tooltip: tooltip
16574
		};
16575
	},
16576
16577
	_find: function( target ) {
16578
		var id = target.data( "ui-tooltip-id" );
16579
		return id ? this.tooltips[ id ] : null;
16580
	},
16581
16582
	_removeTooltip: function( tooltip ) {
16583
		tooltip.remove();
16584
		delete this.tooltips[ tooltip.attr( "id" ) ];
16585
	},
16586
16587
	_destroy: function() {
16588
		var that = this;
16589
16590
		// close open tooltips
16591
		$.each( this.tooltips, function( id, tooltipData ) {
16592
			// Delegate to close method to handle common cleanup
16593
			var event = $.Event( "blur" ),
16594
				element = tooltipData.element;
16595
			event.target = event.currentTarget = element[ 0 ];
16596
			that.close( event, true );
16597
16598
			// Remove immediately; destroying an open tooltip doesn't use the
16599
			// hide animation
16600
			$( "#" + id ).remove();
16601
16602
			// Restore the title
16603
			if ( element.data( "ui-tooltip-title" ) ) {
16604
				// If the title attribute has changed since open(), don't restore
16605
				if ( !element.attr( "title" ) ) {
16606
					element.attr( "title", element.data( "ui-tooltip-title" ) );
16607
				}
16608
				element.removeData( "ui-tooltip-title" );
16609
			}
16610
		});
16611
		this.liveRegion.remove();
16612
	}
16613
});
16614
16615
16616
16617
}));