Issues (81)

assets/jquery-ui.js (16 issues)

1
/*! jQuery UI - v1.11.4 - 2015-05-31
2
* http://jqueryui.com
3
* Includes: core.js, widget.js, position.js, autocomplete.js, menu.js
4
* Copyright 2015 jQuery Foundation and other contributors; Licensed MIT */
5
6
(function( factory ) {
7
	if ( typeof define === "function" && define.amd ) {
0 ignored issues
show
The variable define seems to be never declared. If this is a global, consider adding a /** global: define */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
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 ?
0 ignored issues
show
Comparing selector to null using the == operator is not safe. Consider using === instead.
Loading history...
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 {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
208
				return removeData.call( this );
209
			}
210
		};
211
	})( $.fn.removeData );
212
}
213
214
// deprecated
215
$.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() );
0 ignored issues
show
The variable navigator seems to be never declared. If this is a global, consider adding a /** global: navigator */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
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++ ) {
0 ignored issues
show
Comparing elem = elems.i to null using the != operator is not safe. Consider using !== instead.
Loading history...
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 ) {}
0 ignored issues
show
Coding Style Comprehensibility Best Practice introduced by
Empty catch clauses should be used with caution; consider adding a comment why this is needed.
Loading history...
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 );
0 ignored issues
show
Coding Style Best Practice introduced by
By convention, constructors like constructor should be capitalized.
Loading history...
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 ) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if arguments.length is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
376
			this._createWidget( options, element );
0 ignored issues
show
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
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();
0 ignored issues
show
Coding Style Best Practice introduced by
By convention, constructors like base should be capitalized.
Loading history...
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 ) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if methodValue !== instance...thodValue !== undefined is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
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 ) );
0 ignored issues
show
Coding Style Best Practice introduced by
By convention, constructors like object should be capitalized.
Loading history...
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;
0 ignored issues
show
Comprehensibility Best Practice introduced by
Are you sure this return statement is not missing an argument? If this is intended, consider adding an explicit undefined like return undefined;.
Loading history...
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 Position 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/position/
868
 */
869
870
(function() {
871
872
$.ui = $.ui || {};
873
874
var cachedScrollbarWidth, supportsOffsetFractions,
875
	max = Math.max,
876
	abs = Math.abs,
877
	round = Math.round,
878
	rhorizontal = /left|center|right/,
879
	rvertical = /top|center|bottom/,
880
	roffset = /[\+\-]\d+(\.[\d]+)?%?/,
881
	rposition = /^\w+/,
882
	rpercent = /%$/,
883
	_position = $.fn.position;
884
885
function getOffsets( offsets, width, height ) {
886
	return [
887
		parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),
888
		parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )
889
	];
890
}
891
892
function parseCss( element, property ) {
893
	return parseInt( $.css( element, property ), 10 ) || 0;
894
}
895
896
function getDimensions( elem ) {
897
	var raw = elem[0];
898
	if ( raw.nodeType === 9 ) {
899
		return {
900
			width: elem.width(),
901
			height: elem.height(),
902
			offset: { top: 0, left: 0 }
903
		};
904
	}
905
	if ( $.isWindow( raw ) ) {
906
		return {
907
			width: elem.width(),
908
			height: elem.height(),
909
			offset: { top: elem.scrollTop(), left: elem.scrollLeft() }
910
		};
911
	}
912
	if ( raw.preventDefault ) {
913
		return {
914
			width: 0,
915
			height: 0,
916
			offset: { top: raw.pageY, left: raw.pageX }
917
		};
918
	}
919
	return {
920
		width: elem.outerWidth(),
921
		height: elem.outerHeight(),
922
		offset: elem.offset()
923
	};
924
}
925
926
$.position = {
927
	scrollbarWidth: function() {
928
		if ( cachedScrollbarWidth !== undefined ) {
929
			return cachedScrollbarWidth;
930
		}
931
		var w1, w2,
932
			div = $( "<div style='display:block;position:absolute;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>" ),
933
			innerDiv = div.children()[0];
934
935
		$( "body" ).append( div );
936
		w1 = innerDiv.offsetWidth;
937
		div.css( "overflow", "scroll" );
938
939
		w2 = innerDiv.offsetWidth;
940
941
		if ( w1 === w2 ) {
942
			w2 = div[0].clientWidth;
943
		}
944
945
		div.remove();
946
947
		return (cachedScrollbarWidth = w1 - w2);
948
	},
949
	getScrollInfo: function( within ) {
950
		var overflowX = within.isWindow || within.isDocument ? "" :
951
				within.element.css( "overflow-x" ),
952
			overflowY = within.isWindow || within.isDocument ? "" :
953
				within.element.css( "overflow-y" ),
954
			hasOverflowX = overflowX === "scroll" ||
955
				( overflowX === "auto" && within.width < within.element[0].scrollWidth ),
956
			hasOverflowY = overflowY === "scroll" ||
957
				( overflowY === "auto" && within.height < within.element[0].scrollHeight );
958
		return {
959
			width: hasOverflowY ? $.position.scrollbarWidth() : 0,
960
			height: hasOverflowX ? $.position.scrollbarWidth() : 0
961
		};
962
	},
963
	getWithinInfo: function( element ) {
964
		var withinElement = $( element || window ),
965
			isWindow = $.isWindow( withinElement[0] ),
966
			isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9;
967
		return {
968
			element: withinElement,
969
			isWindow: isWindow,
970
			isDocument: isDocument,
971
			offset: withinElement.offset() || { left: 0, top: 0 },
972
			scrollLeft: withinElement.scrollLeft(),
973
			scrollTop: withinElement.scrollTop(),
974
975
			// support: jQuery 1.6.x
976
			// jQuery 1.6 doesn't support .outerWidth/Height() on documents or windows
977
			width: isWindow || isDocument ? withinElement.width() : withinElement.outerWidth(),
978
			height: isWindow || isDocument ? withinElement.height() : withinElement.outerHeight()
979
		};
980
	}
981
};
982
983
$.fn.position = function( options ) {
984
	if ( !options || !options.of ) {
985
		return _position.apply( this, arguments );
986
	}
987
988
	// make a copy, we don't want to modify arguments
989
	options = $.extend( {}, options );
990
991
	var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,
992
		target = $( options.of ),
993
		within = $.position.getWithinInfo( options.within ),
994
		scrollInfo = $.position.getScrollInfo( within ),
995
		collision = ( options.collision || "flip" ).split( " " ),
996
		offsets = {};
997
998
	dimensions = getDimensions( target );
999
	if ( target[0].preventDefault ) {
1000
		// force left top to allow flipping
1001
		options.at = "left top";
1002
	}
1003
	targetWidth = dimensions.width;
1004
	targetHeight = dimensions.height;
1005
	targetOffset = dimensions.offset;
1006
	// clone to reuse original targetOffset later
1007
	basePosition = $.extend( {}, targetOffset );
1008
1009
	// force my and at to have valid horizontal and vertical positions
1010
	// if a value is missing or invalid, it will be converted to center
1011
	$.each( [ "my", "at" ], function() {
1012
		var pos = ( options[ this ] || "" ).split( " " ),
1013
			horizontalOffset,
1014
			verticalOffset;
1015
1016
		if ( pos.length === 1) {
1017
			pos = rhorizontal.test( pos[ 0 ] ) ?
1018
				pos.concat( [ "center" ] ) :
1019
				rvertical.test( pos[ 0 ] ) ?
1020
					[ "center" ].concat( pos ) :
1021
					[ "center", "center" ];
1022
		}
1023
		pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center";
1024
		pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";
1025
1026
		// calculate offsets
1027
		horizontalOffset = roffset.exec( pos[ 0 ] );
1028
		verticalOffset = roffset.exec( pos[ 1 ] );
1029
		offsets[ this ] = [
1030
			horizontalOffset ? horizontalOffset[ 0 ] : 0,
1031
			verticalOffset ? verticalOffset[ 0 ] : 0
1032
		];
1033
1034
		// reduce to just the positions without the offsets
1035
		options[ this ] = [
1036
			rposition.exec( pos[ 0 ] )[ 0 ],
1037
			rposition.exec( pos[ 1 ] )[ 0 ]
1038
		];
1039
	});
1040
1041
	// normalize collision option
1042
	if ( collision.length === 1 ) {
1043
		collision[ 1 ] = collision[ 0 ];
1044
	}
1045
1046
	if ( options.at[ 0 ] === "right" ) {
1047
		basePosition.left += targetWidth;
1048
	} else if ( options.at[ 0 ] === "center" ) {
1049
		basePosition.left += targetWidth / 2;
1050
	}
1051
1052
	if ( options.at[ 1 ] === "bottom" ) {
1053
		basePosition.top += targetHeight;
1054
	} else if ( options.at[ 1 ] === "center" ) {
1055
		basePosition.top += targetHeight / 2;
1056
	}
1057
1058
	atOffset = getOffsets( offsets.at, targetWidth, targetHeight );
1059
	basePosition.left += atOffset[ 0 ];
1060
	basePosition.top += atOffset[ 1 ];
1061
1062
	return this.each(function() {
1063
		var collisionPosition, using,
1064
			elem = $( this ),
1065
			elemWidth = elem.outerWidth(),
1066
			elemHeight = elem.outerHeight(),
1067
			marginLeft = parseCss( this, "marginLeft" ),
1068
			marginTop = parseCss( this, "marginTop" ),
1069
			collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) + scrollInfo.width,
1070
			collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) + scrollInfo.height,
1071
			position = $.extend( {}, basePosition ),
1072
			myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );
1073
1074
		if ( options.my[ 0 ] === "right" ) {
1075
			position.left -= elemWidth;
1076
		} else if ( options.my[ 0 ] === "center" ) {
1077
			position.left -= elemWidth / 2;
1078
		}
1079
1080
		if ( options.my[ 1 ] === "bottom" ) {
1081
			position.top -= elemHeight;
1082
		} else if ( options.my[ 1 ] === "center" ) {
1083
			position.top -= elemHeight / 2;
1084
		}
1085
1086
		position.left += myOffset[ 0 ];
1087
		position.top += myOffset[ 1 ];
1088
1089
		// if the browser doesn't support fractions, then round for consistent results
1090
		if ( !supportsOffsetFractions ) {
1091
			position.left = round( position.left );
1092
			position.top = round( position.top );
1093
		}
1094
1095
		collisionPosition = {
1096
			marginLeft: marginLeft,
1097
			marginTop: marginTop
1098
		};
1099
1100
		$.each( [ "left", "top" ], function( i, dir ) {
1101
			if ( $.ui.position[ collision[ i ] ] ) {
1102
				$.ui.position[ collision[ i ] ][ dir ]( position, {
1103
					targetWidth: targetWidth,
1104
					targetHeight: targetHeight,
1105
					elemWidth: elemWidth,
1106
					elemHeight: elemHeight,
1107
					collisionPosition: collisionPosition,
1108
					collisionWidth: collisionWidth,
1109
					collisionHeight: collisionHeight,
1110
					offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],
1111
					my: options.my,
1112
					at: options.at,
1113
					within: within,
1114
					elem: elem
1115
				});
1116
			}
1117
		});
1118
1119
		if ( options.using ) {
1120
			// adds feedback as second argument to using callback, if present
1121
			using = function( props ) {
1122
				var left = targetOffset.left - position.left,
1123
					right = left + targetWidth - elemWidth,
1124
					top = targetOffset.top - position.top,
1125
					bottom = top + targetHeight - elemHeight,
1126
					feedback = {
1127
						target: {
1128
							element: target,
1129
							left: targetOffset.left,
1130
							top: targetOffset.top,
1131
							width: targetWidth,
1132
							height: targetHeight
1133
						},
1134
						element: {
1135
							element: elem,
1136
							left: position.left,
1137
							top: position.top,
1138
							width: elemWidth,
1139
							height: elemHeight
1140
						},
1141
						horizontal: right < 0 ? "left" : left > 0 ? "right" : "center",
1142
						vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle"
1143
					};
1144
				if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {
1145
					feedback.horizontal = "center";
1146
				}
1147
				if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {
1148
					feedback.vertical = "middle";
1149
				}
1150
				if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {
1151
					feedback.important = "horizontal";
1152
				} else {
1153
					feedback.important = "vertical";
1154
				}
1155
				options.using.call( this, props, feedback );
1156
			};
1157
		}
1158
1159
		elem.offset( $.extend( position, { using: using } ) );
0 ignored issues
show
The variable using does not seem to be initialized in case options.using on line 1119 is false. Are you sure this can never be the case?
Loading history...
1160
	});
1161
};
1162
1163
$.ui.position = {
1164
	fit: {
1165
		left: function( position, data ) {
1166
			var within = data.within,
1167
				withinOffset = within.isWindow ? within.scrollLeft : within.offset.left,
1168
				outerWidth = within.width,
1169
				collisionPosLeft = position.left - data.collisionPosition.marginLeft,
1170
				overLeft = withinOffset - collisionPosLeft,
1171
				overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
1172
				newOverRight;
1173
1174
			// element is wider than within
1175
			if ( data.collisionWidth > outerWidth ) {
1176
				// element is initially over the left side of within
1177
				if ( overLeft > 0 && overRight <= 0 ) {
1178
					newOverRight = position.left + overLeft + data.collisionWidth - outerWidth - withinOffset;
1179
					position.left += overLeft - newOverRight;
1180
				// element is initially over right side of within
1181
				} else if ( overRight > 0 && overLeft <= 0 ) {
1182
					position.left = withinOffset;
1183
				// element is initially over both left and right sides of within
1184
				} else {
1185
					if ( overLeft > overRight ) {
1186
						position.left = withinOffset + outerWidth - data.collisionWidth;
1187
					} else {
1188
						position.left = withinOffset;
1189
					}
1190
				}
1191
			// too far left -> align with left edge
1192
			} else if ( overLeft > 0 ) {
1193
				position.left += overLeft;
1194
			// too far right -> align with right edge
1195
			} else if ( overRight > 0 ) {
1196
				position.left -= overRight;
1197
			// adjust based on position and margin
1198
			} else {
1199
				position.left = max( position.left - collisionPosLeft, position.left );
1200
			}
1201
		},
1202
		top: function( position, data ) {
1203
			var within = data.within,
1204
				withinOffset = within.isWindow ? within.scrollTop : within.offset.top,
1205
				outerHeight = data.within.height,
1206
				collisionPosTop = position.top - data.collisionPosition.marginTop,
1207
				overTop = withinOffset - collisionPosTop,
1208
				overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
1209
				newOverBottom;
1210
1211
			// element is taller than within
1212
			if ( data.collisionHeight > outerHeight ) {
1213
				// element is initially over the top of within
1214
				if ( overTop > 0 && overBottom <= 0 ) {
1215
					newOverBottom = position.top + overTop + data.collisionHeight - outerHeight - withinOffset;
1216
					position.top += overTop - newOverBottom;
1217
				// element is initially over bottom of within
1218
				} else if ( overBottom > 0 && overTop <= 0 ) {
1219
					position.top = withinOffset;
1220
				// element is initially over both top and bottom of within
1221
				} else {
1222
					if ( overTop > overBottom ) {
1223
						position.top = withinOffset + outerHeight - data.collisionHeight;
1224
					} else {
1225
						position.top = withinOffset;
1226
					}
1227
				}
1228
			// too far up -> align with top
1229
			} else if ( overTop > 0 ) {
1230
				position.top += overTop;
1231
			// too far down -> align with bottom edge
1232
			} else if ( overBottom > 0 ) {
1233
				position.top -= overBottom;
1234
			// adjust based on position and margin
1235
			} else {
1236
				position.top = max( position.top - collisionPosTop, position.top );
1237
			}
1238
		}
1239
	},
1240
	flip: {
1241
		left: function( position, data ) {
1242
			var within = data.within,
1243
				withinOffset = within.offset.left + within.scrollLeft,
1244
				outerWidth = within.width,
1245
				offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,
1246
				collisionPosLeft = position.left - data.collisionPosition.marginLeft,
1247
				overLeft = collisionPosLeft - offsetLeft,
1248
				overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,
1249
				myOffset = data.my[ 0 ] === "left" ?
1250
					-data.elemWidth :
1251
					data.my[ 0 ] === "right" ?
1252
						data.elemWidth :
1253
						0,
1254
				atOffset = data.at[ 0 ] === "left" ?
1255
					data.targetWidth :
1256
					data.at[ 0 ] === "right" ?
1257
						-data.targetWidth :
1258
						0,
1259
				offset = -2 * data.offset[ 0 ],
1260
				newOverRight,
1261
				newOverLeft;
1262
1263
			if ( overLeft < 0 ) {
1264
				newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - outerWidth - withinOffset;
1265
				if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {
1266
					position.left += myOffset + atOffset + offset;
1267
				}
1268
			} else if ( overRight > 0 ) {
1269
				newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + atOffset + offset - offsetLeft;
1270
				if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {
1271
					position.left += myOffset + atOffset + offset;
1272
				}
1273
			}
1274
		},
1275
		top: function( position, data ) {
1276
			var within = data.within,
1277
				withinOffset = within.offset.top + within.scrollTop,
1278
				outerHeight = within.height,
1279
				offsetTop = within.isWindow ? within.scrollTop : within.offset.top,
1280
				collisionPosTop = position.top - data.collisionPosition.marginTop,
1281
				overTop = collisionPosTop - offsetTop,
1282
				overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,
1283
				top = data.my[ 1 ] === "top",
1284
				myOffset = top ?
1285
					-data.elemHeight :
1286
					data.my[ 1 ] === "bottom" ?
1287
						data.elemHeight :
1288
						0,
1289
				atOffset = data.at[ 1 ] === "top" ?
1290
					data.targetHeight :
1291
					data.at[ 1 ] === "bottom" ?
1292
						-data.targetHeight :
1293
						0,
1294
				offset = -2 * data.offset[ 1 ],
1295
				newOverTop,
1296
				newOverBottom;
1297
			if ( overTop < 0 ) {
1298
				newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - outerHeight - withinOffset;
1299
				if ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) {
1300
					position.top += myOffset + atOffset + offset;
1301
				}
1302
			} else if ( overBottom > 0 ) {
1303
				newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset + offset - offsetTop;
1304
				if ( newOverTop > 0 || abs( newOverTop ) < overBottom ) {
1305
					position.top += myOffset + atOffset + offset;
1306
				}
1307
			}
1308
		}
1309
	},
1310
	flipfit: {
1311
		left: function() {
1312
			$.ui.position.flip.left.apply( this, arguments );
1313
			$.ui.position.fit.left.apply( this, arguments );
1314
		},
1315
		top: function() {
1316
			$.ui.position.flip.top.apply( this, arguments );
1317
			$.ui.position.fit.top.apply( this, arguments );
1318
		}
1319
	}
1320
};
1321
1322
// fraction support test
1323
(function() {
1324
	var testElement, testElementParent, testElementStyle, offsetLeft, i,
1325
		body = document.getElementsByTagName( "body" )[ 0 ],
1326
		div = document.createElement( "div" );
1327
1328
	//Create a "fake body" for testing based on method used in jQuery.support
1329
	testElement = document.createElement( body ? "div" : "body" );
1330
	testElementStyle = {
1331
		visibility: "hidden",
1332
		width: 0,
1333
		height: 0,
1334
		border: 0,
1335
		margin: 0,
1336
		background: "none"
1337
	};
1338
	if ( body ) {
1339
		$.extend( testElementStyle, {
1340
			position: "absolute",
1341
			left: "-1000px",
1342
			top: "-1000px"
1343
		});
1344
	}
1345
	for ( i in testElementStyle ) {
1346
		testElement.style[ i ] = testElementStyle[ i ];
1347
	}
1348
	testElement.appendChild( div );
1349
	testElementParent = body || document.documentElement;
1350
	testElementParent.insertBefore( testElement, testElementParent.firstChild );
1351
1352
	div.style.cssText = "position: absolute; left: 10.7432222px;";
1353
1354
	offsetLeft = $( div ).offset().left;
1355
	supportsOffsetFractions = offsetLeft > 10 && offsetLeft < 11;
1356
1357
	testElement.innerHTML = "";
1358
	testElementParent.removeChild( testElement );
1359
})();
1360
1361
})();
1362
1363
var position = $.ui.position;
1364
1365
1366
/*!
1367
 * jQuery UI Menu 1.11.4
1368
 * http://jqueryui.com
1369
 *
1370
 * Copyright jQuery Foundation and other contributors
1371
 * Released under the MIT license.
1372
 * http://jquery.org/license
1373
 *
1374
 * http://api.jqueryui.com/menu/
1375
 */
1376
1377
1378
var menu = $.widget( "ui.menu", {
1379
	version: "1.11.4",
1380
	defaultElement: "<ul>",
1381
	delay: 300,
1382
	options: {
1383
		icons: {
1384
			submenu: "ui-icon-carat-1-e"
1385
		},
1386
		items: "> *",
1387
		menus: "ul",
1388
		position: {
1389
			my: "left-1 top",
1390
			at: "right top"
1391
		},
1392
		role: "menu",
1393
1394
		// callbacks
1395
		blur: null,
1396
		focus: null,
1397
		select: null
1398
	},
1399
1400
	_create: function() {
1401
		this.activeMenu = this.element;
1402
1403
		// Flag used to prevent firing of the click handler
1404
		// as the event bubbles up through nested menus
1405
		this.mouseHandled = false;
1406
		this.element
1407
			.uniqueId()
1408
			.addClass( "ui-menu ui-widget ui-widget-content" )
1409
			.toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length )
1410
			.attr({
1411
				role: this.options.role,
1412
				tabIndex: 0
1413
			});
1414
1415
		if ( this.options.disabled ) {
1416
			this.element
1417
				.addClass( "ui-state-disabled" )
1418
				.attr( "aria-disabled", "true" );
1419
		}
1420
1421
		this._on({
1422
			// Prevent focus from sticking to links inside menu after clicking
1423
			// them (focus should always stay on UL during navigation).
1424
			"mousedown .ui-menu-item": function( event ) {
1425
				event.preventDefault();
1426
			},
1427
			"click .ui-menu-item": function( event ) {
1428
				var target = $( event.target );
1429
				if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) {
1430
					this.select( event );
1431
1432
					// Only set the mouseHandled flag if the event will bubble, see #9469.
1433
					if ( !event.isPropagationStopped() ) {
1434
						this.mouseHandled = true;
1435
					}
1436
1437
					// Open submenu on click
1438
					if ( target.has( ".ui-menu" ).length ) {
1439
						this.expand( event );
1440
					} else if ( !this.element.is( ":focus" ) && $( this.document[ 0 ].activeElement ).closest( ".ui-menu" ).length ) {
1441
1442
						// Redirect focus to the menu
1443
						this.element.trigger( "focus", [ true ] );
1444
1445
						// If the active item is on the top level, let it stay active.
1446
						// Otherwise, blur the active item since it is no longer visible.
1447
						if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) {
1448
							clearTimeout( this.timer );
1449
						}
1450
					}
1451
				}
1452
			},
1453
			"mouseenter .ui-menu-item": function( event ) {
1454
				// Ignore mouse events while typeahead is active, see #10458.
1455
				// Prevents focusing the wrong item when typeahead causes a scroll while the mouse
1456
				// is over an item in the menu
1457
				if ( this.previousFilter ) {
1458
					return;
1459
				}
1460
				var target = $( event.currentTarget );
1461
				// Remove ui-state-active class from siblings of the newly focused menu item
1462
				// to avoid a jump caused by adjacent elements both having a class with a border
1463
				target.siblings( ".ui-state-active" ).removeClass( "ui-state-active" );
1464
				this.focus( event, target );
1465
			},
1466
			mouseleave: "collapseAll",
1467
			"mouseleave .ui-menu": "collapseAll",
1468
			focus: function( event, keepActiveItem ) {
1469
				// If there's already an active item, keep it active
1470
				// If not, activate the first item
1471
				var item = this.active || this.element.find( this.options.items ).eq( 0 );
1472
1473
				if ( !keepActiveItem ) {
1474
					this.focus( event, item );
1475
				}
1476
			},
1477
			blur: function( event ) {
1478
				this._delay(function() {
1479
					if ( !$.contains( this.element[0], this.document[0].activeElement ) ) {
1480
						this.collapseAll( event );
1481
					}
1482
				});
1483
			},
1484
			keydown: "_keydown"
1485
		});
1486
1487
		this.refresh();
1488
1489
		// Clicks outside of a menu collapse any open menus
1490
		this._on( this.document, {
1491
			click: function( event ) {
1492
				if ( this._closeOnDocumentClick( event ) ) {
1493
					this.collapseAll( event );
1494
				}
1495
1496
				// Reset the mouseHandled flag
1497
				this.mouseHandled = false;
1498
			}
1499
		});
1500
	},
1501
1502
	_destroy: function() {
1503
		// Destroy (sub)menus
1504
		this.element
1505
			.removeAttr( "aria-activedescendant" )
1506
			.find( ".ui-menu" ).addBack()
1507
				.removeClass( "ui-menu ui-widget ui-widget-content ui-menu-icons ui-front" )
1508
				.removeAttr( "role" )
1509
				.removeAttr( "tabIndex" )
1510
				.removeAttr( "aria-labelledby" )
1511
				.removeAttr( "aria-expanded" )
1512
				.removeAttr( "aria-hidden" )
1513
				.removeAttr( "aria-disabled" )
1514
				.removeUniqueId()
1515
				.show();
1516
1517
		// Destroy menu items
1518
		this.element.find( ".ui-menu-item" )
1519
			.removeClass( "ui-menu-item" )
1520
			.removeAttr( "role" )
1521
			.removeAttr( "aria-disabled" )
1522
			.removeUniqueId()
1523
			.removeClass( "ui-state-hover" )
1524
			.removeAttr( "tabIndex" )
1525
			.removeAttr( "role" )
1526
			.removeAttr( "aria-haspopup" )
1527
			.children().each( function() {
1528
				var elem = $( this );
1529
				if ( elem.data( "ui-menu-submenu-carat" ) ) {
1530
					elem.remove();
1531
				}
1532
			});
1533
1534
		// Destroy menu dividers
1535
		this.element.find( ".ui-menu-divider" ).removeClass( "ui-menu-divider ui-widget-content" );
1536
	},
1537
1538
	_keydown: function( event ) {
1539
		var match, prev, character, skip,
1540
			preventDefault = true;
1541
1542
		switch ( event.keyCode ) {
1543
		case $.ui.keyCode.PAGE_UP:
1544
			this.previousPage( event );
1545
			break;
1546
		case $.ui.keyCode.PAGE_DOWN:
1547
			this.nextPage( event );
1548
			break;
1549
		case $.ui.keyCode.HOME:
1550
			this._move( "first", "first", event );
1551
			break;
1552
		case $.ui.keyCode.END:
1553
			this._move( "last", "last", event );
1554
			break;
1555
		case $.ui.keyCode.UP:
1556
			this.previous( event );
1557
			break;
1558
		case $.ui.keyCode.DOWN:
1559
			this.next( event );
1560
			break;
1561
		case $.ui.keyCode.LEFT:
1562
			this.collapse( event );
1563
			break;
1564
		case $.ui.keyCode.RIGHT:
1565
			if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
1566
				this.expand( event );
1567
			}
1568
			break;
1569
		case $.ui.keyCode.ENTER:
1570
		case $.ui.keyCode.SPACE:
1571
			this._activate( event );
1572
			break;
1573
		case $.ui.keyCode.ESCAPE:
1574
			this.collapse( event );
1575
			break;
1576
		default:
1577
			preventDefault = false;
1578
			prev = this.previousFilter || "";
1579
			character = String.fromCharCode( event.keyCode );
1580
			skip = false;
1581
1582
			clearTimeout( this.filterTimer );
1583
1584
			if ( character === prev ) {
1585
				skip = true;
1586
			} else {
1587
				character = prev + character;
1588
			}
1589
1590
			match = this._filterMenuItems( character );
1591
			match = skip && match.index( this.active.next() ) !== -1 ?
1592
				this.active.nextAll( ".ui-menu-item" ) :
1593
				match;
1594
1595
			// If no matches on the current filter, reset to the last character pressed
1596
			// to move down the menu to the first item that starts with that character
1597
			if ( !match.length ) {
1598
				character = String.fromCharCode( event.keyCode );
1599
				match = this._filterMenuItems( character );
1600
			}
1601
1602
			if ( match.length ) {
1603
				this.focus( event, match );
1604
				this.previousFilter = character;
1605
				this.filterTimer = this._delay(function() {
1606
					delete this.previousFilter;
1607
				}, 1000 );
1608
			} else {
1609
				delete this.previousFilter;
1610
			}
1611
		}
1612
1613
		if ( preventDefault ) {
1614
			event.preventDefault();
1615
		}
1616
	},
1617
1618
	_activate: function( event ) {
1619
		if ( !this.active.is( ".ui-state-disabled" ) ) {
1620
			if ( this.active.is( "[aria-haspopup='true']" ) ) {
1621
				this.expand( event );
1622
			} else {
1623
				this.select( event );
1624
			}
1625
		}
1626
	},
1627
1628
	refresh: function() {
1629
		var menus, items,
1630
			that = this,
1631
			icon = this.options.icons.submenu,
1632
			submenus = this.element.find( this.options.menus );
1633
1634
		this.element.toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length );
1635
1636
		// Initialize nested menus
1637
		submenus.filter( ":not(.ui-menu)" )
1638
			.addClass( "ui-menu ui-widget ui-widget-content ui-front" )
1639
			.hide()
1640
			.attr({
1641
				role: this.options.role,
1642
				"aria-hidden": "true",
1643
				"aria-expanded": "false"
1644
			})
1645
			.each(function() {
1646
				var menu = $( this ),
1647
					item = menu.parent(),
1648
					submenuCarat = $( "<span>" )
1649
						.addClass( "ui-menu-icon ui-icon " + icon )
1650
						.data( "ui-menu-submenu-carat", true );
1651
1652
				item
1653
					.attr( "aria-haspopup", "true" )
1654
					.prepend( submenuCarat );
1655
				menu.attr( "aria-labelledby", item.attr( "id" ) );
1656
			});
1657
1658
		menus = submenus.add( this.element );
1659
		items = menus.find( this.options.items );
1660
1661
		// Initialize menu-items containing spaces and/or dashes only as dividers
1662
		items.not( ".ui-menu-item" ).each(function() {
1663
			var item = $( this );
1664
			if ( that._isDivider( item ) ) {
1665
				item.addClass( "ui-widget-content ui-menu-divider" );
1666
			}
1667
		});
1668
1669
		// Don't refresh list items that are already adapted
1670
		items.not( ".ui-menu-item, .ui-menu-divider" )
1671
			.addClass( "ui-menu-item" )
1672
			.uniqueId()
1673
			.attr({
1674
				tabIndex: -1,
1675
				role: this._itemRole()
1676
			});
1677
1678
		// Add aria-disabled attribute to any disabled menu item
1679
		items.filter( ".ui-state-disabled" ).attr( "aria-disabled", "true" );
1680
1681
		// If the active item has been removed, blur the menu
1682
		if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
1683
			this.blur();
1684
		}
1685
	},
1686
1687
	_itemRole: function() {
1688
		return {
1689
			menu: "menuitem",
1690
			listbox: "option"
1691
		}[ this.options.role ];
1692
	},
1693
1694
	_setOption: function( key, value ) {
1695
		if ( key === "icons" ) {
1696
			this.element.find( ".ui-menu-icon" )
1697
				.removeClass( this.options.icons.submenu )
1698
				.addClass( value.submenu );
1699
		}
1700
		if ( key === "disabled" ) {
1701
			this.element
1702
				.toggleClass( "ui-state-disabled", !!value )
1703
				.attr( "aria-disabled", value );
1704
		}
1705
		this._super( key, value );
1706
	},
1707
1708
	focus: function( event, item ) {
1709
		var nested, focused;
1710
		this.blur( event, event && event.type === "focus" );
1711
1712
		this._scrollIntoView( item );
1713
1714
		this.active = item.first();
1715
		focused = this.active.addClass( "ui-state-focus" ).removeClass( "ui-state-active" );
1716
		// Only update aria-activedescendant if there's a role
1717
		// otherwise we assume focus is managed elsewhere
1718
		if ( this.options.role ) {
1719
			this.element.attr( "aria-activedescendant", focused.attr( "id" ) );
1720
		}
1721
1722
		// Highlight active parent menu item, if any
1723
		this.active
1724
			.parent()
1725
			.closest( ".ui-menu-item" )
1726
			.addClass( "ui-state-active" );
1727
1728
		if ( event && event.type === "keydown" ) {
1729
			this._close();
1730
		} else {
1731
			this.timer = this._delay(function() {
1732
				this._close();
1733
			}, this.delay );
1734
		}
1735
1736
		nested = item.children( ".ui-menu" );
1737
		if ( nested.length && event && ( /^mouse/.test( event.type ) ) ) {
1738
			this._startOpening(nested);
1739
		}
1740
		this.activeMenu = item.parent();
1741
1742
		this._trigger( "focus", event, { item: item } );
1743
	},
1744
1745
	_scrollIntoView: function( item ) {
1746
		var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight;
1747
		if ( this._hasScroll() ) {
1748
			borderTop = parseFloat( $.css( this.activeMenu[0], "borderTopWidth" ) ) || 0;
1749
			paddingTop = parseFloat( $.css( this.activeMenu[0], "paddingTop" ) ) || 0;
1750
			offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop;
1751
			scroll = this.activeMenu.scrollTop();
1752
			elementHeight = this.activeMenu.height();
1753
			itemHeight = item.outerHeight();
1754
1755
			if ( offset < 0 ) {
1756
				this.activeMenu.scrollTop( scroll + offset );
1757
			} else if ( offset + itemHeight > elementHeight ) {
1758
				this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight );
1759
			}
1760
		}
1761
	},
1762
1763
	blur: function( event, fromFocus ) {
1764
		if ( !fromFocus ) {
1765
			clearTimeout( this.timer );
1766
		}
1767
1768
		if ( !this.active ) {
1769
			return;
1770
		}
1771
1772
		this.active.removeClass( "ui-state-focus" );
1773
		this.active = null;
1774
1775
		this._trigger( "blur", event, { item: this.active } );
1776
	},
1777
1778
	_startOpening: function( submenu ) {
1779
		clearTimeout( this.timer );
1780
1781
		// Don't open if already open fixes a Firefox bug that caused a .5 pixel
1782
		// shift in the submenu position when mousing over the carat icon
1783
		if ( submenu.attr( "aria-hidden" ) !== "true" ) {
1784
			return;
1785
		}
1786
1787
		this.timer = this._delay(function() {
1788
			this._close();
1789
			this._open( submenu );
1790
		}, this.delay );
1791
	},
1792
1793
	_open: function( submenu ) {
1794
		var position = $.extend({
1795
			of: this.active
1796
		}, this.options.position );
1797
1798
		clearTimeout( this.timer );
1799
		this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) )
1800
			.hide()
1801
			.attr( "aria-hidden", "true" );
1802
1803
		submenu
1804
			.show()
1805
			.removeAttr( "aria-hidden" )
1806
			.attr( "aria-expanded", "true" )
1807
			.position( position );
1808
	},
1809
1810
	collapseAll: function( event, all ) {
1811
		clearTimeout( this.timer );
1812
		this.timer = this._delay(function() {
1813
			// If we were passed an event, look for the submenu that contains the event
1814
			var currentMenu = all ? this.element :
1815
				$( event && event.target ).closest( this.element.find( ".ui-menu" ) );
1816
1817
			// If we found no valid submenu ancestor, use the main menu to close all sub menus anyway
1818
			if ( !currentMenu.length ) {
1819
				currentMenu = this.element;
1820
			}
1821
1822
			this._close( currentMenu );
1823
1824
			this.blur( event );
1825
			this.activeMenu = currentMenu;
1826
		}, this.delay );
1827
	},
1828
1829
	// With no arguments, closes the currently active menu - if nothing is active
1830
	// it closes all menus.  If passed an argument, it will search for menus BELOW
1831
	_close: function( startMenu ) {
1832
		if ( !startMenu ) {
1833
			startMenu = this.active ? this.active.parent() : this.element;
1834
		}
1835
1836
		startMenu
1837
			.find( ".ui-menu" )
1838
				.hide()
1839
				.attr( "aria-hidden", "true" )
1840
				.attr( "aria-expanded", "false" )
1841
			.end()
1842
			.find( ".ui-state-active" ).not( ".ui-state-focus" )
1843
				.removeClass( "ui-state-active" );
1844
	},
1845
1846
	_closeOnDocumentClick: function( event ) {
1847
		return !$( event.target ).closest( ".ui-menu" ).length;
1848
	},
1849
1850
	_isDivider: function( item ) {
1851
1852
		// Match hyphen, em dash, en dash
1853
		return !/[^\-\u2014\u2013\s]/.test( item.text() );
1854
	},
1855
1856
	collapse: function( event ) {
1857
		var newItem = this.active &&
1858
			this.active.parent().closest( ".ui-menu-item", this.element );
1859
		if ( newItem && newItem.length ) {
1860
			this._close();
1861
			this.focus( event, newItem );
1862
		}
1863
	},
1864
1865
	expand: function( event ) {
1866
		var newItem = this.active &&
1867
			this.active
1868
				.children( ".ui-menu " )
1869
				.find( this.options.items )
1870
				.first();
1871
1872
		if ( newItem && newItem.length ) {
1873
			this._open( newItem.parent() );
1874
1875
			// Delay so Firefox will not hide activedescendant change in expanding submenu from AT
1876
			this._delay(function() {
1877
				this.focus( event, newItem );
1878
			});
1879
		}
1880
	},
1881
1882
	next: function( event ) {
1883
		this._move( "next", "first", event );
1884
	},
1885
1886
	previous: function( event ) {
1887
		this._move( "prev", "last", event );
1888
	},
1889
1890
	isFirstItem: function() {
1891
		return this.active && !this.active.prevAll( ".ui-menu-item" ).length;
1892
	},
1893
1894
	isLastItem: function() {
1895
		return this.active && !this.active.nextAll( ".ui-menu-item" ).length;
1896
	},
1897
1898
	_move: function( direction, filter, event ) {
1899
		var next;
1900
		if ( this.active ) {
1901
			if ( direction === "first" || direction === "last" ) {
1902
				next = this.active
1903
					[ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" )
1904
					.eq( -1 );
1905
			} else {
1906
				next = this.active
1907
					[ direction + "All" ]( ".ui-menu-item" )
1908
					.eq( 0 );
1909
			}
1910
		}
1911
		if ( !next || !next.length || !this.active ) {
1912
			next = this.activeMenu.find( this.options.items )[ filter ]();
1913
		}
1914
1915
		this.focus( event, next );
1916
	},
1917
1918
	nextPage: function( event ) {
1919
		var item, base, height;
1920
1921
		if ( !this.active ) {
1922
			this.next( event );
1923
			return;
1924
		}
1925
		if ( this.isLastItem() ) {
1926
			return;
1927
		}
1928
		if ( this._hasScroll() ) {
1929
			base = this.active.offset().top;
1930
			height = this.element.height();
1931
			this.active.nextAll( ".ui-menu-item" ).each(function() {
1932
				item = $( this );
1933
				return item.offset().top - base - height < 0;
1934
			});
1935
1936
			this.focus( event, item );
1937
		} else {
1938
			this.focus( event, this.activeMenu.find( this.options.items )
1939
				[ !this.active ? "first" : "last" ]() );
1940
		}
1941
	},
1942
1943
	previousPage: function( event ) {
1944
		var item, base, height;
1945
		if ( !this.active ) {
1946
			this.next( event );
1947
			return;
1948
		}
1949
		if ( this.isFirstItem() ) {
1950
			return;
1951
		}
1952
		if ( this._hasScroll() ) {
1953
			base = this.active.offset().top;
1954
			height = this.element.height();
1955
			this.active.prevAll( ".ui-menu-item" ).each(function() {
1956
				item = $( this );
1957
				return item.offset().top - base + height > 0;
1958
			});
1959
1960
			this.focus( event, item );
1961
		} else {
1962
			this.focus( event, this.activeMenu.find( this.options.items ).first() );
1963
		}
1964
	},
1965
1966
	_hasScroll: function() {
1967
		return this.element.outerHeight() < this.element.prop( "scrollHeight" );
1968
	},
1969
1970
	select: function( event ) {
1971
		// TODO: It should never be possible to not have an active item at this
1972
		// point, but the tests don't trigger mouseenter before click.
1973
		this.active = this.active || $( event.target ).closest( ".ui-menu-item" );
1974
		var ui = { item: this.active };
1975
		if ( !this.active.has( ".ui-menu" ).length ) {
1976
			this.collapseAll( event, true );
1977
		}
1978
		this._trigger( "select", event, ui );
1979
	},
1980
1981
	_filterMenuItems: function(character) {
1982
		var escapedCharacter = character.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ),
1983
			regex = new RegExp( "^" + escapedCharacter, "i" );
1984
1985
		return this.activeMenu
1986
			.find( this.options.items )
1987
1988
			// Only match on items, not dividers or other content (#10571)
1989
			.filter( ".ui-menu-item" )
1990
			.filter(function() {
1991
				return regex.test( $.trim( $( this ).text() ) );
1992
			});
1993
	}
1994
});
1995
1996
1997
/*!
1998
 * jQuery UI Autocomplete 1.11.4
1999
 * http://jqueryui.com
2000
 *
2001
 * Copyright jQuery Foundation and other contributors
2002
 * Released under the MIT license.
2003
 * http://jquery.org/license
2004
 *
2005
 * http://api.jqueryui.com/autocomplete/
2006
 */
2007
2008
2009
$.widget( "ui.autocomplete", {
2010
	version: "1.11.4",
2011
	defaultElement: "<input>",
2012
	options: {
2013
		appendTo: null,
2014
		autoFocus: false,
2015
		delay: 300,
2016
		minLength: 1,
2017
		position: {
2018
			my: "left top",
2019
			at: "left bottom",
2020
			collision: "none"
2021
		},
2022
		source: null,
2023
2024
		// callbacks
2025
		change: null,
2026
		close: null,
2027
		focus: null,
2028
		open: null,
2029
		response: null,
2030
		search: null,
2031
		select: null
2032
	},
2033
2034
	requestIndex: 0,
2035
	pending: 0,
2036
2037
	_create: function() {
2038
		// Some browsers only repeat keydown events, not keypress events,
2039
		// so we use the suppressKeyPress flag to determine if we've already
2040
		// handled the keydown event. #7269
2041
		// Unfortunately the code for & in keypress is the same as the up arrow,
2042
		// so we use the suppressKeyPressRepeat flag to avoid handling keypress
2043
		// events when we know the keydown event was used to modify the
2044
		// search term. #7799
2045
		var suppressKeyPress, suppressKeyPressRepeat, suppressInput,
2046
			nodeName = this.element[ 0 ].nodeName.toLowerCase(),
2047
			isTextarea = nodeName === "textarea",
2048
			isInput = nodeName === "input";
2049
2050
		this.isMultiLine =
2051
			// Textareas are always multi-line
2052
			isTextarea ? true :
2053
			// Inputs are always single-line, even if inside a contentEditable element
2054
			// IE also treats inputs as contentEditable
2055
			isInput ? false :
2056
			// All other element types are determined by whether or not they're contentEditable
2057
			this.element.prop( "isContentEditable" );
2058
2059
		this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ];
2060
		this.isNewMenu = true;
2061
2062
		this.element
2063
			.addClass( "ui-autocomplete-input" )
2064
			.attr( "autocomplete", "off" );
2065
2066
		this._on( this.element, {
2067
			keydown: function( event ) {
2068
				if ( this.element.prop( "readOnly" ) ) {
2069
					suppressKeyPress = true;
2070
					suppressInput = true;
2071
					suppressKeyPressRepeat = true;
2072
					return;
2073
				}
2074
2075
				suppressKeyPress = false;
2076
				suppressInput = false;
2077
				suppressKeyPressRepeat = false;
2078
				var keyCode = $.ui.keyCode;
2079
				switch ( event.keyCode ) {
2080
				case keyCode.PAGE_UP:
2081
					suppressKeyPress = true;
2082
					this._move( "previousPage", event );
2083
					break;
2084
				case keyCode.PAGE_DOWN:
2085
					suppressKeyPress = true;
2086
					this._move( "nextPage", event );
2087
					break;
2088
				case keyCode.UP:
2089
					suppressKeyPress = true;
2090
					this._keyEvent( "previous", event );
2091
					break;
2092
				case keyCode.DOWN:
2093
					suppressKeyPress = true;
2094
					this._keyEvent( "next", event );
2095
					break;
2096
				case keyCode.ENTER:
2097
					// when menu is open and has focus
2098
					if ( this.menu.active ) {
2099
						// #6055 - Opera still allows the keypress to occur
2100
						// which causes forms to submit
2101
						suppressKeyPress = true;
2102
						event.preventDefault();
2103
						this.menu.select( event );
2104
					}
2105
					break;
2106
				case keyCode.TAB:
2107
					if ( this.menu.active ) {
2108
						this.menu.select( event );
2109
					}
2110
					break;
2111
				case keyCode.ESCAPE:
2112
					if ( this.menu.element.is( ":visible" ) ) {
2113
						if ( !this.isMultiLine ) {
2114
							this._value( this.term );
2115
						}
2116
						this.close( event );
2117
						// Different browsers have different default behavior for escape
2118
						// Single press can mean undo or clear
2119
						// Double press in IE means clear the whole form
2120
						event.preventDefault();
2121
					}
2122
					break;
2123
				default:
2124
					suppressKeyPressRepeat = true;
2125
					// search timeout should be triggered before the input value is changed
2126
					this._searchTimeout( event );
2127
					break;
2128
				}
2129
			},
2130
			keypress: function( event ) {
2131
				if ( suppressKeyPress ) {
2132
					suppressKeyPress = false;
2133
					if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
2134
						event.preventDefault();
2135
					}
2136
					return;
2137
				}
2138
				if ( suppressKeyPressRepeat ) {
2139
					return;
2140
				}
2141
2142
				// replicate some key handlers to allow them to repeat in Firefox and Opera
2143
				var keyCode = $.ui.keyCode;
2144
				switch ( event.keyCode ) {
2145
				case keyCode.PAGE_UP:
2146
					this._move( "previousPage", event );
2147
					break;
2148
				case keyCode.PAGE_DOWN:
2149
					this._move( "nextPage", event );
2150
					break;
2151
				case keyCode.UP:
2152
					this._keyEvent( "previous", event );
2153
					break;
2154
				case keyCode.DOWN:
2155
					this._keyEvent( "next", event );
2156
					break;
2157
				}
2158
			},
2159
			input: function( event ) {
2160
				if ( suppressInput ) {
2161
					suppressInput = false;
2162
					event.preventDefault();
2163
					return;
2164
				}
2165
				this._searchTimeout( event );
2166
			},
2167
			focus: function() {
2168
				this.selectedItem = null;
2169
				this.previous = this._value();
2170
			},
2171
			blur: function( event ) {
2172
				if ( this.cancelBlur ) {
2173
					delete this.cancelBlur;
2174
					return;
2175
				}
2176
2177
				clearTimeout( this.searching );
2178
				this.close( event );
2179
				this._change( event );
2180
			}
2181
		});
2182
2183
		this._initSource();
2184
		this.menu = $( "<ul>" )
2185
			.addClass( "ui-autocomplete ui-front" )
2186
			.appendTo( this._appendTo() )
2187
			.menu({
2188
				// disable ARIA support, the live region takes care of that
2189
				role: null
2190
			})
2191
			.hide()
2192
			.menu( "instance" );
2193
2194
		this._on( this.menu.element, {
2195
			mousedown: function( event ) {
2196
				// prevent moving focus out of the text field
2197
				event.preventDefault();
2198
2199
				// IE doesn't prevent moving focus even with event.preventDefault()
2200
				// so we set a flag to know when we should ignore the blur event
2201
				this.cancelBlur = true;
2202
				this._delay(function() {
2203
					delete this.cancelBlur;
2204
				});
2205
2206
				// clicking on the scrollbar causes focus to shift to the body
2207
				// but we can't detect a mouseup or a click immediately afterward
2208
				// so we have to track the next mousedown and close the menu if
2209
				// the user clicks somewhere outside of the autocomplete
2210
				var menuElement = this.menu.element[ 0 ];
2211
				if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
2212
					this._delay(function() {
2213
						var that = this;
2214
						this.document.one( "mousedown", function( event ) {
2215
							if ( event.target !== that.element[ 0 ] &&
2216
									event.target !== menuElement &&
2217
									!$.contains( menuElement, event.target ) ) {
2218
								that.close();
2219
							}
2220
						});
2221
					});
2222
				}
2223
			},
2224
			menufocus: function( event, ui ) {
2225
				var label, item;
2226
				// support: Firefox
2227
				// Prevent accidental activation of menu items in Firefox (#7024 #9118)
2228
				if ( this.isNewMenu ) {
2229
					this.isNewMenu = false;
2230
					if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) {
2231
						this.menu.blur();
2232
2233
						this.document.one( "mousemove", function() {
2234
							$( event.target ).trigger( event.originalEvent );
2235
						});
2236
2237
						return;
2238
					}
2239
				}
2240
2241
				item = ui.item.data( "ui-autocomplete-item" );
2242
				if ( false !== this._trigger( "focus", event, { item: item } ) ) {
2243
					// use value to match what will end up in the input, if it was a key event
2244
					if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) {
2245
						this._value( item.value );
2246
					}
2247
				}
2248
2249
				// Announce the value in the liveRegion
2250
				label = ui.item.attr( "aria-label" ) || item.value;
2251
				if ( label && $.trim( label ).length ) {
2252
					this.liveRegion.children().hide();
2253
					$( "<div>" ).text( label ).appendTo( this.liveRegion );
2254
				}
2255
			},
2256
			menuselect: function( event, ui ) {
2257
				var item = ui.item.data( "ui-autocomplete-item" ),
2258
					previous = this.previous;
2259
2260
				// only trigger when focus was lost (click on menu)
2261
				if ( this.element[ 0 ] !== this.document[ 0 ].activeElement ) {
2262
					this.element.focus();
2263
					this.previous = previous;
2264
					// #6109 - IE triggers two focus events and the second
2265
					// is asynchronous, so we need to reset the previous
2266
					// term synchronously and asynchronously :-(
2267
					this._delay(function() {
2268
						this.previous = previous;
2269
						this.selectedItem = item;
2270
					});
2271
				}
2272
2273
				if ( false !== this._trigger( "select", event, { item: item } ) ) {
2274
					this._value( item.value );
2275
				}
2276
				// reset the term after the select event
2277
				// this allows custom select handling to work properly
2278
				this.term = this._value();
2279
2280
				this.close( event );
2281
				this.selectedItem = item;
2282
			}
2283
		});
2284
2285
		this.liveRegion = $( "<span>", {
2286
				role: "status",
2287
				"aria-live": "assertive",
2288
				"aria-relevant": "additions"
2289
			})
2290
			.addClass( "ui-helper-hidden-accessible" )
2291
			.appendTo( this.document[ 0 ].body );
2292
2293
		// turning off autocomplete prevents the browser from remembering the
2294
		// value when navigating through history, so we re-enable autocomplete
2295
		// if the page is unloaded before the widget is destroyed. #7790
2296
		this._on( this.window, {
2297
			beforeunload: function() {
2298
				this.element.removeAttr( "autocomplete" );
2299
			}
2300
		});
2301
	},
2302
2303
	_destroy: function() {
2304
		clearTimeout( this.searching );
2305
		this.element
2306
			.removeClass( "ui-autocomplete-input" )
2307
			.removeAttr( "autocomplete" );
2308
		this.menu.element.remove();
2309
		this.liveRegion.remove();
2310
	},
2311
2312
	_setOption: function( key, value ) {
2313
		this._super( key, value );
2314
		if ( key === "source" ) {
2315
			this._initSource();
2316
		}
2317
		if ( key === "appendTo" ) {
2318
			this.menu.element.appendTo( this._appendTo() );
2319
		}
2320
		if ( key === "disabled" && value && this.xhr ) {
2321
			this.xhr.abort();
2322
		}
2323
	},
2324
2325
	_appendTo: function() {
2326
		var element = this.options.appendTo;
2327
2328
		if ( element ) {
2329
			element = element.jquery || element.nodeType ?
2330
				$( element ) :
2331
				this.document.find( element ).eq( 0 );
2332
		}
2333
2334
		if ( !element || !element[ 0 ] ) {
2335
			element = this.element.closest( ".ui-front" );
2336
		}
2337
2338
		if ( !element.length ) {
2339
			element = this.document[ 0 ].body;
2340
		}
2341
2342
		return element;
2343
	},
2344
2345
	_initSource: function() {
2346
		var array, url,
2347
			that = this;
2348
		if ( $.isArray( this.options.source ) ) {
2349
			array = this.options.source;
2350
			this.source = function( request, response ) {
2351
				response( $.ui.autocomplete.filter( array, request.term ) );
2352
			};
2353
		} else if ( typeof this.options.source === "string" ) {
2354
			url = this.options.source;
2355
			this.source = function( request, response ) {
2356
				if ( that.xhr ) {
2357
					that.xhr.abort();
2358
				}
2359
				that.xhr = $.ajax({
2360
					url: url,
2361
					data: request,
2362
					dataType: "json",
2363
					success: function( data ) {
2364
						response( data );
2365
					},
2366
					error: function() {
2367
						response([]);
2368
					}
2369
				});
2370
			};
2371
		} else {
2372
			this.source = this.options.source;
2373
		}
2374
	},
2375
2376
	_searchTimeout: function( event ) {
2377
		clearTimeout( this.searching );
2378
		this.searching = this._delay(function() {
2379
2380
			// Search if the value has changed, or if the user retypes the same value (see #7434)
2381
			var equalValues = this.term === this._value(),
2382
				menuVisible = this.menu.element.is( ":visible" ),
2383
				modifierKey = event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;
2384
2385
			if ( !equalValues || ( equalValues && !menuVisible && !modifierKey ) ) {
2386
				this.selectedItem = null;
2387
				this.search( null, event );
2388
			}
2389
		}, this.options.delay );
2390
	},
2391
2392
	search: function( value, event ) {
2393
		value = value != null ? value : this._value();
0 ignored issues
show
Comparing value to null using the != operator is not safe. Consider using !== instead.
Loading history...
2394
2395
		// always save the actual value, not the one passed as an argument
2396
		this.term = this._value();
2397
2398
		if ( value.length < this.options.minLength ) {
2399
			return this.close( event );
2400
		}
2401
2402
		if ( this._trigger( "search", event ) === false ) {
2403
			return;
0 ignored issues
show
Comprehensibility Best Practice introduced by
Are you sure this return statement is not missing an argument? If this is intended, consider adding an explicit undefined like return undefined;.
Loading history...
2404
		}
2405
2406
		return this._search( value );
2407
	},
2408
2409
	_search: function( value ) {
2410
		this.pending++;
2411
		this.element.addClass( "ui-autocomplete-loading" );
2412
		this.cancelSearch = false;
2413
2414
		this.source( { term: value }, this._response() );
2415
	},
2416
2417
	_response: function() {
2418
		var index = ++this.requestIndex;
2419
2420
		return $.proxy(function( content ) {
2421
			if ( index === this.requestIndex ) {
2422
				this.__response( content );
2423
			}
2424
2425
			this.pending--;
2426
			if ( !this.pending ) {
2427
				this.element.removeClass( "ui-autocomplete-loading" );
2428
			}
2429
		}, this );
2430
	},
2431
2432
	__response: function( content ) {
2433
		if ( content ) {
2434
			content = this._normalize( content );
2435
		}
2436
		this._trigger( "response", null, { content: content } );
2437
		if ( !this.options.disabled && content && content.length && !this.cancelSearch ) {
2438
			this._suggest( content );
2439
			this._trigger( "open" );
2440
		} else {
2441
			// use ._close() instead of .close() so we don't cancel future searches
2442
			this._close();
2443
		}
2444
	},
2445
2446
	close: function( event ) {
2447
		this.cancelSearch = true;
2448
		this._close( event );
2449
	},
2450
2451
	_close: function( event ) {
2452
		if ( this.menu.element.is( ":visible" ) ) {
2453
			this.menu.element.hide();
2454
			this.menu.blur();
2455
			this.isNewMenu = true;
2456
			this._trigger( "close", event );
2457
		}
2458
	},
2459
2460
	_change: function( event ) {
2461
		if ( this.previous !== this._value() ) {
2462
			this._trigger( "change", event, { item: this.selectedItem } );
2463
		}
2464
	},
2465
2466
	_normalize: function( items ) {
2467
		// assume all items have the right format when the first item is complete
2468
		if ( items.length && items[ 0 ].label && items[ 0 ].value ) {
2469
			return items;
2470
		}
2471
		return $.map( items, function( item ) {
2472
			if ( typeof item === "string" ) {
2473
				return {
2474
					label: item,
2475
					value: item
2476
				};
2477
			}
2478
			return $.extend( {}, item, {
2479
				label: item.label || item.value,
2480
				value: item.value || item.label
2481
			});
2482
		});
2483
	},
2484
2485
	_suggest: function( items ) {
2486
		var ul = this.menu.element.empty();
2487
		this._renderMenu( ul, items );
2488
		this.isNewMenu = true;
2489
		this.menu.refresh();
2490
2491
		// size and position menu
2492
		ul.show();
2493
		this._resizeMenu();
2494
		ul.position( $.extend({
2495
			of: this.element
2496
		}, this.options.position ) );
2497
2498
		if ( this.options.autoFocus ) {
2499
			this.menu.next();
2500
		}
2501
	},
2502
2503
	_resizeMenu: function() {
2504
		var ul = this.menu.element;
2505
		ul.outerWidth( Math.max(
2506
			// Firefox wraps long text (possibly a rounding bug)
2507
			// so we add 1px to avoid the wrapping (#7513)
2508
			ul.width( "" ).outerWidth() + 1,
2509
			this.element.outerWidth()
2510
		) );
2511
	},
2512
2513
	_renderMenu: function( ul, items ) {
2514
		var that = this;
2515
		$.each( items, function( index, item ) {
2516
			that._renderItemData( ul, item );
2517
		});
2518
	},
2519
2520
	_renderItemData: function( ul, item ) {
2521
		return this._renderItem( ul, item ).data( "ui-autocomplete-item", item );
2522
	},
2523
2524
	_renderItem: function( ul, item ) {
2525
		return $( "<li>" ).text( item.label ).appendTo( ul );
2526
	},
2527
2528
	_move: function( direction, event ) {
2529
		if ( !this.menu.element.is( ":visible" ) ) {
2530
			this.search( null, event );
2531
			return;
2532
		}
2533
		if ( this.menu.isFirstItem() && /^previous/.test( direction ) ||
2534
				this.menu.isLastItem() && /^next/.test( direction ) ) {
2535
2536
			if ( !this.isMultiLine ) {
2537
				this._value( this.term );
2538
			}
2539
2540
			this.menu.blur();
2541
			return;
2542
		}
2543
		this.menu[ direction ]( event );
2544
	},
2545
2546
	widget: function() {
2547
		return this.menu.element;
2548
	},
2549
2550
	_value: function() {
2551
		return this.valueMethod.apply( this.element, arguments );
2552
	},
2553
2554
	_keyEvent: function( keyEvent, event ) {
2555
		if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
2556
			this._move( keyEvent, event );
2557
2558
			// prevents moving cursor to beginning/end of the text field in some browsers
2559
			event.preventDefault();
2560
		}
2561
	}
2562
});
2563
2564
$.extend( $.ui.autocomplete, {
2565
	escapeRegex: function( value ) {
2566
		return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" );
2567
	},
2568
	filter: function( array, term ) {
2569
		var matcher = new RegExp( $.ui.autocomplete.escapeRegex( term ), "i" );
2570
		return $.grep( array, function( value ) {
2571
			return matcher.test( value.label || value.value || value );
2572
		});
2573
	}
2574
});
2575
2576
// live region extension, adding a `messages` option
2577
// NOTE: This is an experimental API. We are still investigating
2578
// a full solution for string manipulation and internationalization.
2579
$.widget( "ui.autocomplete", $.ui.autocomplete, {
2580
	options: {
2581
		messages: {
2582
			noResults: "No search results.",
2583
			results: function( amount ) {
2584
				return amount + ( amount > 1 ? " results are" : " result is" ) +
2585
					" available, use up and down arrow keys to navigate.";
2586
			}
2587
		}
2588
	},
2589
2590
	__response: function( content ) {
2591
		var message;
2592
		this._superApply( arguments );
2593
		if ( this.options.disabled || this.cancelSearch ) {
2594
			return;
2595
		}
2596
		if ( content && content.length ) {
2597
			message = this.options.messages.results( content.length );
2598
		} else {
2599
			message = this.options.messages.noResults;
2600
		}
2601
		this.liveRegion.children().hide();
2602
		$( "<div>" ).text( message ).appendTo( this.liveRegion );
2603
	}
2604
});
2605
2606
var autocomplete = $.ui.autocomplete;
2607
2608
2609
2610
}));