Issues (619)

js/jquery-ui.js (11 issues)

1
/*! jQuery UI - v1.10.3 - 2013-05-03
2
* http://jqueryui.com
3
* Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.draggable.js, jquery.ui.droppable.js, jquery.ui.resizable.js, jquery.ui.selectable.js, jquery.ui.sortable.js, jquery.ui.effect.js, jquery.ui.accordion.js, jquery.ui.autocomplete.js, jquery.ui.button.js, jquery.ui.datepicker.js, jquery.ui.dialog.js, jquery.ui.effect-blind.js, jquery.ui.effect-bounce.js, jquery.ui.effect-clip.js, jquery.ui.effect-drop.js, jquery.ui.effect-explode.js, jquery.ui.effect-fade.js, jquery.ui.effect-fold.js, jquery.ui.effect-highlight.js, jquery.ui.effect-pulsate.js, jquery.ui.effect-scale.js, jquery.ui.effect-shake.js, jquery.ui.effect-slide.js, jquery.ui.effect-transfer.js, jquery.ui.menu.js, jquery.ui.position.js, jquery.ui.progressbar.js, jquery.ui.slider.js, jquery.ui.spinner.js, jquery.ui.tabs.js, jquery.ui.tooltip.js
4
* Copyright 2013 jQuery Foundation and other contributors; Licensed MIT */
5
(function( $, undefined ) {
6
7
var uuid = 0,
8
	runiqueId = /^ui-id-\d+$/;
9
10
// $.ui might exist from components with no dependencies, e.g., $.ui.position
11
$.ui = $.ui || {};
12
13
$.extend( $.ui, {
14
	version: "1.10.3",
15
16
	keyCode: {
17
		BACKSPACE: 8,
18
		COMMA: 188,
19
		DELETE: 46,
20
		DOWN: 40,
21
		END: 35,
22
		ENTER: 13,
23
		ESCAPE: 27,
24
		HOME: 36,
25
		LEFT: 37,
26
		NUMPAD_ADD: 107,
27
		NUMPAD_DECIMAL: 110,
28
		NUMPAD_DIVIDE: 111,
29
		NUMPAD_ENTER: 108,
30
		NUMPAD_MULTIPLY: 106,
31
		NUMPAD_SUBTRACT: 109,
32
		PAGE_DOWN: 34,
33
		PAGE_UP: 33,
34
		PERIOD: 190,
35
		RIGHT: 39,
36
		SPACE: 32,
37
		TAB: 9,
38
		UP: 38
39
	}
40
});
41
42
// plugins
43
$.fn.extend({
44
	focus: (function( orig ) {
45
		return function( delay, fn ) {
46
			return typeof delay === "number" ?
47
				this.each(function() {
48
					var elem = this;
49
					setTimeout(function() {
50
						$( elem ).focus();
51
						if ( fn ) {
52
							fn.call( elem );
53
						}
54
					}, delay );
55
				}) :
56
				orig.apply( this, arguments );
57
		};
58
	})( $.fn.focus ),
59
60
	scrollParent: function() {
61
		var scrollParent;
62
		if (($.ui.ie && (/(static|relative)/).test(this.css("position"))) || (/absolute/).test(this.css("position"))) {
63
			scrollParent = this.parents().filter(function() {
64
				return (/(relative|absolute|fixed)/).test($.css(this,"position")) && (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x"));
65
			}).eq(0);
66
		} else {
67
			scrollParent = this.parents().filter(function() {
68
				return (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x"));
69
			}).eq(0);
70
		}
71
72
		return (/fixed/).test(this.css("position")) || !scrollParent.length ? $(document) : scrollParent;
73
	},
74
75
	zIndex: function( zIndex ) {
76
		if ( zIndex !== undefined ) {
77
			return this.css( "zIndex", zIndex );
78
		}
79
80
		if ( this.length ) {
81
			var elem = $( this[ 0 ] ), position, value;
82
			while ( elem.length && elem[ 0 ] !== document ) {
83
				// Ignore z-index if position is set to a value where z-index is ignored by the browser
84
				// This makes behavior of this function consistent across browsers
85
				// WebKit always returns auto if the element is positioned
86
				position = elem.css( "position" );
87
				if ( position === "absolute" || position === "relative" || position === "fixed" ) {
88
					// IE returns 0 when zIndex is not specified
89
					// other browsers return a string
90
					// we ignore the case of nested elements with an explicit value of 0
91
					// <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
92
					value = parseInt( elem.css( "zIndex" ), 10 );
93
					if ( !isNaN( value ) && value !== 0 ) {
94
						return value;
95
					}
96
				}
97
				elem = elem.parent();
98
			}
99
		}
100
101
		return 0;
102
	},
103
104
	uniqueId: function() {
105
		return this.each(function() {
106
			if ( !this.id ) {
107
				this.id = "ui-id-" + (++uuid);
108
			}
109
		});
110
	},
111
112
	removeUniqueId: function() {
113
		return this.each(function() {
114
			if ( runiqueId.test( this.id ) ) {
115
				$( this ).removeAttr( "id" );
116
			}
117
		});
118
	}
119
});
120
121
// selectors
122
function focusable( element, isTabIndexNotNaN ) {
123
	var map, mapName, img,
124
		nodeName = element.nodeName.toLowerCase();
125
	if ( "area" === nodeName ) {
126
		map = element.parentNode;
127
		mapName = map.name;
128
		if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
129
			return false;
130
		}
131
		img = $( "img[usemap=#" + mapName + "]" )[0];
132
		return !!img && visible( img );
133
	}
134
	return ( /input|select|textarea|button|object/.test( nodeName ) ?
135
		!element.disabled :
136
		"a" === nodeName ?
137
			element.href || isTabIndexNotNaN :
138
			isTabIndexNotNaN) &&
139
		// the element and all of its ancestors must be visible
140
		visible( element );
141
}
142
143
function visible( element ) {
144
	return $.expr.filters.visible( element ) &&
145
		!$( element ).parents().addBack().filter(function() {
146
			return $.css( this, "visibility" ) === "hidden";
147
		}).length;
148
}
149
150
$.extend( $.expr[ ":" ], {
151
	data: $.expr.createPseudo ?
152
		$.expr.createPseudo(function( dataName ) {
153
			return function( elem ) {
154
				return !!$.data( elem, dataName );
155
			};
156
		}) :
157
		// support: jQuery <1.8
158
		function( elem, i, match ) {
159
			return !!$.data( elem, match[ 3 ] );
160
		},
161
162
	focusable: function( element ) {
163
		return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );
164
	},
165
166
	tabbable: function( element ) {
167
		var tabIndex = $.attr( element, "tabindex" ),
168
			isTabIndexNaN = isNaN( tabIndex );
169
		return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );
170
	}
171
});
172
173
// support: jQuery <1.8
174
if ( !$( "<a>" ).outerWidth( 1 ).jquery ) {
175
	$.each( [ "Width", "Height" ], function( i, name ) {
176
		var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
177
			type = name.toLowerCase(),
178
			orig = {
179
				innerWidth: $.fn.innerWidth,
180
				innerHeight: $.fn.innerHeight,
181
				outerWidth: $.fn.outerWidth,
182
				outerHeight: $.fn.outerHeight
183
			};
184
185
		function reduce( elem, size, border, margin ) {
186
			$.each( side, function() {
187
				size -= parseFloat( $.css( elem, "padding" + this ) ) || 0;
188
				if ( border ) {
189
					size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0;
190
				}
191
				if ( margin ) {
192
					size -= parseFloat( $.css( elem, "margin" + this ) ) || 0;
193
				}
194
			});
195
			return size;
196
		}
197
198
		$.fn[ "inner" + name ] = function( size ) {
199
			if ( size === undefined ) {
200
				return orig[ "inner" + name ].call( this );
201
			}
202
203
			return this.each(function() {
204
				$( this ).css( type, reduce( this, size ) + "px" );
205
			});
206
		};
207
208
		$.fn[ "outer" + name] = function( size, margin ) {
209
			if ( typeof size !== "number" ) {
210
				return orig[ "outer" + name ].call( this, size );
211
			}
212
213
			return this.each(function() {
214
				$( this).css( type, reduce( this, size, true, margin ) + "px" );
215
			});
216
		};
217
	});
218
}
219
220
// support: jQuery <1.8
221
if ( !$.fn.addBack ) {
222
	$.fn.addBack = function( selector ) {
223
		return this.add( selector == null ?
224
			this.prevObject : this.prevObject.filter( selector )
225
		);
226
	};
227
}
228
229
// support: jQuery 1.6.1, 1.6.2 (http://bugs.jquery.com/ticket/9413)
230
if ( $( "<a>" ).data( "a-b", "a" ).removeData( "a-b" ).data( "a-b" ) ) {
231
	$.fn.removeData = (function( removeData ) {
232
		return function( key ) {
233
			if ( arguments.length ) {
234
				return removeData.call( this, $.camelCase( key ) );
235
			} else {
236
				return removeData.call( this );
237
			}
238
		};
239
	})( $.fn.removeData );
240
}
241
242
243
244
245
246
// deprecated
247
$.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() );
248
249
$.support.selectstart = "onselectstart" in document.createElement( "div" );
250
$.fn.extend({
251
	disableSelection: function() {
252
		return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
253
			".ui-disableSelection", function( event ) {
254
				event.preventDefault();
255
			});
256
	},
257
258
	enableSelection: function() {
259
		return this.unbind( ".ui-disableSelection" );
260
	}
261
});
262
263
$.extend( $.ui, {
264
	// $.ui.plugin is deprecated. Use $.widget() extensions instead.
265
	plugin: {
266
		add: function( module, option, set ) {
267
			var i,
268
				proto = $.ui[ module ].prototype;
269
			for ( i in set ) {
270
				proto.plugins[ i ] = proto.plugins[ i ] || [];
271
				proto.plugins[ i ].push( [ option, set[ i ] ] );
272
			}
273
		},
274
		call: function( instance, name, args ) {
275
			var i,
276
				set = instance.plugins[ name ];
277
			if ( !set || !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) {
278
				return;
279
			}
280
281
			for ( i = 0; i < set.length; i++ ) {
282
				if ( instance.options[ set[ i ][ 0 ] ] ) {
283
					set[ i ][ 1 ].apply( instance.element, args );
284
				}
285
			}
286
		}
287
	},
288
289
	// only used by resizable
290
	hasScroll: function( el, a ) {
291
292
		//If overflow is hidden, the element might have extra content, but the user wants to hide it
293
		if ( $( el ).css( "overflow" ) === "hidden") {
294
			return false;
295
		}
296
297
		var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
298
			has = false;
299
300
		if ( el[ scroll ] > 0 ) {
301
			return true;
302
		}
303
304
		// TODO: determine which cases actually cause this to happen
305
		// if the element doesn't have the scroll set, see if it's possible to
306
		// set the scroll
307
		el[ scroll ] = 1;
308
		has = ( el[ scroll ] > 0 );
309
		el[ scroll ] = 0;
310
		return has;
311
	}
312
});
313
314
})( jQuery );
315
316
(function( $, undefined ) {
317
318
var uuid = 0,
319
	slice = Array.prototype.slice,
320
	_cleanData = $.cleanData;
321
$.cleanData = function( elems ) {
322
	for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
323
		try {
324
			$( elem ).triggerHandler( "remove" );
325
		// http://bugs.jquery.com/ticket/8235
326
		} catch( e ) {}
327
	}
328
	_cleanData( elems );
329
};
330
331
$.widget = function( name, base, prototype ) {
332
	var fullName, existingConstructor, constructor, basePrototype,
333
		// proxiedPrototype allows the provided prototype to remain unmodified
334
		// so that it can be used as a mixin for multiple widgets (#8876)
335
		proxiedPrototype = {},
336
		namespace = name.split( "." )[ 0 ];
337
338
	name = name.split( "." )[ 1 ];
339
	fullName = namespace + "-" + name;
340
341
	if ( !prototype ) {
342
		prototype = base;
343
		base = $.Widget;
344
	}
345
346
	// create selector for plugin
347
	$.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
348
		return !!$.data( elem, fullName );
349
	};
350
351
	$[ namespace ] = $[ namespace ] || {};
352
	existingConstructor = $[ namespace ][ name ];
353
	constructor = $[ namespace ][ name ] = function( options, element ) {
354
		// allow instantiation without "new" keyword
355
		if ( !this._createWidget ) {
356
			return new constructor( options, element );
357
		}
358
359
		// allow instantiation without initializing for simple inheritance
360
		// must use "new" keyword (the code above always passes args)
361
		if ( arguments.length ) {
362
			this._createWidget( options, element );
363
		}
364
	};
365
	// extend with the existing constructor to carry over any static properties
366
	$.extend( constructor, existingConstructor, {
367
		version: prototype.version,
368
		// copy the object used to create the prototype in case we need to
369
		// redefine the widget later
370
		_proto: $.extend( {}, prototype ),
371
		// track widgets that inherit from this widget in case this widget is
372
		// redefined after a widget inherits from it
373
		_childConstructors: []
374
	});
375
376
	basePrototype = new base();
377
	// we need to make the options hash a property directly on the new instance
378
	// otherwise we'll modify the options hash on the prototype that we're
379
	// inheriting from
380
	basePrototype.options = $.widget.extend( {}, basePrototype.options );
381
	$.each( prototype, function( prop, value ) {
382
		if ( !$.isFunction( value ) ) {
383
			proxiedPrototype[ prop ] = value;
384
			return;
385
		}
386
		proxiedPrototype[ prop ] = (function() {
387
			var _super = function() {
388
					return base.prototype[ prop ].apply( this, arguments );
389
				},
390
				_superApply = function( args ) {
391
					return base.prototype[ prop ].apply( this, args );
392
				};
393
			return function() {
394
				var __super = this._super,
395
					__superApply = this._superApply,
396
					returnValue;
397
398
				this._super = _super;
399
				this._superApply = _superApply;
400
401
				returnValue = value.apply( this, arguments );
402
403
				this._super = __super;
404
				this._superApply = __superApply;
405
406
				return returnValue;
407
			};
408
		})();
409
	});
410
	constructor.prototype = $.widget.extend( basePrototype, {
411
		// TODO: remove support for widgetEventPrefix
412
		// always use the name + a colon as the prefix, e.g., draggable:start
413
		// don't prefix for widgets that aren't DOM-based
414
		widgetEventPrefix: existingConstructor ? basePrototype.widgetEventPrefix : name
415
	}, proxiedPrototype, {
416
		constructor: constructor,
417
		namespace: namespace,
418
		widgetName: name,
419
		widgetFullName: fullName
420
	});
421
422
	// If this widget is being redefined then we need to find all widgets that
423
	// are inheriting from it and redefine all of them so that they inherit from
424
	// the new version of this widget. We're essentially trying to replace one
425
	// level in the prototype chain.
426
	if ( existingConstructor ) {
427
		$.each( existingConstructor._childConstructors, function( i, child ) {
428
			var childPrototype = child.prototype;
429
430
			// redefine the child widget using the same prototype that was
431
			// originally used, but inherit from the new version of the base
432
			$.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto );
433
		});
434
		// remove the list of existing child constructors from the old constructor
435
		// so the old child constructors can be garbage collected
436
		delete existingConstructor._childConstructors;
437
	} else {
438
		base._childConstructors.push( constructor );
439
	}
440
441
	$.widget.bridge( name, constructor );
442
};
443
444
$.widget.extend = function( target ) {
445
	var input = slice.call( arguments, 1 ),
446
		inputIndex = 0,
447
		inputLength = input.length,
448
		key,
449
		value;
450
	for ( ; inputIndex < inputLength; inputIndex++ ) {
451
		for ( key in input[ inputIndex ] ) {
452
			value = input[ inputIndex ][ key ];
453
			if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
454
				// Clone objects
455
				if ( $.isPlainObject( value ) ) {
456
					target[ key ] = $.isPlainObject( target[ key ] ) ?
457
						$.widget.extend( {}, target[ key ], value ) :
458
						// Don't extend strings, arrays, etc. with objects
459
						$.widget.extend( {}, value );
460
				// Copy everything else by reference
461
				} else {
462
					target[ key ] = value;
463
				}
464
			}
465
		}
466
	}
467
	return target;
468
};
469
470
$.widget.bridge = function( name, object ) {
471
	var fullName = object.prototype.widgetFullName || name;
472
	$.fn[ name ] = function( options ) {
473
		var isMethodCall = typeof options === "string",
474
			args = slice.call( arguments, 1 ),
475
			returnValue = this;
476
477
		// allow multiple hashes to be passed on init
478
		options = !isMethodCall && args.length ?
479
			$.widget.extend.apply( null, [ options ].concat(args) ) :
480
			options;
481
482
		if ( isMethodCall ) {
483
			this.each(function() {
484
				var methodValue,
485
					instance = $.data( this, fullName );
486
				if ( !instance ) {
487
					return $.error( "cannot call methods on " + name + " prior to initialization; " +
488
						"attempted to call method '" + options + "'" );
489
				}
490
				if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) {
491
					return $.error( "no such method '" + options + "' for " + name + " widget instance" );
492
				}
493
				methodValue = instance[ options ].apply( instance, args );
494
				if ( methodValue !== instance && methodValue !== undefined ) {
495
					returnValue = methodValue && methodValue.jquery ?
496
						returnValue.pushStack( methodValue.get() ) :
497
						methodValue;
498
					return false;
499
				}
500
			});
501
		} else {
502
			this.each(function() {
503
				var instance = $.data( this, fullName );
504
				if ( instance ) {
505
					instance.option( options || {} )._init();
506
				} else {
507
					$.data( this, fullName, new object( options, this ) );
508
				}
509
			});
510
		}
511
512
		return returnValue;
513
	};
514
};
515
516
$.Widget = function( /* options, element */ ) {};
517
$.Widget._childConstructors = [];
518
519
$.Widget.prototype = {
520
	widgetName: "widget",
521
	widgetEventPrefix: "",
522
	defaultElement: "<div>",
523
	options: {
524
		disabled: false,
525
526
		// callbacks
527
		create: null
528
	},
529
	_createWidget: function( options, element ) {
530
		element = $( element || this.defaultElement || this )[ 0 ];
531
		this.element = $( element );
532
		this.uuid = uuid++;
533
		this.eventNamespace = "." + this.widgetName + this.uuid;
534
		this.options = $.widget.extend( {},
535
			this.options,
536
			this._getCreateOptions(),
537
			options );
538
539
		this.bindings = $();
540
		this.hoverable = $();
541
		this.focusable = $();
542
543
		if ( element !== this ) {
544
			$.data( element, this.widgetFullName, this );
545
			this._on( true, this.element, {
546
				remove: function( event ) {
547
					if ( event.target === element ) {
548
						this.destroy();
549
					}
550
				}
551
			});
552
			this.document = $( element.style ?
553
				// element within the document
554
				element.ownerDocument :
555
				// element is window or document
556
				element.document || element );
557
			this.window = $( this.document[0].defaultView || this.document[0].parentWindow );
558
		}
559
560
		this._create();
561
		this._trigger( "create", null, this._getCreateEventData() );
562
		this._init();
563
	},
564
	_getCreateOptions: $.noop,
565
	_getCreateEventData: $.noop,
566
	_create: $.noop,
567
	_init: $.noop,
568
569
	destroy: function() {
570
		this._destroy();
571
		// we can probably remove the unbind calls in 2.0
572
		// all event bindings should go through this._on()
573
		this.element
574
			.unbind( this.eventNamespace )
575
			// 1.9 BC for #7810
576
			// TODO remove dual storage
577
			.removeData( this.widgetName )
578
			.removeData( this.widgetFullName )
579
			// support: jquery <1.6.3
580
			// http://bugs.jquery.com/ticket/9413
581
			.removeData( $.camelCase( this.widgetFullName ) );
582
		this.widget()
583
			.unbind( this.eventNamespace )
584
			.removeAttr( "aria-disabled" )
585
			.removeClass(
586
				this.widgetFullName + "-disabled " +
587
				"ui-state-disabled" );
588
589
		// clean up events and states
590
		this.bindings.unbind( this.eventNamespace );
591
		this.hoverable.removeClass( "ui-state-hover" );
592
		this.focusable.removeClass( "ui-state-focus" );
593
	},
594
	_destroy: $.noop,
595
596
	widget: function() {
597
		return this.element;
598
	},
599
600
	option: function( key, value ) {
601
		var options = key,
602
			parts,
603
			curOption,
604
			i;
605
606
		if ( arguments.length === 0 ) {
607
			// don't return a reference to the internal hash
608
			return $.widget.extend( {}, this.options );
609
		}
610
611
		if ( typeof key === "string" ) {
612
			// handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
613
			options = {};
614
			parts = key.split( "." );
615
			key = parts.shift();
616
			if ( parts.length ) {
617
				curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
618
				for ( i = 0; i < parts.length - 1; i++ ) {
619
					curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
620
					curOption = curOption[ parts[ i ] ];
621
				}
622
				key = parts.pop();
623
				if ( value === undefined ) {
624
					return curOption[ key ] === undefined ? null : curOption[ key ];
625
				}
626
				curOption[ key ] = value;
627
			} else {
628
				if ( value === undefined ) {
629
					return this.options[ key ] === undefined ? null : this.options[ key ];
630
				}
631
				options[ key ] = value;
632
			}
633
		}
634
635
		this._setOptions( options );
636
637
		return this;
638
	},
639
	_setOptions: function( options ) {
640
		var key;
641
642
		for ( key in options ) {
643
			this._setOption( key, options[ key ] );
644
		}
645
646
		return this;
647
	},
648
	_setOption: function( key, value ) {
649
		this.options[ key ] = value;
650
651
		if ( key === "disabled" ) {
652
			this.widget()
653
				.toggleClass( this.widgetFullName + "-disabled ui-state-disabled", !!value )
654
				.attr( "aria-disabled", value );
655
			this.hoverable.removeClass( "ui-state-hover" );
656
			this.focusable.removeClass( "ui-state-focus" );
657
		}
658
659
		return this;
660
	},
661
662
	enable: function() {
663
		return this._setOption( "disabled", false );
664
	},
665
	disable: function() {
666
		return this._setOption( "disabled", true );
667
	},
668
669
	_on: function( suppressDisabledCheck, element, handlers ) {
670
		var delegateElement,
671
			instance = this;
672
673
		// no suppressDisabledCheck flag, shuffle arguments
674
		if ( typeof suppressDisabledCheck !== "boolean" ) {
675
			handlers = element;
676
			element = suppressDisabledCheck;
677
			suppressDisabledCheck = false;
678
		}
679
680
		// no element argument, shuffle and use this.element
681
		if ( !handlers ) {
682
			handlers = element;
683
			element = this.element;
684
			delegateElement = this.widget();
685
		} else {
686
			// accept selectors, DOM elements
687
			element = delegateElement = $( element );
688
			this.bindings = this.bindings.add( element );
689
		}
690
691
		$.each( handlers, function( event, handler ) {
692
			function handlerProxy() {
693
				// allow widgets to customize the disabled handling
694
				// - disabled as an array instead of boolean
695
				// - disabled class as method for disabling individual parts
696
				if ( !suppressDisabledCheck &&
697
						( instance.options.disabled === true ||
698
							$( this ).hasClass( "ui-state-disabled" ) ) ) {
699
					return;
700
				}
701
				return ( typeof handler === "string" ? instance[ handler ] : handler )
702
					.apply( instance, arguments );
703
			}
704
705
			// copy the guid so direct unbinding works
706
			if ( typeof handler !== "string" ) {
707
				handlerProxy.guid = handler.guid =
708
					handler.guid || handlerProxy.guid || $.guid++;
709
			}
710
711
			var match = event.match( /^(\w+)\s*(.*)$/ ),
712
				eventName = match[1] + instance.eventNamespace,
713
				selector = match[2];
714
			if ( selector ) {
715
				delegateElement.delegate( selector, eventName, handlerProxy );
716
			} else {
717
				element.bind( eventName, handlerProxy );
718
			}
719
		});
720
	},
721
722
	_off: function( element, eventName ) {
723
		eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + this.eventNamespace;
724
		element.unbind( eventName ).undelegate( eventName );
725
	},
726
727
	_delay: function( handler, delay ) {
728
		function handlerProxy() {
729
			return ( typeof handler === "string" ? instance[ handler ] : handler )
730
				.apply( instance, arguments );
731
		}
732
		var instance = this;
733
		return setTimeout( handlerProxy, delay || 0 );
734
	},
735
736
	_hoverable: function( element ) {
737
		this.hoverable = this.hoverable.add( element );
738
		this._on( element, {
739
			mouseenter: function( event ) {
740
				$( event.currentTarget ).addClass( "ui-state-hover" );
741
			},
742
			mouseleave: function( event ) {
743
				$( event.currentTarget ).removeClass( "ui-state-hover" );
744
			}
745
		});
746
	},
747
748
	_focusable: function( element ) {
749
		this.focusable = this.focusable.add( element );
750
		this._on( element, {
751
			focusin: function( event ) {
752
				$( event.currentTarget ).addClass( "ui-state-focus" );
753
			},
754
			focusout: function( event ) {
755
				$( event.currentTarget ).removeClass( "ui-state-focus" );
756
			}
757
		});
758
	},
759
760
	_trigger: function( type, event, data ) {
761
		var prop, orig,
762
			callback = this.options[ type ];
763
764
		data = data || {};
765
		event = $.Event( event );
766
		event.type = ( type === this.widgetEventPrefix ?
767
			type :
768
			this.widgetEventPrefix + type ).toLowerCase();
769
		// the original event may come from any element
770
		// so we need to reset the target on the new event
771
		event.target = this.element[ 0 ];
772
773
		// copy original event properties over to the new event
774
		orig = event.originalEvent;
775
		if ( orig ) {
776
			for ( prop in orig ) {
777
				if ( !( prop in event ) ) {
778
					event[ prop ] = orig[ prop ];
779
				}
780
			}
781
		}
782
783
		this.element.trigger( event, data );
784
		return !( $.isFunction( callback ) &&
785
			callback.apply( this.element[0], [ event ].concat( data ) ) === false ||
786
			event.isDefaultPrevented() );
787
	}
788
};
789
790
$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
791
	$.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
792
		if ( typeof options === "string" ) {
793
			options = { effect: options };
794
		}
795
		var hasOptions,
796
			effectName = !options ?
797
				method :
798
				options === true || typeof options === "number" ?
799
					defaultEffect :
800
					options.effect || defaultEffect;
801
		options = options || {};
802
		if ( typeof options === "number" ) {
803
			options = { duration: options };
804
		}
805
		hasOptions = !$.isEmptyObject( options );
806
		options.complete = callback;
807
		if ( options.delay ) {
808
			element.delay( options.delay );
809
		}
810
		if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
811
			element[ method ]( options );
812
		} else if ( effectName !== method && element[ effectName ] ) {
813
			element[ effectName ]( options.duration, options.easing, callback );
814
		} else {
815
			element.queue(function( next ) {
816
				$( this )[ method ]();
817
				if ( callback ) {
818
					callback.call( element[ 0 ] );
819
				}
820
				next();
821
			});
822
		}
823
	};
824
});
825
826
})( jQuery );
827
828
(function( $, undefined ) {
829
830
var mouseHandled = false;
831
$( document ).mouseup( function() {
832
	mouseHandled = false;
833
});
834
835
$.widget("ui.mouse", {
836
	version: "1.10.3",
837
	options: {
838
		cancel: "input,textarea,button,select,option",
839
		distance: 1,
840
		delay: 0
841
	},
842
	_mouseInit: function() {
843
		var that = this;
844
845
		this.element
846
			.bind("mousedown."+this.widgetName, function(event) {
847
				return that._mouseDown(event);
848
			})
849
			.bind("click."+this.widgetName, function(event) {
850
				if (true === $.data(event.target, that.widgetName + ".preventClickEvent")) {
851
					$.removeData(event.target, that.widgetName + ".preventClickEvent");
852
					event.stopImmediatePropagation();
853
					return false;
854
				}
855
			});
856
857
		this.started = false;
858
	},
859
860
	// TODO: make sure destroying one instance of mouse doesn't mess with
861
	// other instances of mouse
862
	_mouseDestroy: function() {
863
		this.element.unbind("."+this.widgetName);
864
		if ( this._mouseMoveDelegate ) {
865
			$(document)
866
				.unbind("mousemove."+this.widgetName, this._mouseMoveDelegate)
867
				.unbind("mouseup."+this.widgetName, this._mouseUpDelegate);
868
		}
869
	},
870
871
	_mouseDown: function(event) {
872
		// don't let more than one widget handle mouseStart
873
		if( mouseHandled ) { return; }
874
875
		// we may have missed mouseup (out of window)
876
		(this._mouseStarted && this._mouseUp(event));
877
878
		this._mouseDownEvent = event;
879
880
		var that = this,
881
			btnIsLeft = (event.which === 1),
882
			// event.target.nodeName works around a bug in IE 8 with
883
			// disabled inputs (#7620)
884
			elIsCancel = (typeof this.options.cancel === "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false);
885
		if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
886
			return true;
887
		}
888
889
		this.mouseDelayMet = !this.options.delay;
890
		if (!this.mouseDelayMet) {
891
			this._mouseDelayTimer = setTimeout(function() {
892
				that.mouseDelayMet = true;
893
			}, this.options.delay);
894
		}
895
896
		if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
897
			this._mouseStarted = (this._mouseStart(event) !== false);
898
			if (!this._mouseStarted) {
899
				event.preventDefault();
900
				return true;
901
			}
902
		}
903
904
		// Click event may never have fired (Gecko & Opera)
905
		if (true === $.data(event.target, this.widgetName + ".preventClickEvent")) {
906
			$.removeData(event.target, this.widgetName + ".preventClickEvent");
907
		}
908
909
		// these delegates are required to keep context
910
		this._mouseMoveDelegate = function(event) {
911
			return that._mouseMove(event);
912
		};
913
		this._mouseUpDelegate = function(event) {
914
			return that._mouseUp(event);
915
		};
916
		$(document)
917
			.bind("mousemove."+this.widgetName, this._mouseMoveDelegate)
918
			.bind("mouseup."+this.widgetName, this._mouseUpDelegate);
919
920
		event.preventDefault();
921
922
		mouseHandled = true;
923
		return true;
924
	},
925
926
	_mouseMove: function(event) {
927
		// IE mouseup check - mouseup happened when mouse was out of window
928
		if ($.ui.ie && ( !document.documentMode || document.documentMode < 9 ) && !event.button) {
929
			return this._mouseUp(event);
930
		}
931
932
		if (this._mouseStarted) {
933
			this._mouseDrag(event);
934
			return event.preventDefault();
935
		}
936
937
		if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
938
			this._mouseStarted =
939
				(this._mouseStart(this._mouseDownEvent, event) !== false);
940
			(this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
941
		}
942
943
		return !this._mouseStarted;
944
	},
945
946
	_mouseUp: function(event) {
947
		$(document)
948
			.unbind("mousemove."+this.widgetName, this._mouseMoveDelegate)
949
			.unbind("mouseup."+this.widgetName, this._mouseUpDelegate);
950
951
		if (this._mouseStarted) {
952
			this._mouseStarted = false;
953
954
			if (event.target === this._mouseDownEvent.target) {
955
				$.data(event.target, this.widgetName + ".preventClickEvent", true);
956
			}
957
958
			this._mouseStop(event);
959
		}
960
961
		return false;
962
	},
963
964
	_mouseDistanceMet: function(event) {
965
		return (Math.max(
966
				Math.abs(this._mouseDownEvent.pageX - event.pageX),
967
				Math.abs(this._mouseDownEvent.pageY - event.pageY)
968
			) >= this.options.distance
969
		);
970
	},
971
972
	_mouseDelayMet: function(/* event */) {
973
		return this.mouseDelayMet;
974
	},
975
976
	// These are placeholder methods, to be overriden by extending plugin
977
	_mouseStart: function(/* event */) {},
978
	_mouseDrag: function(/* event */) {},
979
	_mouseStop: function(/* event */) {},
980
	_mouseCapture: function(/* event */) { return true; }
981
});
982
983
})(jQuery);
984
985
(function( $, undefined ) {
986
987
$.widget("ui.draggable", $.ui.mouse, {
988
	version: "1.10.3",
989
	widgetEventPrefix: "drag",
990
	options: {
991
		addClasses: true,
992
		appendTo: "parent",
993
		axis: false,
994
		connectToSortable: false,
995
		containment: false,
996
		cursor: "auto",
997
		cursorAt: false,
998
		grid: false,
999
		handle: false,
1000
		helper: "original",
1001
		iframeFix: false,
1002
		opacity: false,
1003
		refreshPositions: false,
1004
		revert: false,
1005
		revertDuration: 500,
1006
		scope: "default",
1007
		scroll: true,
1008
		scrollSensitivity: 20,
1009
		scrollSpeed: 20,
1010
		snap: false,
1011
		snapMode: "both",
1012
		snapTolerance: 20,
1013
		stack: false,
1014
		zIndex: false,
1015
1016
		// callbacks
1017
		drag: null,
1018
		start: null,
1019
		stop: null
1020
	},
1021
	_create: function() {
1022
1023
		if (this.options.helper === "original" && !(/^(?:r|a|f)/).test(this.element.css("position"))) {
1024
			this.element[0].style.position = "relative";
1025
		}
1026
		if (this.options.addClasses){
1027
			this.element.addClass("ui-draggable");
1028
		}
1029
		if (this.options.disabled){
1030
			this.element.addClass("ui-draggable-disabled");
1031
		}
1032
1033
		this._mouseInit();
1034
1035
	},
1036
1037
	_destroy: function() {
1038
		this.element.removeClass( "ui-draggable ui-draggable-dragging ui-draggable-disabled" );
1039
		this._mouseDestroy();
1040
	},
1041
1042
	_mouseCapture: function(event) {
1043
1044
		var o = this.options;
1045
1046
		// among others, prevent a drag on a resizable-handle
1047
		if (this.helper || o.disabled || $(event.target).closest(".ui-resizable-handle").length > 0) {
1048
			return false;
1049
		}
1050
1051
		//Quit if we're not on a valid handle
1052
		this.handle = this._getHandle(event);
1053
		if (!this.handle) {
1054
			return false;
1055
		}
1056
1057
		$(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
1058
			$("<div class='ui-draggable-iframeFix' style='background: #fff;'></div>")
1059
			.css({
1060
				width: this.offsetWidth+"px", height: this.offsetHeight+"px",
1061
				position: "absolute", opacity: "0.001", zIndex: 1000
1062
			})
1063
			.css($(this).offset())
1064
			.appendTo("body");
1065
		});
1066
1067
		return true;
1068
1069
	},
1070
1071
	_mouseStart: function(event) {
1072
1073
		var o = this.options;
1074
1075
		//Create and append the visible helper
1076
		this.helper = this._createHelper(event);
1077
1078
		this.helper.addClass("ui-draggable-dragging");
1079
1080
		//Cache the helper size
1081
		this._cacheHelperProportions();
1082
1083
		//If ddmanager is used for droppables, set the global draggable
1084
		if($.ui.ddmanager) {
1085
			$.ui.ddmanager.current = this;
1086
		}
1087
1088
		/*
1089
		 * - Position generation -
1090
		 * This block generates everything position related - it's the core of draggables.
1091
		 */
1092
1093
		//Cache the margins of the original element
1094
		this._cacheMargins();
1095
1096
		//Store the helper's css position
1097
		this.cssPosition = this.helper.css( "position" );
1098
		this.scrollParent = this.helper.scrollParent();
1099
		this.offsetParent = this.helper.offsetParent();
1100
		this.offsetParentCssPosition = this.offsetParent.css( "position" );
1101
1102
		//The element's absolute position on the page minus margins
1103
		this.offset = this.positionAbs = this.element.offset();
1104
		this.offset = {
1105
			top: this.offset.top - this.margins.top,
1106
			left: this.offset.left - this.margins.left
1107
		};
1108
1109
		//Reset scroll cache
1110
		this.offset.scroll = false;
1111
1112
		$.extend(this.offset, {
1113
			click: { //Where the click happened, relative to the element
1114
				left: event.pageX - this.offset.left,
1115
				top: event.pageY - this.offset.top
1116
			},
1117
			parent: this._getParentOffset(),
1118
			relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
1119
		});
1120
1121
		//Generate the original position
1122
		this.originalPosition = this.position = this._generatePosition(event);
1123
		this.originalPageX = event.pageX;
1124
		this.originalPageY = event.pageY;
1125
1126
		//Adjust the mouse offset relative to the helper if "cursorAt" is supplied
1127
		(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
1128
1129
		//Set a containment if given in the options
1130
		this._setContainment();
1131
1132
		//Trigger event + callbacks
1133
		if(this._trigger("start", event) === false) {
1134
			this._clear();
1135
			return false;
1136
		}
1137
1138
		//Recache the helper size
1139
		this._cacheHelperProportions();
1140
1141
		//Prepare the droppable offsets
1142
		if ($.ui.ddmanager && !o.dropBehaviour) {
1143
			$.ui.ddmanager.prepareOffsets(this, event);
1144
		}
1145
1146
1147
		this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
1148
1149
		//If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003)
1150
		if ( $.ui.ddmanager ) {
1151
			$.ui.ddmanager.dragStart(this, event);
1152
		}
1153
1154
		return true;
1155
	},
1156
1157
	_mouseDrag: function(event, noPropagation) {
1158
		// reset any necessary cached properties (see #5009)
1159
		if ( this.offsetParentCssPosition === "fixed" ) {
1160
			this.offset.parent = this._getParentOffset();
1161
		}
1162
1163
		//Compute the helpers position
1164
		this.position = this._generatePosition(event);
1165
		this.positionAbs = this._convertPositionTo("absolute");
1166
1167
		//Call plugins and callbacks and use the resulting position if something is returned
1168
		if (!noPropagation) {
1169
			var ui = this._uiHash();
1170
			if(this._trigger("drag", event, ui) === false) {
1171
				this._mouseUp({});
1172
				return false;
1173
			}
1174
			this.position = ui.position;
1175
		}
1176
1177
		if(!this.options.axis || this.options.axis !== "y") {
1178
			this.helper[0].style.left = this.position.left+"px";
1179
		}
1180
		if(!this.options.axis || this.options.axis !== "x") {
1181
			this.helper[0].style.top = this.position.top+"px";
1182
		}
1183
		if($.ui.ddmanager) {
1184
			$.ui.ddmanager.drag(this, event);
1185
		}
1186
1187
		return false;
1188
	},
1189
1190
	_mouseStop: function(event) {
1191
1192
		//If we are using droppables, inform the manager about the drop
1193
		var that = this,
1194
			dropped = false;
1195
		if ($.ui.ddmanager && !this.options.dropBehaviour) {
1196
			dropped = $.ui.ddmanager.drop(this, event);
1197
		}
1198
1199
		//if a drop comes from outside (a sortable)
1200
		if(this.dropped) {
1201
			dropped = this.dropped;
1202
			this.dropped = false;
1203
		}
1204
1205
		//if the original element is no longer in the DOM don't bother to continue (see #8269)
1206
		if ( this.options.helper === "original" && !$.contains( this.element[ 0 ].ownerDocument, this.element[ 0 ] ) ) {
1207
			return false;
1208
		}
1209
1210
		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))) {
1211
			$(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
1212
				if(that._trigger("stop", event) !== false) {
1213
					that._clear();
1214
				}
1215
			});
1216
		} else {
1217
			if(this._trigger("stop", event) !== false) {
1218
				this._clear();
1219
			}
1220
		}
1221
1222
		return false;
1223
	},
1224
1225
	_mouseUp: function(event) {
1226
		//Remove frame helpers
1227
		$("div.ui-draggable-iframeFix").each(function() {
1228
			this.parentNode.removeChild(this);
1229
		});
1230
1231
		//If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003)
1232
		if( $.ui.ddmanager ) {
1233
			$.ui.ddmanager.dragStop(this, event);
1234
		}
1235
1236
		return $.ui.mouse.prototype._mouseUp.call(this, event);
1237
	},
1238
1239
	cancel: function() {
1240
1241
		if(this.helper.is(".ui-draggable-dragging")) {
1242
			this._mouseUp({});
1243
		} else {
1244
			this._clear();
1245
		}
1246
1247
		return this;
1248
1249
	},
1250
1251
	_getHandle: function(event) {
1252
		return this.options.handle ?
1253
			!!$( event.target ).closest( this.element.find( this.options.handle ) ).length :
1254
			true;
1255
	},
1256
1257
	_createHelper: function(event) {
1258
1259
		var o = this.options,
1260
			helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper === "clone" ? this.element.clone().removeAttr("id") : this.element);
1261
1262
		if(!helper.parents("body").length) {
1263
			helper.appendTo((o.appendTo === "parent" ? this.element[0].parentNode : o.appendTo));
1264
		}
1265
1266
		if(helper[0] !== this.element[0] && !(/(fixed|absolute)/).test(helper.css("position"))) {
1267
			helper.css("position", "absolute");
1268
		}
1269
1270
		return helper;
1271
1272
	},
1273
1274 View Code Duplication
	_adjustOffsetFromHelper: function(obj) {
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
1275
		if (typeof obj === "string") {
1276
			obj = obj.split(" ");
1277
		}
1278
		if ($.isArray(obj)) {
1279
			obj = {left: +obj[0], top: +obj[1] || 0};
1280
		}
1281
		if ("left" in obj) {
1282
			this.offset.click.left = obj.left + this.margins.left;
1283
		}
1284
		if ("right" in obj) {
1285
			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
1286
		}
1287
		if ("top" in obj) {
1288
			this.offset.click.top = obj.top + this.margins.top;
1289
		}
1290
		if ("bottom" in obj) {
1291
			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
1292
		}
1293
	},
1294
1295 View Code Duplication
	_getParentOffset: function() {
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
1296
1297
		//Get the offsetParent and cache its position
1298
		var po = this.offsetParent.offset();
1299
1300
		// This is a special case where we need to modify a offset calculated on start, since the following happened:
1301
		// 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
1302
		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
1303
		//    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
1304
		if(this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) {
1305
			po.left += this.scrollParent.scrollLeft();
1306
			po.top += this.scrollParent.scrollTop();
1307
		}
1308
1309
		//This needs to be actually done for all browsers, since pageX/pageY includes this information
1310
		//Ugly IE fix
1311
		if((this.offsetParent[0] === document.body) ||
1312
			(this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie)) {
1313
			po = { top: 0, left: 0 };
1314
		}
1315
1316
		return {
1317
			top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
1318
			left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
1319
		};
1320
1321
	},
1322
1323
	_getRelativeOffset: function() {
1324
1325
		if(this.cssPosition === "relative") {
1326
			var p = this.element.position();
1327
			return {
1328
				top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
1329
				left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
1330
			};
1331
		} else {
1332
			return { top: 0, left: 0 };
1333
		}
1334
1335
	},
1336
1337
	_cacheMargins: function() {
1338
		this.margins = {
1339
			left: (parseInt(this.element.css("marginLeft"),10) || 0),
1340
			top: (parseInt(this.element.css("marginTop"),10) || 0),
1341
			right: (parseInt(this.element.css("marginRight"),10) || 0),
1342
			bottom: (parseInt(this.element.css("marginBottom"),10) || 0)
1343
		};
1344
	},
1345
1346
	_cacheHelperProportions: function() {
1347
		this.helperProportions = {
1348
			width: this.helper.outerWidth(),
1349
			height: this.helper.outerHeight()
1350
		};
1351
	},
1352
1353
	_setContainment: function() {
1354
1355
		var over, c, ce,
1356
			o = this.options;
1357
1358
		if ( !o.containment ) {
1359
			this.containment = null;
1360
			return;
1361
		}
1362
1363
		if ( o.containment === "window" ) {
1364
			this.containment = [
1365
				$( window ).scrollLeft() - this.offset.relative.left - this.offset.parent.left,
1366
				$( window ).scrollTop() - this.offset.relative.top - this.offset.parent.top,
1367
				$( window ).scrollLeft() + $( window ).width() - this.helperProportions.width - this.margins.left,
1368
				$( window ).scrollTop() + ( $( window ).height() || document.body.parentNode.scrollHeight ) - this.helperProportions.height - this.margins.top
1369
			];
1370
			return;
1371
		}
1372
1373
		if ( o.containment === "document") {
1374
			this.containment = [
1375
				0,
1376
				0,
1377
				$( document ).width() - this.helperProportions.width - this.margins.left,
1378
				( $( document ).height() || document.body.parentNode.scrollHeight ) - this.helperProportions.height - this.margins.top
1379
			];
1380
			return;
1381
		}
1382
1383
		if ( o.containment.constructor === Array ) {
1384
			this.containment = o.containment;
1385
			return;
1386
		}
1387
1388
		if ( o.containment === "parent" ) {
1389
			o.containment = this.helper[ 0 ].parentNode;
1390
		}
1391
1392
		c = $( o.containment );
1393
		ce = c[ 0 ];
1394
1395
		if( !ce ) {
1396
			return;
1397
		}
1398
1399
		over = c.css( "overflow" ) !== "hidden";
1400
1401
		this.containment = [
1402
			( parseInt( c.css( "borderLeftWidth" ), 10 ) || 0 ) + ( parseInt( c.css( "paddingLeft" ), 10 ) || 0 ),
1403
			( parseInt( c.css( "borderTopWidth" ), 10 ) || 0 ) + ( parseInt( c.css( "paddingTop" ), 10 ) || 0 ) ,
1404
			( over ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) - ( parseInt( c.css( "borderRightWidth" ), 10 ) || 0 ) - ( parseInt( c.css( "paddingRight" ), 10 ) || 0 ) - this.helperProportions.width - this.margins.left - this.margins.right,
1405
			( over ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) - ( parseInt( c.css( "borderBottomWidth" ), 10 ) || 0 ) - ( parseInt( c.css( "paddingBottom" ), 10 ) || 0 ) - this.helperProportions.height - this.margins.top  - this.margins.bottom
1406
		];
1407
		this.relative_container = c;
1408
	},
1409
1410
	_convertPositionTo: function(d, pos) {
1411
1412
		if(!pos) {
1413
			pos = this.position;
1414
		}
1415
1416
		var mod = d === "absolute" ? 1 : -1,
1417
			scroll = this.cssPosition === "absolute" && !( this.scrollParent[ 0 ] !== document && $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ? this.offsetParent : this.scrollParent;
1418
1419
		//Cache the scroll
1420
		if (!this.offset.scroll) {
1421
			this.offset.scroll = {top : scroll.scrollTop(), left : scroll.scrollLeft()};
1422
		}
1423
1424
		return {
1425
			top: (
1426
				pos.top	+																// The absolute mouse position
1427
				this.offset.relative.top * mod +										// Only for relative positioned nodes: Relative offset from element to offset parent
1428
				this.offset.parent.top * mod -										// The offsetParent's offset without borders (offset + border)
1429
				( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : this.offset.scroll.top ) * mod )
1430
			),
1431
			left: (
1432
				pos.left +																// The absolute mouse position
1433
				this.offset.relative.left * mod +										// Only for relative positioned nodes: Relative offset from element to offset parent
1434
				this.offset.parent.left * mod	-										// The offsetParent's offset without borders (offset + border)
1435
				( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : this.offset.scroll.left ) * mod )
1436
			)
1437
		};
1438
1439
	},
1440
1441 View Code Duplication
	_generatePosition: function(event) {
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
1442
1443
		var containment, co, top, left,
1444
			o = this.options,
1445
			scroll = this.cssPosition === "absolute" && !( this.scrollParent[ 0 ] !== document && $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ? this.offsetParent : this.scrollParent,
1446
			pageX = event.pageX,
1447
			pageY = event.pageY;
1448
1449
		//Cache the scroll
1450
		if (!this.offset.scroll) {
1451
			this.offset.scroll = {top : scroll.scrollTop(), left : scroll.scrollLeft()};
1452
		}
1453
1454
		/*
1455
		 * - Position constraining -
1456
		 * Constrain the position to a mix of grid, containment.
1457
		 */
1458
1459
		// If we are not dragging yet, we won't check for options
1460
		if ( this.originalPosition ) {
1461
			if ( this.containment ) {
1462
				if ( this.relative_container ){
1463
					co = this.relative_container.offset();
1464
					containment = [
1465
						this.containment[ 0 ] + co.left,
1466
						this.containment[ 1 ] + co.top,
1467
						this.containment[ 2 ] + co.left,
1468
						this.containment[ 3 ] + co.top
1469
					];
1470
				}
1471
				else {
1472
					containment = this.containment;
1473
				}
1474
1475
				if(event.pageX - this.offset.click.left < containment[0]) {
1476
					pageX = containment[0] + this.offset.click.left;
1477
				}
1478
				if(event.pageY - this.offset.click.top < containment[1]) {
1479
					pageY = containment[1] + this.offset.click.top;
1480
				}
1481
				if(event.pageX - this.offset.click.left > containment[2]) {
1482
					pageX = containment[2] + this.offset.click.left;
1483
				}
1484
				if(event.pageY - this.offset.click.top > containment[3]) {
1485
					pageY = containment[3] + this.offset.click.top;
1486
				}
1487
			}
1488
1489
			if(o.grid) {
1490
				//Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950)
1491
				top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY;
1492
				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;
1493
1494
				left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX;
1495
				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;
1496
			}
1497
1498
		}
1499
1500
		return {
1501
			top: (
1502
				pageY -																	// The absolute mouse position
1503
				this.offset.click.top	-												// Click offset (relative to the element)
1504
				this.offset.relative.top -												// Only for relative positioned nodes: Relative offset from element to offset parent
1505
				this.offset.parent.top +												// The offsetParent's offset without borders (offset + border)
1506
				( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : this.offset.scroll.top )
1507
			),
1508
			left: (
1509
				pageX -																	// The absolute mouse position
1510
				this.offset.click.left -												// Click offset (relative to the element)
1511
				this.offset.relative.left -												// Only for relative positioned nodes: Relative offset from element to offset parent
1512
				this.offset.parent.left +												// The offsetParent's offset without borders (offset + border)
1513
				( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : this.offset.scroll.left )
1514
			)
1515
		};
1516
1517
	},
1518
1519
	_clear: function() {
1520
		this.helper.removeClass("ui-draggable-dragging");
1521
		if(this.helper[0] !== this.element[0] && !this.cancelHelperRemoval) {
1522
			this.helper.remove();
1523
		}
1524
		this.helper = null;
1525
		this.cancelHelperRemoval = false;
1526
	},
1527
1528
	// From now on bulk stuff - mainly helpers
1529
1530
	_trigger: function(type, event, ui) {
1531
		ui = ui || this._uiHash();
1532
		$.ui.plugin.call(this, type, [event, ui]);
1533
		//The absolute position has to be recalculated after plugins
1534
		if(type === "drag") {
1535
			this.positionAbs = this._convertPositionTo("absolute");
1536
		}
1537
		return $.Widget.prototype._trigger.call(this, type, event, ui);
1538
	},
1539
1540
	plugins: {},
1541
1542
	_uiHash: function() {
1543
		return {
1544
			helper: this.helper,
1545
			position: this.position,
1546
			originalPosition: this.originalPosition,
1547
			offset: this.positionAbs
1548
		};
1549
	}
1550
1551
});
1552
1553
$.ui.plugin.add("draggable", "connectToSortable", {
1554
	start: function(event, ui) {
1555
1556
		var inst = $(this).data("ui-draggable"), o = inst.options,
1557
			uiSortable = $.extend({}, ui, { item: inst.element });
1558
		inst.sortables = [];
1559
		$(o.connectToSortable).each(function() {
1560
			var sortable = $.data(this, "ui-sortable");
1561
			if (sortable && !sortable.options.disabled) {
1562
				inst.sortables.push({
1563
					instance: sortable,
1564
					shouldRevert: sortable.options.revert
1565
				});
1566
				sortable.refreshPositions();	// Call the sortable's refreshPositions at drag start to refresh the containerCache since the sortable container cache is used in drag and needs to be up to date (this will ensure it's initialised as well as being kept in step with any changes that might have happened on the page).
1567
				sortable._trigger("activate", event, uiSortable);
1568
			}
1569
		});
1570
1571
	},
1572
	stop: function(event, ui) {
1573
1574
		//If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
1575
		var inst = $(this).data("ui-draggable"),
1576
			uiSortable = $.extend({}, ui, { item: inst.element });
1577
1578
		$.each(inst.sortables, function() {
1579
			if(this.instance.isOver) {
1580
1581
				this.instance.isOver = 0;
1582
1583
				inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
1584
				this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
1585
1586
				//The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: "valid/invalid"
1587
				if(this.shouldRevert) {
1588
					this.instance.options.revert = this.shouldRevert;
1589
				}
1590
1591
				//Trigger the stop of the sortable
1592
				this.instance._mouseStop(event);
1593
1594
				this.instance.options.helper = this.instance.options._helper;
1595
1596
				//If the helper has been the original item, restore properties in the sortable
1597
				if(inst.options.helper === "original") {
1598
					this.instance.currentItem.css({ top: "auto", left: "auto" });
1599
				}
1600
1601
			} else {
1602
				this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
1603
				this.instance._trigger("deactivate", event, uiSortable);
1604
			}
1605
1606
		});
1607
1608
	},
1609
	drag: function(event, ui) {
1610
1611
		var inst = $(this).data("ui-draggable"), that = this;
1612
1613
		$.each(inst.sortables, function() {
1614
1615
			var innermostIntersecting = false,
1616
				thisSortable = this;
1617
1618
			//Copy over some variables to allow calling the sortable's native _intersectsWith
1619
			this.instance.positionAbs = inst.positionAbs;
1620
			this.instance.helperProportions = inst.helperProportions;
1621
			this.instance.offset.click = inst.offset.click;
1622
1623
			if(this.instance._intersectsWith(this.instance.containerCache)) {
1624
				innermostIntersecting = true;
1625
				$.each(inst.sortables, function () {
1626
					this.instance.positionAbs = inst.positionAbs;
1627
					this.instance.helperProportions = inst.helperProportions;
1628
					this.instance.offset.click = inst.offset.click;
1629
					if (this !== thisSortable &&
1630
						this.instance._intersectsWith(this.instance.containerCache) &&
1631
						$.contains(thisSortable.instance.element[0], this.instance.element[0])
1632
					) {
1633
						innermostIntersecting = false;
1634
					}
1635
					return innermostIntersecting;
1636
				});
1637
			}
1638
1639
1640
			if(innermostIntersecting) {
1641
				//If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
1642
				if(!this.instance.isOver) {
1643
1644
					this.instance.isOver = 1;
1645
					//Now we fake the start of dragging for the sortable instance,
1646
					//by cloning the list group item, appending it to the sortable and using it as inst.currentItem
1647
					//We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one)
1648
					this.instance.currentItem = $(that).clone().removeAttr("id").appendTo(this.instance.element).data("ui-sortable-item", true);
1649
					this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
1650
					this.instance.options.helper = function() { return ui.helper[0]; };
1651
1652
					event.target = this.instance.currentItem[0];
1653
					this.instance._mouseCapture(event, true);
1654
					this.instance._mouseStart(event, true, true);
1655
1656
					//Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
1657
					this.instance.offset.click.top = inst.offset.click.top;
1658
					this.instance.offset.click.left = inst.offset.click.left;
1659
					this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
1660
					this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
1661
1662
					inst._trigger("toSortable", event);
1663
					inst.dropped = this.instance.element; //draggable revert needs that
1664
					//hack so receive/update callbacks work (mostly)
1665
					inst.currentItem = inst.element;
1666
					this.instance.fromOutside = inst;
1667
1668
				}
1669
1670
				//Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable
1671
				if(this.instance.currentItem) {
1672
					this.instance._mouseDrag(event);
1673
				}
1674
1675
			} else {
1676
1677
				//If it doesn't intersect with the sortable, and it intersected before,
1678
				//we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
1679
				if(this.instance.isOver) {
1680
1681
					this.instance.isOver = 0;
1682
					this.instance.cancelHelperRemoval = true;
1683
1684
					//Prevent reverting on this forced stop
1685
					this.instance.options.revert = false;
1686
1687
					// The out event needs to be triggered independently
1688
					this.instance._trigger("out", event, this.instance._uiHash(this.instance));
1689
1690
					this.instance._mouseStop(event, true);
1691
					this.instance.options.helper = this.instance.options._helper;
1692
1693
					//Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
1694
					this.instance.currentItem.remove();
1695
					if(this.instance.placeholder) {
1696
						this.instance.placeholder.remove();
1697
					}
1698
1699
					inst._trigger("fromSortable", event);
1700
					inst.dropped = false; //draggable revert needs that
1701
				}
1702
1703
			}
1704
1705
		});
1706
1707
	}
1708
});
1709
1710
$.ui.plugin.add("draggable", "cursor", {
1711
	start: function() {
1712
		var t = $("body"), o = $(this).data("ui-draggable").options;
1713
		if (t.css("cursor")) {
1714
			o._cursor = t.css("cursor");
1715
		}
1716
		t.css("cursor", o.cursor);
1717
	},
1718
	stop: function() {
1719
		var o = $(this).data("ui-draggable").options;
1720
		if (o._cursor) {
1721
			$("body").css("cursor", o._cursor);
1722
		}
1723
	}
1724
});
1725
1726
$.ui.plugin.add("draggable", "opacity", {
1727
	start: function(event, ui) {
1728
		var t = $(ui.helper), o = $(this).data("ui-draggable").options;
1729
		if(t.css("opacity")) {
1730
			o._opacity = t.css("opacity");
1731
		}
1732
		t.css("opacity", o.opacity);
1733
	},
1734
	stop: function(event, ui) {
1735
		var o = $(this).data("ui-draggable").options;
1736
		if(o._opacity) {
1737
			$(ui.helper).css("opacity", o._opacity);
1738
		}
1739
	}
1740
});
1741
1742
$.ui.plugin.add("draggable", "scroll", {
1743
	start: function() {
1744
		var i = $(this).data("ui-draggable");
1745
		if(i.scrollParent[0] !== document && i.scrollParent[0].tagName !== "HTML") {
1746
			i.overflowOffset = i.scrollParent.offset();
1747
		}
1748
	},
1749
	drag: function( event ) {
1750
1751
		var i = $(this).data("ui-draggable"), o = i.options, scrolled = false;
1752
1753
		if(i.scrollParent[0] !== document && i.scrollParent[0].tagName !== "HTML") {
1754
1755
			if(!o.axis || o.axis !== "x") {
1756
				if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) {
1757
					i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
1758
				} else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity) {
1759
					i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
1760
				}
1761
			}
1762
1763
			if(!o.axis || o.axis !== "y") {
1764
				if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) {
1765
					i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
1766
				} else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity) {
1767
					i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
1768
				}
1769
			}
1770
1771
		} else {
1772
1773
			if(!o.axis || o.axis !== "x") {
1774
				if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) {
1775
					scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
1776
				} else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) {
1777
					scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
1778
				}
1779
			}
1780
1781
			if(!o.axis || o.axis !== "y") {
1782
				if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) {
1783
					scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
1784
				} else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) {
1785
					scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
1786
				}
1787
			}
1788
1789
		}
1790
1791
		if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) {
1792
			$.ui.ddmanager.prepareOffsets(i, event);
1793
		}
1794
1795
	}
1796
});
1797
1798
$.ui.plugin.add("draggable", "snap", {
1799
	start: function() {
1800
1801
		var i = $(this).data("ui-draggable"),
1802
			o = i.options;
1803
1804
		i.snapElements = [];
1805
1806
		$(o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap).each(function() {
1807
			var $t = $(this),
1808
				$o = $t.offset();
1809
			if(this !== i.element[0]) {
1810
				i.snapElements.push({
1811
					item: this,
1812
					width: $t.outerWidth(), height: $t.outerHeight(),
1813
					top: $o.top, left: $o.left
1814
				});
1815
			}
1816
		});
1817
1818
	},
1819
	drag: function(event, ui) {
1820
1821
		var ts, bs, ls, rs, l, r, t, b, i, first,
1822
			inst = $(this).data("ui-draggable"),
1823
			o = inst.options,
1824
			d = o.snapTolerance,
1825
			x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
1826
			y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
1827
1828
		for (i = inst.snapElements.length - 1; i >= 0; i--){
1829
1830
			l = inst.snapElements[i].left;
1831
			r = l + inst.snapElements[i].width;
1832
			t = inst.snapElements[i].top;
1833
			b = t + inst.snapElements[i].height;
1834
1835
			if ( x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d || !$.contains( inst.snapElements[ i ].item.ownerDocument, inst.snapElements[ i ].item ) ) {
1836
				if(inst.snapElements[i].snapping) {
1837
					(inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
1838
				}
1839
				inst.snapElements[i].snapping = false;
1840
				continue;
1841
			}
1842
1843 View Code Duplication
			if(o.snapMode !== "inner") {
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
1844
				ts = Math.abs(t - y2) <= d;
1845
				bs = Math.abs(b - y1) <= d;
1846
				ls = Math.abs(l - x2) <= d;
1847
				rs = Math.abs(r - x1) <= d;
1848
				if(ts) {
1849
					ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
1850
				}
1851
				if(bs) {
1852
					ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
1853
				}
1854
				if(ls) {
1855
					ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
1856
				}
1857
				if(rs) {
1858
					ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
1859
				}
1860
			}
1861
1862
			first = (ts || bs || ls || rs);
1863
1864 View Code Duplication
			if(o.snapMode !== "outer") {
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
1865
				ts = Math.abs(t - y1) <= d;
1866
				bs = Math.abs(b - y2) <= d;
1867
				ls = Math.abs(l - x1) <= d;
1868
				rs = Math.abs(r - x2) <= d;
1869
				if(ts) {
1870
					ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
1871
				}
1872
				if(bs) {
1873
					ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
1874
				}
1875
				if(ls) {
1876
					ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
1877
				}
1878
				if(rs) {
1879
					ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
1880
				}
1881
			}
1882
1883
			if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first)) {
1884
				(inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
1885
			}
1886
			inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
1887
1888
		}
1889
1890
	}
1891
});
1892
1893
$.ui.plugin.add("draggable", "stack", {
1894
	start: function() {
1895
		var min,
1896
			o = this.data("ui-draggable").options,
1897
			group = $.makeArray($(o.stack)).sort(function(a,b) {
1898
				return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);
1899
			});
1900
1901
		if (!group.length) { return; }
1902
1903
		min = parseInt($(group[0]).css("zIndex"), 10) || 0;
1904
		$(group).each(function(i) {
1905
			$(this).css("zIndex", min + i);
1906
		});
1907
		this.css("zIndex", (min + group.length));
1908
	}
1909
});
1910
1911
$.ui.plugin.add("draggable", "zIndex", {
1912
	start: function(event, ui) {
1913
		var t = $(ui.helper), o = $(this).data("ui-draggable").options;
1914
		if(t.css("zIndex")) {
1915
			o._zIndex = t.css("zIndex");
1916
		}
1917
		t.css("zIndex", o.zIndex);
1918
	},
1919
	stop: function(event, ui) {
1920
		var o = $(this).data("ui-draggable").options;
1921
		if(o._zIndex) {
1922
			$(ui.helper).css("zIndex", o._zIndex);
1923
		}
1924
	}
1925
});
1926
1927
})(jQuery);
1928
1929
(function( $, undefined ) {
1930
1931
function isOverAxis( x, reference, size ) {
1932
	return ( x > reference ) && ( x < ( reference + size ) );
1933
}
1934
1935
$.widget("ui.droppable", {
1936
	version: "1.10.3",
1937
	widgetEventPrefix: "drop",
1938
	options: {
1939
		accept: "*",
1940
		activeClass: false,
1941
		addClasses: true,
1942
		greedy: false,
1943
		hoverClass: false,
1944
		scope: "default",
1945
		tolerance: "intersect",
1946
1947
		// callbacks
1948
		activate: null,
1949
		deactivate: null,
1950
		drop: null,
1951
		out: null,
1952
		over: null
1953
	},
1954
	_create: function() {
1955
1956
		var o = this.options,
1957
			accept = o.accept;
1958
1959
		this.isover = false;
1960
		this.isout = true;
1961
1962
		this.accept = $.isFunction(accept) ? accept : function(d) {
1963
			return d.is(accept);
1964
		};
1965
1966
		//Store the droppable's proportions
1967
		this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight };
1968
1969
		// Add the reference and positions to the manager
1970
		$.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || [];
1971
		$.ui.ddmanager.droppables[o.scope].push(this);
1972
1973
		(o.addClasses && this.element.addClass("ui-droppable"));
1974
1975
	},
1976
1977
	_destroy: function() {
1978
		var i = 0,
1979
			drop = $.ui.ddmanager.droppables[this.options.scope];
1980
1981
		for ( ; i < drop.length; i++ ) {
1982
			if ( drop[i] === this ) {
1983
				drop.splice(i, 1);
1984
			}
1985
		}
1986
1987
		this.element.removeClass("ui-droppable ui-droppable-disabled");
1988
	},
1989
1990
	_setOption: function(key, value) {
1991
1992
		if(key === "accept") {
1993
			this.accept = $.isFunction(value) ? value : function(d) {
1994
				return d.is(value);
1995
			};
1996
		}
1997
		$.Widget.prototype._setOption.apply(this, arguments);
1998
	},
1999
2000
	_activate: function(event) {
2001
		var draggable = $.ui.ddmanager.current;
2002
		if(this.options.activeClass) {
2003
			this.element.addClass(this.options.activeClass);
2004
		}
2005
		if(draggable){
2006
			this._trigger("activate", event, this.ui(draggable));
2007
		}
2008
	},
2009
2010
	_deactivate: function(event) {
2011
		var draggable = $.ui.ddmanager.current;
2012
		if(this.options.activeClass) {
2013
			this.element.removeClass(this.options.activeClass);
2014
		}
2015
		if(draggable){
2016
			this._trigger("deactivate", event, this.ui(draggable));
2017
		}
2018
	},
2019
2020
	_over: function(event) {
2021
2022
		var draggable = $.ui.ddmanager.current;
2023
2024
		// Bail if draggable and droppable are same element
2025
		if (!draggable || (draggable.currentItem || draggable.element)[0] === this.element[0]) {
2026
			return;
2027
		}
2028
2029
		if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
2030
			if(this.options.hoverClass) {
2031
				this.element.addClass(this.options.hoverClass);
2032
			}
2033
			this._trigger("over", event, this.ui(draggable));
2034
		}
2035
2036
	},
2037
2038
	_out: function(event) {
2039
2040
		var draggable = $.ui.ddmanager.current;
2041
2042
		// Bail if draggable and droppable are same element
2043
		if (!draggable || (draggable.currentItem || draggable.element)[0] === this.element[0]) {
2044
			return;
2045
		}
2046
2047
		if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
2048
			if(this.options.hoverClass) {
2049
				this.element.removeClass(this.options.hoverClass);
2050
			}
2051
			this._trigger("out", event, this.ui(draggable));
2052
		}
2053
2054
	},
2055
2056
	_drop: function(event,custom) {
2057
2058
		var draggable = custom || $.ui.ddmanager.current,
2059
			childrenIntersection = false;
2060
2061
		// Bail if draggable and droppable are same element
2062
		if (!draggable || (draggable.currentItem || draggable.element)[0] === this.element[0]) {
2063
			return false;
2064
		}
2065
2066
		this.element.find(":data(ui-droppable)").not(".ui-draggable-dragging").each(function() {
2067
			var inst = $.data(this, "ui-droppable");
2068
			if(
2069
				inst.options.greedy &&
2070
				!inst.options.disabled &&
2071
				inst.options.scope === draggable.options.scope &&
2072
				inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element)) &&
2073
				$.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)
2074
			) { childrenIntersection = true; return false; }
2075
		});
2076
		if(childrenIntersection) {
2077
			return false;
2078
		}
2079
2080
		if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
2081
			if(this.options.activeClass) {
2082
				this.element.removeClass(this.options.activeClass);
2083
			}
2084
			if(this.options.hoverClass) {
2085
				this.element.removeClass(this.options.hoverClass);
2086
			}
2087
			this._trigger("drop", event, this.ui(draggable));
2088
			return this.element;
2089
		}
2090
2091
		return false;
2092
2093
	},
2094
2095
	ui: function(c) {
2096
		return {
2097
			draggable: (c.currentItem || c.element),
2098
			helper: c.helper,
2099
			position: c.position,
2100
			offset: c.positionAbs
2101
		};
2102
	}
2103
2104
});
2105
2106
$.ui.intersect = function(draggable, droppable, toleranceMode) {
2107
2108
	if (!droppable.offset) {
2109
		return false;
2110
	}
2111
2112
	var draggableLeft, draggableTop,
2113
		x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width,
2114
		y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height,
2115
		l = droppable.offset.left, r = l + droppable.proportions.width,
2116
		t = droppable.offset.top, b = t + droppable.proportions.height;
2117
2118
	switch (toleranceMode) {
2119
		case "fit":
2120
			return (l <= x1 && x2 <= r && t <= y1 && y2 <= b);
2121
		case "intersect":
2122
			return (l < x1 + (draggable.helperProportions.width / 2) && // Right Half
2123
				x2 - (draggable.helperProportions.width / 2) < r && // Left Half
2124
				t < y1 + (draggable.helperProportions.height / 2) && // Bottom Half
2125
				y2 - (draggable.helperProportions.height / 2) < b ); // Top Half
2126
		case "pointer":
2127
			draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left);
2128
			draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top);
2129
			return isOverAxis( draggableTop, t, droppable.proportions.height ) && isOverAxis( draggableLeft, l, droppable.proportions.width );
2130
		case "touch":
2131
			return (
2132
				(y1 >= t && y1 <= b) ||	// Top edge touching
2133
				(y2 >= t && y2 <= b) ||	// Bottom edge touching
2134
				(y1 < t && y2 > b)		// Surrounded vertically
2135
			) && (
2136
				(x1 >= l && x1 <= r) ||	// Left edge touching
2137
				(x2 >= l && x2 <= r) ||	// Right edge touching
2138
				(x1 < l && x2 > r)		// Surrounded horizontally
2139
			);
2140
		default:
2141
			return false;
2142
		}
2143
2144
};
2145
2146
/*
2147
	This manager tracks offsets of draggables and droppables
2148
*/
2149
$.ui.ddmanager = {
2150
	current: null,
2151
	droppables: { "default": [] },
2152
	prepareOffsets: function(t, event) {
2153
2154
		var i, j,
2155
			m = $.ui.ddmanager.droppables[t.options.scope] || [],
2156
			type = event ? event.type : null, // workaround for #2317
2157
			list = (t.currentItem || t.element).find(":data(ui-droppable)").addBack();
2158
2159
		droppablesLoop: for (i = 0; i < m.length; i++) {
2160
2161
			//No disabled and non-accepted
2162
			if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) {
2163
				continue;
2164
			}
2165
2166
			// Filter out elements in the current dragged item
2167
			for (j=0; j < list.length; j++) {
2168
				if(list[j] === m[i].element[0]) {
2169
					m[i].proportions.height = 0;
2170
					continue droppablesLoop;
2171
				}
2172
			}
2173
2174
			m[i].visible = m[i].element.css("display") !== "none";
2175
			if(!m[i].visible) {
2176
				continue;
2177
			}
2178
2179
			//Activate the droppable if used directly from draggables
2180
			if(type === "mousedown") {
2181
				m[i]._activate.call(m[i], event);
2182
			}
2183
2184
			m[i].offset = m[i].element.offset();
2185
			m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };
2186
2187
		}
2188
2189
	},
2190
	drop: function(draggable, event) {
2191
2192
		var dropped = false;
2193
		// Create a copy of the droppables in case the list changes during the drop (#9116)
2194
		$.each(($.ui.ddmanager.droppables[draggable.options.scope] || []).slice(), function() {
2195
2196
			if(!this.options) {
2197
				return;
2198
			}
2199
			if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance)) {
2200
				dropped = this._drop.call(this, event) || dropped;
2201
			}
2202
2203
			if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
2204
				this.isout = true;
2205
				this.isover = false;
2206
				this._deactivate.call(this, event);
2207
			}
2208
2209
		});
2210
		return dropped;
2211
2212
	},
2213
	dragStart: function( draggable, event ) {
2214
		//Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003)
2215
		draggable.element.parentsUntil( "body" ).bind( "scroll.droppable", function() {
2216
			if( !draggable.options.refreshPositions ) {
2217
				$.ui.ddmanager.prepareOffsets( draggable, event );
2218
			}
2219
		});
2220
	},
2221
	drag: function(draggable, event) {
2222
2223
		//If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
2224
		if(draggable.options.refreshPositions) {
2225
			$.ui.ddmanager.prepareOffsets(draggable, event);
2226
		}
2227
2228
		//Run through all droppables and check their positions based on specific tolerance options
2229
		$.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
2230
2231
			if(this.options.disabled || this.greedyChild || !this.visible) {
2232
				return;
2233
			}
2234
2235
			var parentInstance, scope, parent,
2236
				intersects = $.ui.intersect(draggable, this, this.options.tolerance),
2237
				c = !intersects && this.isover ? "isout" : (intersects && !this.isover ? "isover" : null);
2238
			if(!c) {
2239
				return;
2240
			}
2241
2242
			if (this.options.greedy) {
2243
				// find droppable parents with same scope
2244
				scope = this.options.scope;
2245
				parent = this.element.parents(":data(ui-droppable)").filter(function () {
2246
					return $.data(this, "ui-droppable").options.scope === scope;
2247
				});
2248
2249
				if (parent.length) {
2250
					parentInstance = $.data(parent[0], "ui-droppable");
2251
					parentInstance.greedyChild = (c === "isover");
2252
				}
2253
			}
2254
2255
			// we just moved into a greedy child
2256
			if (parentInstance && c === "isover") {
2257
				parentInstance.isover = false;
2258
				parentInstance.isout = true;
2259
				parentInstance._out.call(parentInstance, event);
2260
			}
2261
2262
			this[c] = true;
2263
			this[c === "isout" ? "isover" : "isout"] = false;
2264
			this[c === "isover" ? "_over" : "_out"].call(this, event);
2265
2266
			// we just moved out of a greedy child
2267
			if (parentInstance && c === "isout") {
2268
				parentInstance.isout = false;
2269
				parentInstance.isover = true;
2270
				parentInstance._over.call(parentInstance, event);
2271
			}
2272
		});
2273
2274
	},
2275
	dragStop: function( draggable, event ) {
2276
		draggable.element.parentsUntil( "body" ).unbind( "scroll.droppable" );
2277
		//Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003)
2278
		if( !draggable.options.refreshPositions ) {
2279
			$.ui.ddmanager.prepareOffsets( draggable, event );
2280
		}
2281
	}
2282
};
2283
2284
})(jQuery);
2285
2286
(function( $, undefined ) {
2287
2288
function num(v) {
2289
	return parseInt(v, 10) || 0;
2290
}
2291
2292
function isNumber(value) {
2293
	return !isNaN(parseInt(value, 10));
2294
}
2295
2296
$.widget("ui.resizable", $.ui.mouse, {
2297
	version: "1.10.3",
2298
	widgetEventPrefix: "resize",
2299
	options: {
2300
		alsoResize: false,
2301
		animate: false,
2302
		animateDuration: "slow",
2303
		animateEasing: "swing",
2304
		aspectRatio: false,
2305
		autoHide: false,
2306
		containment: false,
2307
		ghost: false,
2308
		grid: false,
2309
		handles: "e,s,se",
2310
		helper: false,
2311
		maxHeight: null,
2312
		maxWidth: null,
2313
		minHeight: 10,
2314
		minWidth: 10,
2315
		// See #7960
2316
		zIndex: 90,
2317
2318
		// callbacks
2319
		resize: null,
2320
		start: null,
2321
		stop: null
2322
	},
2323
	_create: function() {
2324
2325
		var n, i, handle, axis, hname,
2326
			that = this,
2327
			o = this.options;
2328
		this.element.addClass("ui-resizable");
2329
2330
		$.extend(this, {
2331
			_aspectRatio: !!(o.aspectRatio),
2332
			aspectRatio: o.aspectRatio,
2333
			originalElement: this.element,
2334
			_proportionallyResizeElements: [],
2335
			_helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null
2336
		});
2337
2338
		//Wrap the element if it cannot hold child nodes
2339
		if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {
2340
2341
			//Create a wrapper element and set the wrapper to the new current internal element
2342
			this.element.wrap(
2343
				$("<div class='ui-wrapper' style='overflow: hidden;'></div>").css({
2344
					position: this.element.css("position"),
2345
					width: this.element.outerWidth(),
2346
					height: this.element.outerHeight(),
2347
					top: this.element.css("top"),
2348
					left: this.element.css("left")
2349
				})
2350
			);
2351
2352
			//Overwrite the original this.element
2353
			this.element = this.element.parent().data(
2354
				"ui-resizable", this.element.data("ui-resizable")
2355
			);
2356
2357
			this.elementIsWrapper = true;
2358
2359
			//Move margins to the wrapper
2360
			this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") });
2361
			this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
2362
2363
			//Prevent Safari textarea resize
2364
			this.originalResizeStyle = this.originalElement.css("resize");
2365
			this.originalElement.css("resize", "none");
2366
2367
			//Push the actual element to our proportionallyResize internal array
2368
			this._proportionallyResizeElements.push(this.originalElement.css({ position: "static", zoom: 1, display: "block" }));
2369
2370
			// avoid IE jump (hard set the margin)
2371
			this.originalElement.css({ margin: this.originalElement.css("margin") });
2372
2373
			// fix handlers offset
2374
			this._proportionallyResize();
2375
2376
		}
2377
2378
		this.handles = o.handles || (!$(".ui-resizable-handle", this.element).length ? "e,s,se" : { n: ".ui-resizable-n", e: ".ui-resizable-e", s: ".ui-resizable-s", w: ".ui-resizable-w", se: ".ui-resizable-se", sw: ".ui-resizable-sw", ne: ".ui-resizable-ne", nw: ".ui-resizable-nw" });
2379
		if(this.handles.constructor === String) {
2380
2381
			if ( this.handles === "all") {
2382
				this.handles = "n,e,s,w,se,sw,ne,nw";
2383
			}
2384
2385
			n = this.handles.split(",");
2386
			this.handles = {};
2387
2388
			for(i = 0; i < n.length; i++) {
2389
2390
				handle = $.trim(n[i]);
2391
				hname = "ui-resizable-"+handle;
2392
				axis = $("<div class='ui-resizable-handle " + hname + "'></div>");
2393
2394
				// Apply zIndex to all handles - see #7960
2395
				axis.css({ zIndex: o.zIndex });
2396
2397
				//TODO : What's going on here?
2398
				if ("se" === handle) {
2399
					axis.addClass("ui-icon ui-icon-gripsmall-diagonal-se");
2400
				}
2401
2402
				//Insert into internal handles object and append to element
2403
				this.handles[handle] = ".ui-resizable-"+handle;
2404
				this.element.append(axis);
2405
			}
2406
2407
		}
2408
2409
		this._renderAxis = function(target) {
2410
2411
			var i, axis, padPos, padWrapper;
2412
2413
			target = target || this.element;
2414
2415
			for(i in this.handles) {
2416
2417
				if(this.handles[i].constructor === String) {
2418
					this.handles[i] = $(this.handles[i], this.element).show();
2419
				}
2420
2421
				//Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
2422
				if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {
2423
2424
					axis = $(this.handles[i], this.element);
2425
2426
					//Checking the correct pad and border
2427
					padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
2428
2429
					//The padding type i have to apply...
2430
					padPos = [ "padding",
2431
						/ne|nw|n/.test(i) ? "Top" :
2432
						/se|sw|s/.test(i) ? "Bottom" :
2433
						/^e$/.test(i) ? "Right" : "Left" ].join("");
2434
2435
					target.css(padPos, padWrapper);
2436
2437
					this._proportionallyResize();
2438
2439
				}
2440
2441
				//TODO: What's that good for? There's not anything to be executed left
2442
				if(!$(this.handles[i]).length) {
2443
					continue;
2444
				}
2445
			}
2446
		};
2447
2448
		//TODO: make renderAxis a prototype function
2449
		this._renderAxis(this.element);
2450
2451
		this._handles = $(".ui-resizable-handle", this.element)
2452
			.disableSelection();
2453
2454
		//Matching axis name
2455
		this._handles.mouseover(function() {
2456
			if (!that.resizing) {
2457
				if (this.className) {
2458
					axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
2459
				}
2460
				//Axis, default = se
2461
				that.axis = axis && axis[1] ? axis[1] : "se";
2462
			}
2463
		});
2464
2465
		//If we want to auto hide the elements
2466
		if (o.autoHide) {
2467
			this._handles.hide();
2468
			$(this.element)
2469
				.addClass("ui-resizable-autohide")
2470
				.mouseenter(function() {
2471
					if (o.disabled) {
2472
						return;
2473
					}
2474
					$(this).removeClass("ui-resizable-autohide");
2475
					that._handles.show();
2476
				})
2477
				.mouseleave(function(){
2478
					if (o.disabled) {
2479
						return;
2480
					}
2481
					if (!that.resizing) {
2482
						$(this).addClass("ui-resizable-autohide");
2483
						that._handles.hide();
2484
					}
2485
				});
2486
		}
2487
2488
		//Initialize the mouse interaction
2489
		this._mouseInit();
2490
2491
	},
2492
2493
	_destroy: function() {
2494
2495
		this._mouseDestroy();
2496
2497
		var wrapper,
2498
			_destroy = function(exp) {
2499
				$(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
2500
					.removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove();
2501
			};
2502
2503
		//TODO: Unwrap at same DOM position
2504
		if (this.elementIsWrapper) {
2505
			_destroy(this.element);
2506
			wrapper = this.element;
2507
			this.originalElement.css({
2508
				position: wrapper.css("position"),
2509
				width: wrapper.outerWidth(),
2510
				height: wrapper.outerHeight(),
2511
				top: wrapper.css("top"),
2512
				left: wrapper.css("left")
2513
			}).insertAfter( wrapper );
2514
			wrapper.remove();
2515
		}
2516
2517
		this.originalElement.css("resize", this.originalResizeStyle);
2518
		_destroy(this.originalElement);
2519
2520
		return this;
2521
	},
2522
2523
	_mouseCapture: function(event) {
2524
		var i, handle,
2525
			capture = false;
2526
2527
		for (i in this.handles) {
2528
			handle = $(this.handles[i])[0];
2529
			if (handle === event.target || $.contains(handle, event.target)) {
2530
				capture = true;
2531
			}
2532
		}
2533
2534
		return !this.options.disabled && capture;
2535
	},
2536
2537
	_mouseStart: function(event) {
2538
2539
		var curleft, curtop, cursor,
2540
			o = this.options,
2541
			iniPos = this.element.position(),
2542
			el = this.element;
2543
2544
		this.resizing = true;
2545
2546
		// bugfix for http://dev.jquery.com/ticket/1749
2547
		if ( (/absolute/).test( el.css("position") ) ) {
2548
			el.css({ position: "absolute", top: el.css("top"), left: el.css("left") });
2549
		} else if (el.is(".ui-draggable")) {
2550
			el.css({ position: "absolute", top: iniPos.top, left: iniPos.left });
2551
		}
2552
2553
		this._renderProxy();
2554
2555
		curleft = num(this.helper.css("left"));
2556
		curtop = num(this.helper.css("top"));
2557
2558
		if (o.containment) {
2559
			curleft += $(o.containment).scrollLeft() || 0;
2560
			curtop += $(o.containment).scrollTop() || 0;
2561
		}
2562
2563
		//Store needed variables
2564
		this.offset = this.helper.offset();
2565
		this.position = { left: curleft, top: curtop };
2566
		this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
2567
		this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
2568
		this.originalPosition = { left: curleft, top: curtop };
2569
		this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
2570
		this.originalMousePosition = { left: event.pageX, top: event.pageY };
2571
2572
		//Aspect Ratio
2573
		this.aspectRatio = (typeof o.aspectRatio === "number") ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);
2574
2575
		cursor = $(".ui-resizable-" + this.axis).css("cursor");
2576
		$("body").css("cursor", cursor === "auto" ? this.axis + "-resize" : cursor);
2577
2578
		el.addClass("ui-resizable-resizing");
2579
		this._propagate("start", event);
2580
		return true;
2581
	},
2582
2583
	_mouseDrag: function(event) {
2584
2585
		//Increase performance, avoid regex
2586
		var data,
2587
			el = this.helper, props = {},
2588
			smp = this.originalMousePosition,
2589
			a = this.axis,
2590
			prevTop = this.position.top,
2591
			prevLeft = this.position.left,
2592
			prevWidth = this.size.width,
2593
			prevHeight = this.size.height,
2594
			dx = (event.pageX-smp.left)||0,
2595
			dy = (event.pageY-smp.top)||0,
2596
			trigger = this._change[a];
2597
2598
		if (!trigger) {
2599
			return false;
2600
		}
2601
2602
		// Calculate the attrs that will be change
2603
		data = trigger.apply(this, [event, dx, dy]);
2604
2605
		// Put this in the mouseDrag handler since the user can start pressing shift while resizing
2606
		this._updateVirtualBoundaries(event.shiftKey);
2607
		if (this._aspectRatio || event.shiftKey) {
2608
			data = this._updateRatio(data, event);
2609
		}
2610
2611
		data = this._respectSize(data, event);
2612
2613
		this._updateCache(data);
2614
2615
		// plugins callbacks need to be called first
2616
		this._propagate("resize", event);
2617
2618
		if (this.position.top !== prevTop) {
2619
			props.top = this.position.top + "px";
2620
		}
2621
		if (this.position.left !== prevLeft) {
2622
			props.left = this.position.left + "px";
2623
		}
2624
		if (this.size.width !== prevWidth) {
2625
			props.width = this.size.width + "px";
2626
		}
2627
		if (this.size.height !== prevHeight) {
2628
			props.height = this.size.height + "px";
2629
		}
2630
		el.css(props);
2631
2632
		if (!this._helper && this._proportionallyResizeElements.length) {
2633
			this._proportionallyResize();
2634
		}
2635
2636
		// Call the user callback if the element was resized
2637
		if ( ! $.isEmptyObject(props) ) {
2638
			this._trigger("resize", event, this.ui());
2639
		}
2640
2641
		return false;
2642
	},
2643
2644
	_mouseStop: function(event) {
2645
2646
		this.resizing = false;
2647
		var pr, ista, soffseth, soffsetw, s, left, top,
2648
			o = this.options, that = this;
2649
2650
		if(this._helper) {
2651
2652
			pr = this._proportionallyResizeElements;
2653
			ista = pr.length && (/textarea/i).test(pr[0].nodeName);
2654
			soffseth = ista && $.ui.hasScroll(pr[0], "left") /* TODO - jump height */ ? 0 : that.sizeDiff.height;
2655
			soffsetw = ista ? 0 : that.sizeDiff.width;
2656
2657
			s = { width: (that.helper.width()  - soffsetw), height: (that.helper.height() - soffseth) };
2658
			left = (parseInt(that.element.css("left"), 10) + (that.position.left - that.originalPosition.left)) || null;
2659
			top = (parseInt(that.element.css("top"), 10) + (that.position.top - that.originalPosition.top)) || null;
2660
2661
			if (!o.animate) {
2662
				this.element.css($.extend(s, { top: top, left: left }));
2663
			}
2664
2665
			that.helper.height(that.size.height);
2666
			that.helper.width(that.size.width);
2667
2668
			if (this._helper && !o.animate) {
2669
				this._proportionallyResize();
2670
			}
2671
		}
2672
2673
		$("body").css("cursor", "auto");
2674
2675
		this.element.removeClass("ui-resizable-resizing");
2676
2677
		this._propagate("stop", event);
2678
2679
		if (this._helper) {
2680
			this.helper.remove();
2681
		}
2682
2683
		return false;
2684
2685
	},
2686
2687
	_updateVirtualBoundaries: function(forceAspectRatio) {
2688
		var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b,
2689
			o = this.options;
2690
2691
		b = {
2692
			minWidth: isNumber(o.minWidth) ? o.minWidth : 0,
2693
			maxWidth: isNumber(o.maxWidth) ? o.maxWidth : Infinity,
2694
			minHeight: isNumber(o.minHeight) ? o.minHeight : 0,
2695
			maxHeight: isNumber(o.maxHeight) ? o.maxHeight : Infinity
2696
		};
2697
2698
		if(this._aspectRatio || forceAspectRatio) {
2699
			// We want to create an enclosing box whose aspect ration is the requested one
2700
			// First, compute the "projected" size for each dimension based on the aspect ratio and other dimension
2701
			pMinWidth = b.minHeight * this.aspectRatio;
2702
			pMinHeight = b.minWidth / this.aspectRatio;
2703
			pMaxWidth = b.maxHeight * this.aspectRatio;
2704
			pMaxHeight = b.maxWidth / this.aspectRatio;
2705
2706
			if(pMinWidth > b.minWidth) {
2707
				b.minWidth = pMinWidth;
2708
			}
2709
			if(pMinHeight > b.minHeight) {
2710
				b.minHeight = pMinHeight;
2711
			}
2712
			if(pMaxWidth < b.maxWidth) {
2713
				b.maxWidth = pMaxWidth;
2714
			}
2715
			if(pMaxHeight < b.maxHeight) {
2716
				b.maxHeight = pMaxHeight;
2717
			}
2718
		}
2719
		this._vBoundaries = b;
2720
	},
2721
2722
	_updateCache: function(data) {
2723
		this.offset = this.helper.offset();
2724
		if (isNumber(data.left)) {
2725
			this.position.left = data.left;
2726
		}
2727
		if (isNumber(data.top)) {
2728
			this.position.top = data.top;
2729
		}
2730
		if (isNumber(data.height)) {
2731
			this.size.height = data.height;
2732
		}
2733
		if (isNumber(data.width)) {
2734
			this.size.width = data.width;
2735
		}
2736
	},
2737
2738
	_updateRatio: function( data ) {
2739
2740
		var cpos = this.position,
2741
			csize = this.size,
2742
			a = this.axis;
2743
2744
		if (isNumber(data.height)) {
2745
			data.width = (data.height * this.aspectRatio);
2746
		} else if (isNumber(data.width)) {
2747
			data.height = (data.width / this.aspectRatio);
2748
		}
2749
2750
		if (a === "sw") {
2751
			data.left = cpos.left + (csize.width - data.width);
2752
			data.top = null;
2753
		}
2754
		if (a === "nw") {
2755
			data.top = cpos.top + (csize.height - data.height);
2756
			data.left = cpos.left + (csize.width - data.width);
2757
		}
2758
2759
		return data;
2760
	},
2761
2762
	_respectSize: function( data ) {
2763
2764
		var o = this._vBoundaries,
2765
			a = this.axis,
2766
			ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
2767
			isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height),
2768
			dw = this.originalPosition.left + this.originalSize.width,
2769
			dh = this.position.top + this.size.height,
2770
			cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
2771
		if (isminw) {
2772
			data.width = o.minWidth;
2773
		}
2774
		if (isminh) {
2775
			data.height = o.minHeight;
2776
		}
2777
		if (ismaxw) {
2778
			data.width = o.maxWidth;
2779
		}
2780
		if (ismaxh) {
2781
			data.height = o.maxHeight;
2782
		}
2783
2784
		if (isminw && cw) {
2785
			data.left = dw - o.minWidth;
2786
		}
2787
		if (ismaxw && cw) {
2788
			data.left = dw - o.maxWidth;
2789
		}
2790
		if (isminh && ch) {
2791
			data.top = dh - o.minHeight;
2792
		}
2793
		if (ismaxh && ch) {
2794
			data.top = dh - o.maxHeight;
2795
		}
2796
2797
		// fixing jump error on top/left - bug #2330
2798
		if (!data.width && !data.height && !data.left && data.top) {
2799
			data.top = null;
2800
		} else if (!data.width && !data.height && !data.top && data.left) {
2801
			data.left = null;
2802
		}
2803
2804
		return data;
2805
	},
2806
2807
	_proportionallyResize: function() {
2808
2809
		if (!this._proportionallyResizeElements.length) {
2810
			return;
2811
		}
2812
2813
		var i, j, borders, paddings, prel,
2814
			element = this.helper || this.element;
2815
2816
		for ( i=0; i < this._proportionallyResizeElements.length; i++) {
2817
2818
			prel = this._proportionallyResizeElements[i];
2819
2820
			if (!this.borderDif) {
2821
				this.borderDif = [];
2822
				borders = [prel.css("borderTopWidth"), prel.css("borderRightWidth"), prel.css("borderBottomWidth"), prel.css("borderLeftWidth")];
2823
				paddings = [prel.css("paddingTop"), prel.css("paddingRight"), prel.css("paddingBottom"), prel.css("paddingLeft")];
2824
2825
				for ( j = 0; j < borders.length; j++ ) {
2826
					this.borderDif[ j ] = ( parseInt( borders[ j ], 10 ) || 0 ) + ( parseInt( paddings[ j ], 10 ) || 0 );
2827
				}
2828
			}
2829
2830
			prel.css({
2831
				height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,
2832
				width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0
2833
			});
2834
2835
		}
2836
2837
	},
2838
2839
	_renderProxy: function() {
2840
2841
		var el = this.element, o = this.options;
2842
		this.elementOffset = el.offset();
2843
2844
		if(this._helper) {
2845
2846
			this.helper = this.helper || $("<div style='overflow:hidden;'></div>");
2847
2848
			this.helper.addClass(this._helper).css({
2849
				width: this.element.outerWidth() - 1,
2850
				height: this.element.outerHeight() - 1,
2851
				position: "absolute",
2852
				left: this.elementOffset.left +"px",
2853
				top: this.elementOffset.top +"px",
2854
				zIndex: ++o.zIndex //TODO: Don't modify option
2855
			});
2856
2857
			this.helper
2858
				.appendTo("body")
2859
				.disableSelection();
2860
2861
		} else {
2862
			this.helper = this.element;
2863
		}
2864
2865
	},
2866
2867
	_change: {
2868
		e: function(event, dx) {
2869
			return { width: this.originalSize.width + dx };
2870
		},
2871
		w: function(event, dx) {
2872
			var cs = this.originalSize, sp = this.originalPosition;
2873
			return { left: sp.left + dx, width: cs.width - dx };
2874
		},
2875
		n: function(event, dx, dy) {
2876
			var cs = this.originalSize, sp = this.originalPosition;
2877
			return { top: sp.top + dy, height: cs.height - dy };
2878
		},
2879
		s: function(event, dx, dy) {
2880
			return { height: this.originalSize.height + dy };
2881
		},
2882
		se: function(event, dx, dy) {
2883
			return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
2884
		},
2885
		sw: function(event, dx, dy) {
2886
			return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
2887
		},
2888
		ne: function(event, dx, dy) {
2889
			return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
2890
		},
2891
		nw: function(event, dx, dy) {
2892
			return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
2893
		}
2894
	},
2895
2896
	_propagate: function(n, event) {
2897
		$.ui.plugin.call(this, n, [event, this.ui()]);
2898
		(n !== "resize" && this._trigger(n, event, this.ui()));
2899
	},
2900
2901
	plugins: {},
2902
2903
	ui: function() {
2904
		return {
2905
			originalElement: this.originalElement,
2906
			element: this.element,
2907
			helper: this.helper,
2908
			position: this.position,
2909
			size: this.size,
2910
			originalSize: this.originalSize,
2911
			originalPosition: this.originalPosition
2912
		};
2913
	}
2914
2915
});
2916
2917
/*
2918
 * Resizable Extensions
2919
 */
2920
2921
$.ui.plugin.add("resizable", "animate", {
2922
2923
	stop: function( event ) {
2924
		var that = $(this).data("ui-resizable"),
2925
			o = that.options,
2926
			pr = that._proportionallyResizeElements,
2927
			ista = pr.length && (/textarea/i).test(pr[0].nodeName),
2928
			soffseth = ista && $.ui.hasScroll(pr[0], "left") /* TODO - jump height */ ? 0 : that.sizeDiff.height,
2929
			soffsetw = ista ? 0 : that.sizeDiff.width,
2930
			style = { width: (that.size.width - soffsetw), height: (that.size.height - soffseth) },
2931
			left = (parseInt(that.element.css("left"), 10) + (that.position.left - that.originalPosition.left)) || null,
2932
			top = (parseInt(that.element.css("top"), 10) + (that.position.top - that.originalPosition.top)) || null;
2933
2934
		that.element.animate(
2935
			$.extend(style, top && left ? { top: top, left: left } : {}), {
2936
				duration: o.animateDuration,
2937
				easing: o.animateEasing,
2938
				step: function() {
2939
2940
					var data = {
2941
						width: parseInt(that.element.css("width"), 10),
2942
						height: parseInt(that.element.css("height"), 10),
2943
						top: parseInt(that.element.css("top"), 10),
2944
						left: parseInt(that.element.css("left"), 10)
2945
					};
2946
2947
					if (pr && pr.length) {
2948
						$(pr[0]).css({ width: data.width, height: data.height });
2949
					}
2950
2951
					// propagating resize, and updating values for each animation step
2952
					that._updateCache(data);
2953
					that._propagate("resize", event);
2954
2955
				}
2956
			}
2957
		);
2958
	}
2959
2960
});
2961
2962
$.ui.plugin.add("resizable", "containment", {
2963
2964
	start: function() {
2965
		var element, p, co, ch, cw, width, height,
2966
			that = $(this).data("ui-resizable"),
2967
			o = that.options,
2968
			el = that.element,
2969
			oc = o.containment,
2970
			ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
2971
2972
		if (!ce) {
2973
			return;
2974
		}
2975
2976
		that.containerElement = $(ce);
2977
2978
		if (/document/.test(oc) || oc === document) {
2979
			that.containerOffset = { left: 0, top: 0 };
2980
			that.containerPosition = { left: 0, top: 0 };
2981
2982
			that.parentData = {
2983
				element: $(document), left: 0, top: 0,
2984
				width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight
2985
			};
2986
		}
2987
2988
		// i'm a node, so compute top, left, right, bottom
2989
		else {
2990
			element = $(ce);
2991
			p = [];
2992
			$([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); });
2993
2994
			that.containerOffset = element.offset();
2995
			that.containerPosition = element.position();
2996
			that.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };
2997
2998
			co = that.containerOffset;
2999
			ch = that.containerSize.height;
3000
			cw = that.containerSize.width;
3001
			width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw );
3002
			height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);
3003
3004
			that.parentData = {
3005
				element: ce, left: co.left, top: co.top, width: width, height: height
3006
			};
3007
		}
3008
	},
3009
3010
	resize: function( event ) {
3011
		var woset, hoset, isParent, isOffsetRelative,
3012
			that = $(this).data("ui-resizable"),
3013
			o = that.options,
3014
			co = that.containerOffset, cp = that.position,
3015
			pRatio = that._aspectRatio || event.shiftKey,
3016
			cop = { top:0, left:0 }, ce = that.containerElement;
3017
3018
		if (ce[0] !== document && (/static/).test(ce.css("position"))) {
3019
			cop = co;
3020
		}
3021
3022
		if (cp.left < (that._helper ? co.left : 0)) {
3023
			that.size.width = that.size.width + (that._helper ? (that.position.left - co.left) : (that.position.left - cop.left));
3024
			if (pRatio) {
3025
				that.size.height = that.size.width / that.aspectRatio;
3026
			}
3027
			that.position.left = o.helper ? co.left : 0;
3028
		}
3029
3030
		if (cp.top < (that._helper ? co.top : 0)) {
3031
			that.size.height = that.size.height + (that._helper ? (that.position.top - co.top) : that.position.top);
3032
			if (pRatio) {
3033
				that.size.width = that.size.height * that.aspectRatio;
3034
			}
3035
			that.position.top = that._helper ? co.top : 0;
3036
		}
3037
3038
		that.offset.left = that.parentData.left+that.position.left;
3039
		that.offset.top = that.parentData.top+that.position.top;
3040
3041
		woset = Math.abs( (that._helper ? that.offset.left - cop.left : (that.offset.left - cop.left)) + that.sizeDiff.width );
3042
		hoset = Math.abs( (that._helper ? that.offset.top - cop.top : (that.offset.top - co.top)) + that.sizeDiff.height );
3043
3044
		isParent = that.containerElement.get(0) === that.element.parent().get(0);
3045
		isOffsetRelative = /relative|absolute/.test(that.containerElement.css("position"));
3046
3047
		if(isParent && isOffsetRelative) {
3048
			woset -= that.parentData.left;
3049
		}
3050
3051
		if (woset + that.size.width >= that.parentData.width) {
3052
			that.size.width = that.parentData.width - woset;
3053
			if (pRatio) {
3054
				that.size.height = that.size.width / that.aspectRatio;
3055
			}
3056
		}
3057
3058
		if (hoset + that.size.height >= that.parentData.height) {
3059
			that.size.height = that.parentData.height - hoset;
3060
			if (pRatio) {
3061
				that.size.width = that.size.height * that.aspectRatio;
3062
			}
3063
		}
3064
	},
3065
3066
	stop: function(){
3067
		var that = $(this).data("ui-resizable"),
3068
			o = that.options,
3069
			co = that.containerOffset,
3070
			cop = that.containerPosition,
3071
			ce = that.containerElement,
3072
			helper = $(that.helper),
3073
			ho = helper.offset(),
3074
			w = helper.outerWidth() - that.sizeDiff.width,
3075
			h = helper.outerHeight() - that.sizeDiff.height;
3076
3077
		if (that._helper && !o.animate && (/relative/).test(ce.css("position"))) {
3078
			$(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
3079
		}
3080
3081
		if (that._helper && !o.animate && (/static/).test(ce.css("position"))) {
3082
			$(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
3083
		}
3084
3085
	}
3086
});
3087
3088
$.ui.plugin.add("resizable", "alsoResize", {
3089
3090
	start: function () {
3091
		var that = $(this).data("ui-resizable"),
3092
			o = that.options,
3093
			_store = function (exp) {
3094
				$(exp).each(function() {
3095
					var el = $(this);
3096
					el.data("ui-resizable-alsoresize", {
3097
						width: parseInt(el.width(), 10), height: parseInt(el.height(), 10),
3098
						left: parseInt(el.css("left"), 10), top: parseInt(el.css("top"), 10)
3099
					});
3100
				});
3101
			};
3102
3103
		if (typeof(o.alsoResize) === "object" && !o.alsoResize.parentNode) {
3104
			if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); }
3105
			else { $.each(o.alsoResize, function (exp) { _store(exp); }); }
3106
		}else{
3107
			_store(o.alsoResize);
3108
		}
3109
	},
3110
3111
	resize: function (event, ui) {
3112
		var that = $(this).data("ui-resizable"),
3113
			o = that.options,
3114
			os = that.originalSize,
3115
			op = that.originalPosition,
3116
			delta = {
3117
				height: (that.size.height - os.height) || 0, width: (that.size.width - os.width) || 0,
3118
				top: (that.position.top - op.top) || 0, left: (that.position.left - op.left) || 0
3119
			},
3120
3121
			_alsoResize = function (exp, c) {
3122
				$(exp).each(function() {
3123
					var el = $(this), start = $(this).data("ui-resizable-alsoresize"), style = {},
3124
						css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ["width", "height"] : ["width", "height", "top", "left"];
3125
3126
					$.each(css, function (i, prop) {
3127
						var sum = (start[prop]||0) + (delta[prop]||0);
3128
						if (sum && sum >= 0) {
3129
							style[prop] = sum || null;
3130
						}
3131
					});
3132
3133
					el.css(style);
3134
				});
3135
			};
3136
3137
		if (typeof(o.alsoResize) === "object" && !o.alsoResize.nodeType) {
3138
			$.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); });
3139
		}else{
3140
			_alsoResize(o.alsoResize);
3141
		}
3142
	},
3143
3144
	stop: function () {
3145
		$(this).removeData("resizable-alsoresize");
3146
	}
3147
});
3148
3149
$.ui.plugin.add("resizable", "ghost", {
3150
3151
	start: function() {
3152
3153
		var that = $(this).data("ui-resizable"), o = that.options, cs = that.size;
3154
3155
		that.ghost = that.originalElement.clone();
3156
		that.ghost
3157
			.css({ opacity: 0.25, display: "block", position: "relative", height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })
3158
			.addClass("ui-resizable-ghost")
3159
			.addClass(typeof o.ghost === "string" ? o.ghost : "");
3160
3161
		that.ghost.appendTo(that.helper);
3162
3163
	},
3164
3165
	resize: function(){
3166
		var that = $(this).data("ui-resizable");
3167
		if (that.ghost) {
3168
			that.ghost.css({ position: "relative", height: that.size.height, width: that.size.width });
3169
		}
3170
	},
3171
3172
	stop: function() {
3173
		var that = $(this).data("ui-resizable");
3174
		if (that.ghost && that.helper) {
3175
			that.helper.get(0).removeChild(that.ghost.get(0));
3176
		}
3177
	}
3178
3179
});
3180
3181
$.ui.plugin.add("resizable", "grid", {
3182
3183
	resize: function() {
3184
		var that = $(this).data("ui-resizable"),
3185
			o = that.options,
3186
			cs = that.size,
3187
			os = that.originalSize,
3188
			op = that.originalPosition,
3189
			a = that.axis,
3190
			grid = typeof o.grid === "number" ? [o.grid, o.grid] : o.grid,
3191
			gridX = (grid[0]||1),
3192
			gridY = (grid[1]||1),
3193
			ox = Math.round((cs.width - os.width) / gridX) * gridX,
3194
			oy = Math.round((cs.height - os.height) / gridY) * gridY,
3195
			newWidth = os.width + ox,
3196
			newHeight = os.height + oy,
3197
			isMaxWidth = o.maxWidth && (o.maxWidth < newWidth),
3198
			isMaxHeight = o.maxHeight && (o.maxHeight < newHeight),
3199
			isMinWidth = o.minWidth && (o.minWidth > newWidth),
3200
			isMinHeight = o.minHeight && (o.minHeight > newHeight);
3201
3202
		o.grid = grid;
3203
3204
		if (isMinWidth) {
3205
			newWidth = newWidth + gridX;
3206
		}
3207
		if (isMinHeight) {
3208
			newHeight = newHeight + gridY;
3209
		}
3210
		if (isMaxWidth) {
3211
			newWidth = newWidth - gridX;
3212
		}
3213
		if (isMaxHeight) {
3214
			newHeight = newHeight - gridY;
3215
		}
3216
3217
		if (/^(se|s|e)$/.test(a)) {
3218
			that.size.width = newWidth;
3219
			that.size.height = newHeight;
3220
		} else if (/^(ne)$/.test(a)) {
3221
			that.size.width = newWidth;
3222
			that.size.height = newHeight;
3223
			that.position.top = op.top - oy;
3224
		} else if (/^(sw)$/.test(a)) {
3225
			that.size.width = newWidth;
3226
			that.size.height = newHeight;
3227
			that.position.left = op.left - ox;
3228
		} else {
3229
			that.size.width = newWidth;
3230
			that.size.height = newHeight;
3231
			that.position.top = op.top - oy;
3232
			that.position.left = op.left - ox;
3233
		}
3234
	}
3235
3236
});
3237
3238
})(jQuery);
3239
3240
(function( $, undefined ) {
3241
3242
$.widget("ui.selectable", $.ui.mouse, {
3243
	version: "1.10.3",
3244
	options: {
3245
		appendTo: "body",
3246
		autoRefresh: true,
3247
		distance: 0,
3248
		filter: "*",
3249
		tolerance: "touch",
3250
3251
		// callbacks
3252
		selected: null,
3253
		selecting: null,
3254
		start: null,
3255
		stop: null,
3256
		unselected: null,
3257
		unselecting: null
3258
	},
3259
	_create: function() {
3260
		var selectees,
3261
			that = this;
3262
3263
		this.element.addClass("ui-selectable");
3264
3265
		this.dragged = false;
3266
3267
		// cache selectee children based on filter
3268
		this.refresh = function() {
3269
			selectees = $(that.options.filter, that.element[0]);
3270
			selectees.addClass("ui-selectee");
3271
			selectees.each(function() {
3272
				var $this = $(this),
3273
					pos = $this.offset();
3274
				$.data(this, "selectable-item", {
3275
					element: this,
3276
					$element: $this,
3277
					left: pos.left,
3278
					top: pos.top,
3279
					right: pos.left + $this.outerWidth(),
3280
					bottom: pos.top + $this.outerHeight(),
3281
					startselected: false,
3282
					selected: $this.hasClass("ui-selected"),
3283
					selecting: $this.hasClass("ui-selecting"),
3284
					unselecting: $this.hasClass("ui-unselecting")
3285
				});
3286
			});
3287
		};
3288
		this.refresh();
3289
3290
		this.selectees = selectees.addClass("ui-selectee");
3291
3292
		this._mouseInit();
3293
3294
		this.helper = $("<div class='ui-selectable-helper'></div>");
3295
	},
3296
3297
	_destroy: function() {
3298
		this.selectees
3299
			.removeClass("ui-selectee")
3300
			.removeData("selectable-item");
3301
		this.element
3302
			.removeClass("ui-selectable ui-selectable-disabled");
3303
		this._mouseDestroy();
3304
	},
3305
3306
	_mouseStart: function(event) {
3307
		var that = this,
3308
			options = this.options;
3309
3310
		this.opos = [event.pageX, event.pageY];
3311
3312
		if (this.options.disabled) {
3313
			return;
3314
		}
3315
3316
		this.selectees = $(options.filter, this.element[0]);
3317
3318
		this._trigger("start", event);
3319
3320
		$(options.appendTo).append(this.helper);
3321
		// position helper (lasso)
3322
		this.helper.css({
3323
			"left": event.pageX,
3324
			"top": event.pageY,
3325
			"width": 0,
3326
			"height": 0
3327
		});
3328
3329
		if (options.autoRefresh) {
3330
			this.refresh();
3331
		}
3332
3333
		this.selectees.filter(".ui-selected").each(function() {
3334
			var selectee = $.data(this, "selectable-item");
3335
			selectee.startselected = true;
3336
			if (!event.metaKey && !event.ctrlKey) {
3337
				selectee.$element.removeClass("ui-selected");
3338
				selectee.selected = false;
3339
				selectee.$element.addClass("ui-unselecting");
3340
				selectee.unselecting = true;
3341
				// selectable UNSELECTING callback
3342
				that._trigger("unselecting", event, {
3343
					unselecting: selectee.element
3344
				});
3345
			}
3346
		});
3347
3348
		$(event.target).parents().addBack().each(function() {
3349
			var doSelect,
3350
				selectee = $.data(this, "selectable-item");
3351
			if (selectee) {
3352
				doSelect = (!event.metaKey && !event.ctrlKey) || !selectee.$element.hasClass("ui-selected");
3353
				selectee.$element
3354
					.removeClass(doSelect ? "ui-unselecting" : "ui-selected")
3355
					.addClass(doSelect ? "ui-selecting" : "ui-unselecting");
3356
				selectee.unselecting = !doSelect;
3357
				selectee.selecting = doSelect;
3358
				selectee.selected = doSelect;
3359
				// selectable (UN)SELECTING callback
3360
				if (doSelect) {
3361
					that._trigger("selecting", event, {
3362
						selecting: selectee.element
3363
					});
3364
				} else {
3365
					that._trigger("unselecting", event, {
3366
						unselecting: selectee.element
3367
					});
3368
				}
3369
				return false;
3370
			}
3371
		});
3372
3373
	},
3374
3375
	_mouseDrag: function(event) {
3376
3377
		this.dragged = true;
3378
3379
		if (this.options.disabled) {
3380
			return;
3381
		}
3382
3383
		var tmp,
3384
			that = this,
3385
			options = this.options,
3386
			x1 = this.opos[0],
3387
			y1 = this.opos[1],
3388
			x2 = event.pageX,
3389
			y2 = event.pageY;
3390
3391
		if (x1 > x2) { tmp = x2; x2 = x1; x1 = tmp; }
3392
		if (y1 > y2) { tmp = y2; y2 = y1; y1 = tmp; }
3393
		this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1});
3394
3395
		this.selectees.each(function() {
3396
			var selectee = $.data(this, "selectable-item"),
3397
				hit = false;
3398
3399
			//prevent helper from being selected if appendTo: selectable
3400
			if (!selectee || selectee.element === that.element[0]) {
3401
				return;
3402
			}
3403
3404
			if (options.tolerance === "touch") {
3405
				hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
3406
			} else if (options.tolerance === "fit") {
3407
				hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
3408
			}
3409
3410
			if (hit) {
3411
				// SELECT
3412
				if (selectee.selected) {
3413
					selectee.$element.removeClass("ui-selected");
3414
					selectee.selected = false;
3415
				}
3416
				if (selectee.unselecting) {
3417
					selectee.$element.removeClass("ui-unselecting");
3418
					selectee.unselecting = false;
3419
				}
3420
				if (!selectee.selecting) {
3421
					selectee.$element.addClass("ui-selecting");
3422
					selectee.selecting = true;
3423
					// selectable SELECTING callback
3424
					that._trigger("selecting", event, {
3425
						selecting: selectee.element
3426
					});
3427
				}
3428
			} else {
3429
				// UNSELECT
3430
				if (selectee.selecting) {
3431
					if ((event.metaKey || event.ctrlKey) && selectee.startselected) {
3432
						selectee.$element.removeClass("ui-selecting");
3433
						selectee.selecting = false;
3434
						selectee.$element.addClass("ui-selected");
3435
						selectee.selected = true;
3436
					} else {
3437
						selectee.$element.removeClass("ui-selecting");
3438
						selectee.selecting = false;
3439
						if (selectee.startselected) {
3440
							selectee.$element.addClass("ui-unselecting");
3441
							selectee.unselecting = true;
3442
						}
3443
						// selectable UNSELECTING callback
3444
						that._trigger("unselecting", event, {
3445
							unselecting: selectee.element
3446
						});
3447
					}
3448
				}
3449
				if (selectee.selected) {
3450
					if (!event.metaKey && !event.ctrlKey && !selectee.startselected) {
3451
						selectee.$element.removeClass("ui-selected");
3452
						selectee.selected = false;
3453
3454
						selectee.$element.addClass("ui-unselecting");
3455
						selectee.unselecting = true;
3456
						// selectable UNSELECTING callback
3457
						that._trigger("unselecting", event, {
3458
							unselecting: selectee.element
3459
						});
3460
					}
3461
				}
3462
			}
3463
		});
3464
3465
		return false;
3466
	},
3467
3468
	_mouseStop: function(event) {
3469
		var that = this;
3470
3471
		this.dragged = false;
3472
3473
		$(".ui-unselecting", this.element[0]).each(function() {
3474
			var selectee = $.data(this, "selectable-item");
3475
			selectee.$element.removeClass("ui-unselecting");
3476
			selectee.unselecting = false;
3477
			selectee.startselected = false;
3478
			that._trigger("unselected", event, {
3479
				unselected: selectee.element
3480
			});
3481
		});
3482
		$(".ui-selecting", this.element[0]).each(function() {
3483
			var selectee = $.data(this, "selectable-item");
3484
			selectee.$element.removeClass("ui-selecting").addClass("ui-selected");
3485
			selectee.selecting = false;
3486
			selectee.selected = true;
3487
			selectee.startselected = true;
3488
			that._trigger("selected", event, {
3489
				selected: selectee.element
3490
			});
3491
		});
3492
		this._trigger("stop", event);
3493
3494
		this.helper.remove();
3495
3496
		return false;
3497
	}
3498
3499
});
3500
3501
})(jQuery);
3502
3503
(function( $, undefined ) {
3504
3505
/*jshint loopfunc: true */
3506
3507
function isOverAxis( x, reference, size ) {
3508
	return ( x > reference ) && ( x < ( reference + size ) );
3509
}
3510
3511
function isFloating(item) {
3512
	return (/left|right/).test(item.css("float")) || (/inline|table-cell/).test(item.css("display"));
3513
}
3514
3515
$.widget("ui.sortable", $.ui.mouse, {
3516
	version: "1.10.3",
3517
	widgetEventPrefix: "sort",
3518
	ready: false,
3519
	options: {
3520
		appendTo: "parent",
3521
		axis: false,
3522
		connectWith: false,
3523
		containment: false,
3524
		cursor: "auto",
3525
		cursorAt: false,
3526
		dropOnEmpty: true,
3527
		forcePlaceholderSize: false,
3528
		forceHelperSize: false,
3529
		grid: false,
3530
		handle: false,
3531
		helper: "original",
3532
		items: "> *",
3533
		opacity: false,
3534
		placeholder: false,
3535
		revert: false,
3536
		scroll: true,
3537
		scrollSensitivity: 20,
3538
		scrollSpeed: 20,
3539
		scope: "default",
3540
		tolerance: "intersect",
3541
		zIndex: 1000,
3542
3543
		// callbacks
3544
		activate: null,
3545
		beforeStop: null,
3546
		change: null,
3547
		deactivate: null,
3548
		out: null,
3549
		over: null,
3550
		receive: null,
3551
		remove: null,
3552
		sort: null,
3553
		start: null,
3554
		stop: null,
3555
		update: null
3556
	},
3557
	_create: function() {
3558
3559
		var o = this.options;
3560
		this.containerCache = {};
3561
		this.element.addClass("ui-sortable");
3562
3563
		//Get the items
3564
		this.refresh();
3565
3566
		//Let's determine if the items are being displayed horizontally
3567
		this.floating = this.items.length ? o.axis === "x" || isFloating(this.items[0].item) : false;
3568
3569
		//Let's determine the parent's offset
3570
		this.offset = this.element.offset();
3571
3572
		//Initialize mouse events for interaction
3573
		this._mouseInit();
3574
3575
		//We're ready to go
3576
		this.ready = true;
3577
3578
	},
3579
3580
	_destroy: function() {
3581
		this.element
3582
			.removeClass("ui-sortable ui-sortable-disabled");
3583
		this._mouseDestroy();
3584
3585
		for ( var i = this.items.length - 1; i >= 0; i-- ) {
3586
			this.items[i].item.removeData(this.widgetName + "-item");
3587
		}
3588
3589
		return this;
3590
	},
3591
3592
	_setOption: function(key, value){
3593
		if ( key === "disabled" ) {
3594
			this.options[ key ] = value;
3595
3596
			this.widget().toggleClass( "ui-sortable-disabled", !!value );
3597
		} else {
3598
			// Don't call widget base _setOption for disable as it adds ui-state-disabled class
3599
			$.Widget.prototype._setOption.apply(this, arguments);
3600
		}
3601
	},
3602
3603
	_mouseCapture: function(event, overrideHandle) {
3604
		var currentItem = null,
3605
			validHandle = false,
3606
			that = this;
3607
3608
		if (this.reverting) {
3609
			return false;
3610
		}
3611
3612
		if(this.options.disabled || this.options.type === "static") {
3613
			return false;
3614
		}
3615
3616
		//We have to refresh the items data once first
3617
		this._refreshItems(event);
3618
3619
		//Find out if the clicked node (or one of its parents) is a actual item in this.items
3620
		$(event.target).parents().each(function() {
3621
			if($.data(this, that.widgetName + "-item") === that) {
3622
				currentItem = $(this);
3623
				return false;
3624
			}
3625
		});
3626
		if($.data(event.target, that.widgetName + "-item") === that) {
3627
			currentItem = $(event.target);
3628
		}
3629
3630
		if(!currentItem) {
3631
			return false;
3632
		}
3633
		if(this.options.handle && !overrideHandle) {
3634
			$(this.options.handle, currentItem).find("*").addBack().each(function() {
3635
				if(this === event.target) {
3636
					validHandle = true;
3637
				}
3638
			});
3639
			if(!validHandle) {
3640
				return false;
3641
			}
3642
		}
3643
3644
		this.currentItem = currentItem;
3645
		this._removeCurrentsFromItems();
3646
		return true;
3647
3648
	},
3649
3650
	_mouseStart: function(event, overrideHandle, noActivation) {
3651
3652
		var i, body,
3653
			o = this.options;
3654
3655
		this.currentContainer = this;
3656
3657
		//We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
3658
		this.refreshPositions();
3659
3660
		//Create and append the visible helper
3661
		this.helper = this._createHelper(event);
3662
3663
		//Cache the helper size
3664
		this._cacheHelperProportions();
3665
3666
		/*
3667
		 * - Position generation -
3668
		 * This block generates everything position related - it's the core of draggables.
3669
		 */
3670
3671
		//Cache the margins of the original element
3672
		this._cacheMargins();
3673
3674
		//Get the next scrolling parent
3675
		this.scrollParent = this.helper.scrollParent();
3676
3677
		//The element's absolute position on the page minus margins
3678
		this.offset = this.currentItem.offset();
3679
		this.offset = {
3680
			top: this.offset.top - this.margins.top,
3681
			left: this.offset.left - this.margins.left
3682
		};
3683
3684
		$.extend(this.offset, {
3685
			click: { //Where the click happened, relative to the element
3686
				left: event.pageX - this.offset.left,
3687
				top: event.pageY - this.offset.top
3688
			},
3689
			parent: this._getParentOffset(),
3690
			relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
3691
		});
3692
3693
		// Only after we got the offset, we can change the helper's position to absolute
3694
		// TODO: Still need to figure out a way to make relative sorting possible
3695
		this.helper.css("position", "absolute");
3696
		this.cssPosition = this.helper.css("position");
3697
3698
		//Generate the original position
3699
		this.originalPosition = this._generatePosition(event);
3700
		this.originalPageX = event.pageX;
3701
		this.originalPageY = event.pageY;
3702
3703
		//Adjust the mouse offset relative to the helper if "cursorAt" is supplied
3704
		(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
3705
3706
		//Cache the former DOM position
3707
		this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };
3708
3709
		//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
3710
		if(this.helper[0] !== this.currentItem[0]) {
3711
			this.currentItem.hide();
3712
		}
3713
3714
		//Create the placeholder
3715
		this._createPlaceholder();
3716
3717
		//Set a containment if given in the options
3718
		if(o.containment) {
3719
			this._setContainment();
3720
		}
3721
3722
		if( o.cursor && o.cursor !== "auto" ) { // cursor option
3723
			body = this.document.find( "body" );
3724
3725
			// support: IE
3726
			this.storedCursor = body.css( "cursor" );
3727
			body.css( "cursor", o.cursor );
3728
3729
			this.storedStylesheet = $( "<style>*{ cursor: "+o.cursor+" !important; }</style>" ).appendTo( body );
3730
		}
3731
3732
		if(o.opacity) { // opacity option
3733
			if (this.helper.css("opacity")) {
3734
				this._storedOpacity = this.helper.css("opacity");
3735
			}
3736
			this.helper.css("opacity", o.opacity);
3737
		}
3738
3739
		if(o.zIndex) { // zIndex option
3740
			if (this.helper.css("zIndex")) {
3741
				this._storedZIndex = this.helper.css("zIndex");
3742
			}
3743
			this.helper.css("zIndex", o.zIndex);
3744
		}
3745
3746
		//Prepare scrolling
3747
		if(this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") {
3748
			this.overflowOffset = this.scrollParent.offset();
3749
		}
3750
3751
		//Call callbacks
3752
		this._trigger("start", event, this._uiHash());
3753
3754
		//Recache the helper size
3755
		if(!this._preserveHelperProportions) {
3756
			this._cacheHelperProportions();
3757
		}
3758
3759
3760
		//Post "activate" events to possible containers
3761
		if( !noActivation ) {
3762
			for ( i = this.containers.length - 1; i >= 0; i-- ) {
3763
				this.containers[ i ]._trigger( "activate", event, this._uiHash( this ) );
3764
			}
3765
		}
3766
3767
		//Prepare possible droppables
3768
		if($.ui.ddmanager) {
3769
			$.ui.ddmanager.current = this;
3770
		}
3771
3772
		if ($.ui.ddmanager && !o.dropBehaviour) {
3773
			$.ui.ddmanager.prepareOffsets(this, event);
3774
		}
3775
3776
		this.dragging = true;
3777
3778
		this.helper.addClass("ui-sortable-helper");
3779
		this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
3780
		return true;
3781
3782
	},
3783
3784
	_mouseDrag: function(event) {
3785
		var i, item, itemElement, intersection,
3786
			o = this.options,
3787
			scrolled = false;
3788
3789
		//Compute the helpers position
3790
		this.position = this._generatePosition(event);
3791
		this.positionAbs = this._convertPositionTo("absolute");
3792
3793
		if (!this.lastPositionAbs) {
3794
			this.lastPositionAbs = this.positionAbs;
3795
		}
3796
3797
		//Do scrolling
3798
		if(this.options.scroll) {
3799
			if(this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") {
3800
3801
				if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) {
3802
					this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
3803
				} else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity) {
3804
					this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
3805
				}
3806
3807
				if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) {
3808
					this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
3809
				} else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity) {
3810
					this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
3811
				}
3812
3813
			} else {
3814
3815
				if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) {
3816
					scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
3817
				} else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) {
3818
					scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
3819
				}
3820
3821
				if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) {
3822
					scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
3823
				} else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) {
3824
					scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
3825
				}
3826
3827
			}
3828
3829
			if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) {
3830
				$.ui.ddmanager.prepareOffsets(this, event);
3831
			}
3832
		}
3833
3834
		//Regenerate the absolute position used for position checks
3835
		this.positionAbs = this._convertPositionTo("absolute");
3836
3837
		//Set the helper position
3838
		if(!this.options.axis || this.options.axis !== "y") {
3839
			this.helper[0].style.left = this.position.left+"px";
3840
		}
3841
		if(!this.options.axis || this.options.axis !== "x") {
3842
			this.helper[0].style.top = this.position.top+"px";
3843
		}
3844
3845
		//Rearrange
3846
		for (i = this.items.length - 1; i >= 0; i--) {
3847
3848
			//Cache variables and intersection, continue if no intersection
3849
			item = this.items[i];
3850
			itemElement = item.item[0];
3851
			intersection = this._intersectsWithPointer(item);
3852
			if (!intersection) {
3853
				continue;
3854
			}
3855
3856
			// Only put the placeholder inside the current Container, skip all
3857
			// items form other containers. This works because when moving
3858
			// an item from one container to another the
3859
			// currentContainer is switched before the placeholder is moved.
3860
			//
3861
			// Without this moving items in "sub-sortables" can cause the placeholder to jitter
3862
			// beetween the outer and inner container.
3863
			if (item.instance !== this.currentContainer) {
3864
				continue;
3865
			}
3866
3867
			// cannot intersect with itself
3868
			// no useless actions that have been done before
3869
			// no action if the item moved is the parent of the item checked
3870
			if (itemElement !== this.currentItem[0] &&
3871
				this.placeholder[intersection === 1 ? "next" : "prev"]()[0] !== itemElement &&
3872
				!$.contains(this.placeholder[0], itemElement) &&
3873
				(this.options.type === "semi-dynamic" ? !$.contains(this.element[0], itemElement) : true)
3874
			) {
3875
3876
				this.direction = intersection === 1 ? "down" : "up";
3877
3878
				if (this.options.tolerance === "pointer" || this._intersectsWithSides(item)) {
3879
					this._rearrange(event, item);
3880
				} else {
3881
					break;
3882
				}
3883
3884
				this._trigger("change", event, this._uiHash());
3885
				break;
3886
			}
3887
		}
3888
3889
		//Post events to containers
3890
		this._contactContainers(event);
3891
3892
		//Interconnect with droppables
3893
		if($.ui.ddmanager) {
3894
			$.ui.ddmanager.drag(this, event);
3895
		}
3896
3897
		//Call callbacks
3898
		this._trigger("sort", event, this._uiHash());
3899
3900
		this.lastPositionAbs = this.positionAbs;
3901
		return false;
3902
3903
	},
3904
3905
	_mouseStop: function(event, noPropagation) {
3906
3907
		if(!event) {
3908
			return;
3909
		}
3910
3911
		//If we are using droppables, inform the manager about the drop
3912
		if ($.ui.ddmanager && !this.options.dropBehaviour) {
3913
			$.ui.ddmanager.drop(this, event);
3914
		}
3915
3916
		if(this.options.revert) {
3917
			var that = this,
3918
				cur = this.placeholder.offset(),
3919
				axis = this.options.axis,
3920
				animation = {};
3921
3922
			if ( !axis || axis === "x" ) {
3923
				animation.left = cur.left - this.offset.parent.left - this.margins.left + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollLeft);
3924
			}
3925
			if ( !axis || axis === "y" ) {
3926
				animation.top = cur.top - this.offset.parent.top - this.margins.top + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollTop);
3927
			}
3928
			this.reverting = true;
3929
			$(this.helper).animate( animation, parseInt(this.options.revert, 10) || 500, function() {
3930
				that._clear(event);
3931
			});
3932
		} else {
3933
			this._clear(event, noPropagation);
3934
		}
3935
3936
		return false;
3937
3938
	},
3939
3940
	cancel: function() {
3941
3942
		if(this.dragging) {
3943
3944
			this._mouseUp({ target: null });
3945
3946
			if(this.options.helper === "original") {
3947
				this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
3948
			} else {
3949
				this.currentItem.show();
3950
			}
3951
3952
			//Post deactivating events to containers
3953
			for (var i = this.containers.length - 1; i >= 0; i--){
3954
				this.containers[i]._trigger("deactivate", null, this._uiHash(this));
3955
				if(this.containers[i].containerCache.over) {
3956
					this.containers[i]._trigger("out", null, this._uiHash(this));
3957
					this.containers[i].containerCache.over = 0;
3958
				}
3959
			}
3960
3961
		}
3962
3963
		if (this.placeholder) {
3964
			//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
3965
			if(this.placeholder[0].parentNode) {
3966
				this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
3967
			}
3968
			if(this.options.helper !== "original" && this.helper && this.helper[0].parentNode) {
3969
				this.helper.remove();
3970
			}
3971
3972
			$.extend(this, {
3973
				helper: null,
3974
				dragging: false,
3975
				reverting: false,
3976
				_noFinalSort: null
3977
			});
3978
3979
			if(this.domPosition.prev) {
3980
				$(this.domPosition.prev).after(this.currentItem);
3981
			} else {
3982
				$(this.domPosition.parent).prepend(this.currentItem);
3983
			}
3984
		}
3985
3986
		return this;
3987
3988
	},
3989
3990
	serialize: function(o) {
3991
3992
		var items = this._getItemsAsjQuery(o && o.connected),
3993
			str = [];
3994
		o = o || {};
3995
3996
		$(items).each(function() {
3997
			var res = ($(o.item || this).attr(o.attribute || "id") || "").match(o.expression || (/(.+)[\-=_](.+)/));
3998
			if (res) {
3999
				str.push((o.key || res[1]+"[]")+"="+(o.key && o.expression ? res[1] : res[2]));
4000
			}
4001
		});
4002
4003
		if(!str.length && o.key) {
4004
			str.push(o.key + "=");
4005
		}
4006
4007
		return str.join("&");
4008
4009
	},
4010
4011
	toArray: function(o) {
4012
4013
		var items = this._getItemsAsjQuery(o && o.connected),
4014
			ret = [];
4015
4016
		o = o || {};
4017
4018
		items.each(function() { ret.push($(o.item || this).attr(o.attribute || "id") || ""); });
4019
		return ret;
4020
4021
	},
4022
4023
	/* Be careful with the following core functions */
4024
	_intersectsWith: function(item) {
4025
4026
		var x1 = this.positionAbs.left,
4027
			x2 = x1 + this.helperProportions.width,
4028
			y1 = this.positionAbs.top,
4029
			y2 = y1 + this.helperProportions.height,
4030
			l = item.left,
4031
			r = l + item.width,
4032
			t = item.top,
4033
			b = t + item.height,
4034
			dyClick = this.offset.click.top,
4035
			dxClick = this.offset.click.left,
4036
			isOverElementHeight = ( this.options.axis === "x" ) || ( ( y1 + dyClick ) > t && ( y1 + dyClick ) < b ),
4037
			isOverElementWidth = ( this.options.axis === "y" ) || ( ( x1 + dxClick ) > l && ( x1 + dxClick ) < r ),
4038
			isOverElement = isOverElementHeight && isOverElementWidth;
4039
4040
		if ( this.options.tolerance === "pointer" ||
4041
			this.options.forcePointerForContainers ||
4042
			(this.options.tolerance !== "pointer" && this.helperProportions[this.floating ? "width" : "height"] > item[this.floating ? "width" : "height"])
4043
		) {
4044
			return isOverElement;
4045
		} else {
4046
4047
			return (l < x1 + (this.helperProportions.width / 2) && // Right Half
4048
				x2 - (this.helperProportions.width / 2) < r && // Left Half
4049
				t < y1 + (this.helperProportions.height / 2) && // Bottom Half
4050
				y2 - (this.helperProportions.height / 2) < b ); // Top Half
4051
4052
		}
4053
	},
4054
4055
	_intersectsWithPointer: function(item) {
4056
4057
		var isOverElementHeight = (this.options.axis === "x") || isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
4058
			isOverElementWidth = (this.options.axis === "y") || isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
4059
			isOverElement = isOverElementHeight && isOverElementWidth,
4060
			verticalDirection = this._getDragVerticalDirection(),
4061
			horizontalDirection = this._getDragHorizontalDirection();
4062
4063
		if (!isOverElement) {
4064
			return false;
4065
		}
4066
4067
		return this.floating ?
4068
			( ((horizontalDirection && horizontalDirection === "right") || verticalDirection === "down") ? 2 : 1 )
4069
			: ( verticalDirection && (verticalDirection === "down" ? 2 : 1) );
4070
4071
	},
4072
4073
	_intersectsWithSides: function(item) {
4074
4075
		var isOverBottomHalf = isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),
4076
			isOverRightHalf = isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
4077
			verticalDirection = this._getDragVerticalDirection(),
4078
			horizontalDirection = this._getDragHorizontalDirection();
4079
4080
		if (this.floating && horizontalDirection) {
4081
			return ((horizontalDirection === "right" && isOverRightHalf) || (horizontalDirection === "left" && !isOverRightHalf));
4082
		} else {
4083
			return verticalDirection && ((verticalDirection === "down" && isOverBottomHalf) || (verticalDirection === "up" && !isOverBottomHalf));
4084
		}
4085
4086
	},
4087
4088
	_getDragVerticalDirection: function() {
4089
		var delta = this.positionAbs.top - this.lastPositionAbs.top;
4090
		return delta !== 0 && (delta > 0 ? "down" : "up");
4091
	},
4092
4093
	_getDragHorizontalDirection: function() {
4094
		var delta = this.positionAbs.left - this.lastPositionAbs.left;
4095
		return delta !== 0 && (delta > 0 ? "right" : "left");
4096
	},
4097
4098
	refresh: function(event) {
4099
		this._refreshItems(event);
4100
		this.refreshPositions();
4101
		return this;
4102
	},
4103
4104
	_connectWith: function() {
4105
		var options = this.options;
4106
		return options.connectWith.constructor === String ? [options.connectWith] : options.connectWith;
4107
	},
4108
4109
	_getItemsAsjQuery: function(connected) {
4110
4111
		var i, j, cur, inst,
4112
			items = [],
4113
			queries = [],
4114
			connectWith = this._connectWith();
4115
4116
		if(connectWith && connected) {
4117
			for (i = connectWith.length - 1; i >= 0; i--){
4118
				cur = $(connectWith[i]);
4119
				for ( j = cur.length - 1; j >= 0; j--){
4120
					inst = $.data(cur[j], this.widgetFullName);
4121
					if(inst && inst !== this && !inst.options.disabled) {
4122
						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]);
4123
					}
4124
				}
4125
			}
4126
		}
4127
4128
		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]);
4129
4130
		for (i = queries.length - 1; i >= 0; i--){
4131
			queries[i][0].each(function() {
4132
				items.push(this);
4133
			});
4134
		}
4135
4136
		return $(items);
4137
4138
	},
4139
4140
	_removeCurrentsFromItems: function() {
4141
4142
		var list = this.currentItem.find(":data(" + this.widgetName + "-item)");
4143
4144
		this.items = $.grep(this.items, function (item) {
4145
			for (var j=0; j < list.length; j++) {
4146
				if(list[j] === item.item[0]) {
4147
					return false;
4148
				}
4149
			}
4150
			return true;
4151
		});
4152
4153
	},
4154
4155
	_refreshItems: function(event) {
4156
4157
		this.items = [];
4158
		this.containers = [this];
4159
4160
		var i, j, cur, inst, targetData, _queries, item, queriesLength,
4161
			items = this.items,
4162
			queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]],
4163
			connectWith = this._connectWith();
4164
4165
		if(connectWith && this.ready) { //Shouldn't be run the first time through due to massive slow-down
4166
			for (i = connectWith.length - 1; i >= 0; i--){
4167
				cur = $(connectWith[i]);
4168
				for (j = cur.length - 1; j >= 0; j--){
4169
					inst = $.data(cur[j], this.widgetFullName);
4170
					if(inst && inst !== this && !inst.options.disabled) {
4171
						queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
4172
						this.containers.push(inst);
4173
					}
4174
				}
4175
			}
4176
		}
4177
4178
		for (i = queries.length - 1; i >= 0; i--) {
4179
			targetData = queries[i][1];
4180
			_queries = queries[i][0];
4181
4182
			for (j=0, queriesLength = _queries.length; j < queriesLength; j++) {
4183
				item = $(_queries[j]);
4184
4185
				item.data(this.widgetName + "-item", targetData); // Data for target checking (mouse manager)
4186
4187
				items.push({
4188
					item: item,
4189
					instance: targetData,
4190
					width: 0, height: 0,
4191
					left: 0, top: 0
4192
				});
4193
			}
4194
		}
4195
4196
	},
4197
4198
	refreshPositions: function(fast) {
4199
4200
		//This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
4201
		if(this.offsetParent && this.helper) {
4202
			this.offset.parent = this._getParentOffset();
4203
		}
4204
4205
		var i, item, t, p;
4206
4207
		for (i = this.items.length - 1; i >= 0; i--){
4208
			item = this.items[i];
4209
4210
			//We ignore calculating positions of all connected containers when we're not over them
4211
			if(item.instance !== this.currentContainer && this.currentContainer && item.item[0] !== this.currentItem[0]) {
4212
				continue;
4213
			}
4214
4215
			t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
4216
4217
			if (!fast) {
4218
				item.width = t.outerWidth();
4219
				item.height = t.outerHeight();
4220
			}
4221
4222
			p = t.offset();
4223
			item.left = p.left;
4224
			item.top = p.top;
4225
		}
4226
4227
		if(this.options.custom && this.options.custom.refreshContainers) {
4228
			this.options.custom.refreshContainers.call(this);
4229
		} else {
4230
			for (i = this.containers.length - 1; i >= 0; i--){
4231
				p = this.containers[i].element.offset();
4232
				this.containers[i].containerCache.left = p.left;
4233
				this.containers[i].containerCache.top = p.top;
4234
				this.containers[i].containerCache.width	= this.containers[i].element.outerWidth();
4235
				this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
4236
			}
4237
		}
4238
4239
		return this;
4240
	},
4241
4242
	_createPlaceholder: function(that) {
4243
		that = that || this;
4244
		var className,
4245
			o = that.options;
4246
4247
		if(!o.placeholder || o.placeholder.constructor === String) {
4248
			className = o.placeholder;
4249
			o.placeholder = {
4250
				element: function() {
4251
4252
					var nodeName = that.currentItem[0].nodeName.toLowerCase(),
4253
						element = $( "<" + nodeName + ">", that.document[0] )
4254
							.addClass(className || that.currentItem[0].className+" ui-sortable-placeholder")
4255
							.removeClass("ui-sortable-helper");
4256
4257
					if ( nodeName === "tr" ) {
4258
						that.currentItem.children().each(function() {
4259
							$( "<td>&#160;</td>", that.document[0] )
4260
								.attr( "colspan", $( this ).attr( "colspan" ) || 1 )
4261
								.appendTo( element );
4262
						});
4263
					} else if ( nodeName === "img" ) {
4264
						element.attr( "src", that.currentItem.attr( "src" ) );
4265
					}
4266
4267
					if ( !className ) {
4268
						element.css( "visibility", "hidden" );
4269
					}
4270
4271
					return element;
4272
				},
4273
				update: function(container, p) {
4274
4275
					// 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
4276
					// 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
4277
					if(className && !o.forcePlaceholderSize) {
4278
						return;
4279
					}
4280
4281
					//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
4282
					if(!p.height()) { p.height(that.currentItem.innerHeight() - parseInt(that.currentItem.css("paddingTop")||0, 10) - parseInt(that.currentItem.css("paddingBottom")||0, 10)); }
4283
					if(!p.width()) { p.width(that.currentItem.innerWidth() - parseInt(that.currentItem.css("paddingLeft")||0, 10) - parseInt(that.currentItem.css("paddingRight")||0, 10)); }
4284
				}
4285
			};
4286
		}
4287
4288
		//Create the placeholder
4289
		that.placeholder = $(o.placeholder.element.call(that.element, that.currentItem));
4290
4291
		//Append it after the actual current item
4292
		that.currentItem.after(that.placeholder);
4293
4294
		//Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
4295
		o.placeholder.update(that, that.placeholder);
4296
4297
	},
4298
4299
	_contactContainers: function(event) {
4300
		var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, base, cur, nearBottom, floating,
4301
			innermostContainer = null,
4302
			innermostIndex = null;
4303
4304
		// get innermost container that intersects with item
4305
		for (i = this.containers.length - 1; i >= 0; i--) {
4306
4307
			// never consider a container that's located within the item itself
4308
			if($.contains(this.currentItem[0], this.containers[i].element[0])) {
4309
				continue;
4310
			}
4311
4312
			if(this._intersectsWith(this.containers[i].containerCache)) {
4313
4314
				// if we've already found a container and it's more "inner" than this, then continue
4315
				if(innermostContainer && $.contains(this.containers[i].element[0], innermostContainer.element[0])) {
4316
					continue;
4317
				}
4318
4319
				innermostContainer = this.containers[i];
4320
				innermostIndex = i;
4321
4322
			} else {
4323
				// container doesn't intersect. trigger "out" event if necessary
4324
				if(this.containers[i].containerCache.over) {
4325
					this.containers[i]._trigger("out", event, this._uiHash(this));
4326
					this.containers[i].containerCache.over = 0;
4327
				}
4328
			}
4329
4330
		}
4331
4332
		// if no intersecting containers found, return
4333
		if(!innermostContainer) {
4334
			return;
4335
		}
4336
4337
		// move the item into the container if it's not there already
4338
		if(this.containers.length === 1) {
4339
			if (!this.containers[innermostIndex].containerCache.over) {
4340
				this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
4341
				this.containers[innermostIndex].containerCache.over = 1;
4342
			}
4343
		} else {
4344
4345
			//When entering a new container, we will find the item with the least distance and append our item near it
4346
			dist = 10000;
4347
			itemWithLeastDistance = null;
4348
			floating = innermostContainer.floating || isFloating(this.currentItem);
4349
			posProperty = floating ? "left" : "top";
4350
			sizeProperty = floating ? "width" : "height";
4351
			base = this.positionAbs[posProperty] + this.offset.click[posProperty];
4352
			for (j = this.items.length - 1; j >= 0; j--) {
4353
				if(!$.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) {
4354
					continue;
4355
				}
4356
				if(this.items[j].item[0] === this.currentItem[0]) {
4357
					continue;
4358
				}
4359
				if (floating && !isOverAxis(this.positionAbs.top + this.offset.click.top, this.items[j].top, this.items[j].height)) {
4360
					continue;
4361
				}
4362
				cur = this.items[j].item.offset()[posProperty];
4363
				nearBottom = false;
4364
				if(Math.abs(cur - base) > Math.abs(cur + this.items[j][sizeProperty] - base)){
4365
					nearBottom = true;
4366
					cur += this.items[j][sizeProperty];
4367
				}
4368
4369
				if(Math.abs(cur - base) < dist) {
4370
					dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j];
4371
					this.direction = nearBottom ? "up": "down";
4372
				}
4373
			}
4374
4375
			//Check if dropOnEmpty is enabled
4376
			if(!itemWithLeastDistance && !this.options.dropOnEmpty) {
4377
				return;
4378
			}
4379
4380
			if(this.currentContainer === this.containers[innermostIndex]) {
4381
				return;
4382
			}
4383
4384
			itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true);
4385
			this._trigger("change", event, this._uiHash());
4386
			this.containers[innermostIndex]._trigger("change", event, this._uiHash(this));
4387
			this.currentContainer = this.containers[innermostIndex];
4388
4389
			//Update the placeholder
4390
			this.options.placeholder.update(this.currentContainer, this.placeholder);
4391
4392
			this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
4393
			this.containers[innermostIndex].containerCache.over = 1;
4394
		}
4395
4396
4397
	},
4398
4399
	_createHelper: function(event) {
4400
4401
		var o = this.options,
4402
			helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper === "clone" ? this.currentItem.clone() : this.currentItem);
4403
4404
		//Add the helper to the DOM if that didn't happen already
4405
		if(!helper.parents("body").length) {
4406
			$(o.appendTo !== "parent" ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);
4407
		}
4408
4409
		if(helper[0] === this.currentItem[0]) {
4410
			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") };
4411
		}
4412
4413
		if(!helper[0].style.width || o.forceHelperSize) {
4414
			helper.width(this.currentItem.width());
4415
		}
4416
		if(!helper[0].style.height || o.forceHelperSize) {
4417
			helper.height(this.currentItem.height());
4418
		}
4419
4420
		return helper;
4421
4422
	},
4423
4424 View Code Duplication
	_adjustOffsetFromHelper: function(obj) {
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
4425
		if (typeof obj === "string") {
4426
			obj = obj.split(" ");
4427
		}
4428
		if ($.isArray(obj)) {
4429
			obj = {left: +obj[0], top: +obj[1] || 0};
4430
		}
4431
		if ("left" in obj) {
4432
			this.offset.click.left = obj.left + this.margins.left;
4433
		}
4434
		if ("right" in obj) {
4435
			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
4436
		}
4437
		if ("top" in obj) {
4438
			this.offset.click.top = obj.top + this.margins.top;
4439
		}
4440
		if ("bottom" in obj) {
4441
			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
4442
		}
4443
	},
4444
4445 View Code Duplication
	_getParentOffset: function() {
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
4446
4447
4448
		//Get the offsetParent and cache its position
4449
		this.offsetParent = this.helper.offsetParent();
4450
		var po = this.offsetParent.offset();
4451
4452
		// This is a special case where we need to modify a offset calculated on start, since the following happened:
4453
		// 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
4454
		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
4455
		//    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
4456
		if(this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) {
4457
			po.left += this.scrollParent.scrollLeft();
4458
			po.top += this.scrollParent.scrollTop();
4459
		}
4460
4461
		// This needs to be actually done for all browsers, since pageX/pageY includes this information
4462
		// with an ugly IE fix
4463
		if( this.offsetParent[0] === document.body || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie)) {
4464
			po = { top: 0, left: 0 };
4465
		}
4466
4467
		return {
4468
			top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
4469
			left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
4470
		};
4471
4472
	},
4473
4474
	_getRelativeOffset: function() {
4475
4476
		if(this.cssPosition === "relative") {
4477
			var p = this.currentItem.position();
4478
			return {
4479
				top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
4480
				left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
4481
			};
4482
		} else {
4483
			return { top: 0, left: 0 };
4484
		}
4485
4486
	},
4487
4488
	_cacheMargins: function() {
4489
		this.margins = {
4490
			left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),
4491
			top: (parseInt(this.currentItem.css("marginTop"),10) || 0)
4492
		};
4493
	},
4494
4495
	_cacheHelperProportions: function() {
4496
		this.helperProportions = {
4497
			width: this.helper.outerWidth(),
4498
			height: this.helper.outerHeight()
4499
		};
4500
	},
4501
4502
	_setContainment: function() {
4503
4504
		var ce, co, over,
4505
			o = this.options;
4506
		if(o.containment === "parent") {
4507
			o.containment = this.helper[0].parentNode;
4508
		}
4509
		if(o.containment === "document" || o.containment === "window") {
4510
			this.containment = [
4511
				0 - this.offset.relative.left - this.offset.parent.left,
4512
				0 - this.offset.relative.top - this.offset.parent.top,
4513
				$(o.containment === "document" ? document : window).width() - this.helperProportions.width - this.margins.left,
4514
				($(o.containment === "document" ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
4515
			];
4516
		}
4517
4518
		if(!(/^(document|window|parent)$/).test(o.containment)) {
4519
			ce = $(o.containment)[0];
4520
			co = $(o.containment).offset();
4521
			over = ($(ce).css("overflow") !== "hidden");
4522
4523
			this.containment = [
4524
				co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
4525
				co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
4526
				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,
4527
				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
4528
			];
4529
		}
4530
4531
	},
4532
4533
	_convertPositionTo: function(d, pos) {
4534
4535
		if(!pos) {
4536
			pos = this.position;
4537
		}
4538
		var mod = d === "absolute" ? 1 : -1,
4539
			scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent,
4540
			scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
4541
4542
		return {
4543
			top: (
4544
				pos.top	+																// The absolute mouse position
4545
				this.offset.relative.top * mod +										// Only for relative positioned nodes: Relative offset from element to offset parent
4546
				this.offset.parent.top * mod -											// The offsetParent's offset without borders (offset + border)
4547
				( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
4548
			),
4549
			left: (
4550
				pos.left +																// The absolute mouse position
4551
				this.offset.relative.left * mod +										// Only for relative positioned nodes: Relative offset from element to offset parent
4552
				this.offset.parent.left * mod	-										// The offsetParent's offset without borders (offset + border)
4553
				( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
4554
			)
4555
		};
4556
4557
	},
4558
4559 View Code Duplication
	_generatePosition: function(event) {
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
4560
4561
		var top, left,
4562
			o = this.options,
4563
			pageX = event.pageX,
4564
			pageY = event.pageY,
4565
			scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
4566
4567
		// This is another very weird special case that only happens for relative elements:
4568
		// 1. If the css position is relative
4569
		// 2. and the scroll parent is the document or similar to the offset parent
4570
		// we have to refresh the relative offset during the scroll so there are no jumps
4571
		if(this.cssPosition === "relative" && !(this.scrollParent[0] !== document && this.scrollParent[0] !== this.offsetParent[0])) {
4572
			this.offset.relative = this._getRelativeOffset();
4573
		}
4574
4575
		/*
4576
		 * - Position constraining -
4577
		 * Constrain the position to a mix of grid, containment.
4578
		 */
4579
4580
		if(this.originalPosition) { //If we are not dragging yet, we won't check for options
4581
4582
			if(this.containment) {
4583
				if(event.pageX - this.offset.click.left < this.containment[0]) {
4584
					pageX = this.containment[0] + this.offset.click.left;
4585
				}
4586
				if(event.pageY - this.offset.click.top < this.containment[1]) {
4587
					pageY = this.containment[1] + this.offset.click.top;
4588
				}
4589
				if(event.pageX - this.offset.click.left > this.containment[2]) {
4590
					pageX = this.containment[2] + this.offset.click.left;
4591
				}
4592
				if(event.pageY - this.offset.click.top > this.containment[3]) {
4593
					pageY = this.containment[3] + this.offset.click.top;
4594
				}
4595
			}
4596
4597
			if(o.grid) {
4598
				top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
4599
				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;
4600
4601
				left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
4602
				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;
4603
			}
4604
4605
		}
4606
4607
		return {
4608
			top: (
4609
				pageY -																// The absolute mouse position
4610
				this.offset.click.top -													// Click offset (relative to the element)
4611
				this.offset.relative.top	-											// Only for relative positioned nodes: Relative offset from element to offset parent
4612
				this.offset.parent.top +												// The offsetParent's offset without borders (offset + border)
4613
				( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
4614
			),
4615
			left: (
4616
				pageX -																// The absolute mouse position
4617
				this.offset.click.left -												// Click offset (relative to the element)
4618
				this.offset.relative.left	-											// Only for relative positioned nodes: Relative offset from element to offset parent
4619
				this.offset.parent.left +												// The offsetParent's offset without borders (offset + border)
4620
				( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
4621
			)
4622
		};
4623
4624
	},
4625
4626
	_rearrange: function(event, i, a, hardRefresh) {
4627
4628
		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));
4629
4630
		//Various things done here to improve the performance:
4631
		// 1. we create a setTimeout, that calls refreshPositions
4632
		// 2. on the instance, we have a counter variable, that get's higher after every append
4633
		// 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
4634
		// 4. this lets only the last addition to the timeout stack through
4635
		this.counter = this.counter ? ++this.counter : 1;
4636
		var counter = this.counter;
4637
4638
		this._delay(function() {
4639
			if(counter === this.counter) {
4640
				this.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
4641
			}
4642
		});
4643
4644
	},
4645
4646
	_clear: function(event, noPropagation) {
4647
4648
		this.reverting = false;
4649
		// We delay all events that have to be triggered to after the point where the placeholder has been removed and
4650
		// everything else normalized again
4651
		var i,
4652
			delayedTriggers = [];
4653
4654
		// We first have to update the dom position of the actual currentItem
4655
		// Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
4656
		if(!this._noFinalSort && this.currentItem.parent().length) {
4657
			this.placeholder.before(this.currentItem);
4658
		}
4659
		this._noFinalSort = null;
4660
4661
		if(this.helper[0] === this.currentItem[0]) {
4662
			for(i in this._storedCSS) {
4663
				if(this._storedCSS[i] === "auto" || this._storedCSS[i] === "static") {
4664
					this._storedCSS[i] = "";
4665
				}
4666
			}
4667
			this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
4668
		} else {
4669
			this.currentItem.show();
4670
		}
4671
4672
		if(this.fromOutside && !noPropagation) {
4673
			delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });
4674
		}
4675
		if((this.fromOutside || this.domPosition.prev !== this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent !== this.currentItem.parent()[0]) && !noPropagation) {
4676
			delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed
4677
		}
4678
4679
		// Check if the items Container has Changed and trigger appropriate
4680
		// events.
4681
		if (this !== this.currentContainer) {
4682
			if(!noPropagation) {
4683
				delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
4684
				delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); };  }).call(this, this.currentContainer));
4685
				delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this));  }; }).call(this, this.currentContainer));
4686
			}
4687
		}
4688
4689
4690
		//Post events to containers
4691
		for (i = this.containers.length - 1; i >= 0; i--){
4692
			if(!noPropagation) {
4693
				delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
4694
			}
4695
			if(this.containers[i].containerCache.over) {
4696
				delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
4697
				this.containers[i].containerCache.over = 0;
4698
			}
4699
		}
4700
4701
		//Do what was originally in plugins
4702
		if ( this.storedCursor ) {
4703
			this.document.find( "body" ).css( "cursor", this.storedCursor );
4704
			this.storedStylesheet.remove();
4705
		}
4706
		if(this._storedOpacity) {
4707
			this.helper.css("opacity", this._storedOpacity);
4708
		}
4709
		if(this._storedZIndex) {
4710
			this.helper.css("zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex);
4711
		}
4712
4713
		this.dragging = false;
4714
		if(this.cancelHelperRemoval) {
4715
			if(!noPropagation) {
4716
				this._trigger("beforeStop", event, this._uiHash());
4717
				for (i=0; i < delayedTriggers.length; i++) {
4718
					delayedTriggers[i].call(this, event);
4719
				} //Trigger all delayed events
4720
				this._trigger("stop", event, this._uiHash());
4721
			}
4722
4723
			this.fromOutside = false;
4724
			return false;
4725
		}
4726
4727
		if(!noPropagation) {
4728
			this._trigger("beforeStop", event, this._uiHash());
4729
		}
4730
4731
		//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
4732
		this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
4733
4734
		if(this.helper[0] !== this.currentItem[0]) {
4735
			this.helper.remove();
4736
		}
4737
		this.helper = null;
4738
4739
		if(!noPropagation) {
4740
			for (i=0; i < delayedTriggers.length; i++) {
4741
				delayedTriggers[i].call(this, event);
4742
			} //Trigger all delayed events
4743
			this._trigger("stop", event, this._uiHash());
4744
		}
4745
4746
		this.fromOutside = false;
4747
		return true;
4748
4749
	},
4750
4751
	_trigger: function() {
4752
		if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
4753
			this.cancel();
4754
		}
4755
	},
4756
4757
	_uiHash: function(_inst) {
4758
		var inst = _inst || this;
4759
		return {
4760
			helper: inst.helper,
4761
			placeholder: inst.placeholder || $([]),
4762
			position: inst.position,
4763
			originalPosition: inst.originalPosition,
4764
			offset: inst.positionAbs,
4765
			item: inst.currentItem,
4766
			sender: _inst ? _inst.element : null
4767
		};
4768
	}
4769
4770
});
4771
4772
})(jQuery);
4773
4774
(function($, undefined) {
4775
4776
var dataSpace = "ui-effects-";
4777
4778
$.effects = {
4779
	effect: {}
4780
};
4781
4782
/*!
4783
 * jQuery Color Animations v2.1.2
4784
 * https://github.com/jquery/jquery-color
4785
 *
4786
 * Copyright 2013 jQuery Foundation and other contributors
4787
 * Released under the MIT license.
4788
 * http://jquery.org/license
4789
 *
4790
 * Date: Wed Jan 16 08:47:09 2013 -0600
4791
 */
4792
(function( jQuery, undefined ) {
4793
4794
	var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor",
4795
4796
	// plusequals test for += 100 -= 100
4797
	rplusequals = /^([\-+])=\s*(\d+\.?\d*)/,
4798
	// a set of RE's that can match strings and generate color tuples.
4799
	stringParsers = [{
4800
			re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
4801
			parse: function( execResult ) {
4802
				return [
4803
					execResult[ 1 ],
4804
					execResult[ 2 ],
4805
					execResult[ 3 ],
4806
					execResult[ 4 ]
4807
				];
4808
			}
4809
		}, {
4810
			re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
4811
			parse: function( execResult ) {
4812
				return [
4813
					execResult[ 1 ] * 2.55,
4814
					execResult[ 2 ] * 2.55,
4815
					execResult[ 3 ] * 2.55,
4816
					execResult[ 4 ]
4817
				];
4818
			}
4819
		}, {
4820
			// this regex ignores A-F because it's compared against an already lowercased string
4821
			re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/,
4822
			parse: function( execResult ) {
4823
				return [
4824
					parseInt( execResult[ 1 ], 16 ),
4825
					parseInt( execResult[ 2 ], 16 ),
4826
					parseInt( execResult[ 3 ], 16 )
4827
				];
4828
			}
4829
		}, {
4830
			// this regex ignores A-F because it's compared against an already lowercased string
4831
			re: /#([a-f0-9])([a-f0-9])([a-f0-9])/,
4832
			parse: function( execResult ) {
4833
				return [
4834
					parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ),
4835
					parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ),
4836
					parseInt( execResult[ 3 ] + execResult[ 3 ], 16 )
4837
				];
4838
			}
4839
		}, {
4840
			re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
4841
			space: "hsla",
4842
			parse: function( execResult ) {
4843
				return [
4844
					execResult[ 1 ],
4845
					execResult[ 2 ] / 100,
4846
					execResult[ 3 ] / 100,
4847
					execResult[ 4 ]
4848
				];
4849
			}
4850
		}],
4851
4852
	// jQuery.Color( )
4853
	color = jQuery.Color = function( color, green, blue, alpha ) {
4854
		return new jQuery.Color.fn.parse( color, green, blue, alpha );
4855
	},
4856
	spaces = {
4857
		rgba: {
4858
			props: {
4859
				red: {
4860
					idx: 0,
4861
					type: "byte"
4862
				},
4863
				green: {
4864
					idx: 1,
4865
					type: "byte"
4866
				},
4867
				blue: {
4868
					idx: 2,
4869
					type: "byte"
4870
				}
4871
			}
4872
		},
4873
4874
		hsla: {
4875
			props: {
4876
				hue: {
4877
					idx: 0,
4878
					type: "degrees"
4879
				},
4880
				saturation: {
4881
					idx: 1,
4882
					type: "percent"
4883
				},
4884
				lightness: {
4885
					idx: 2,
4886
					type: "percent"
4887
				}
4888
			}
4889
		}
4890
	},
4891
	propTypes = {
4892
		"byte": {
4893
			floor: true,
4894
			max: 255
4895
		},
4896
		"percent": {
4897
			max: 1
4898
		},
4899
		"degrees": {
4900
			mod: 360,
4901
			floor: true
4902
		}
4903
	},
4904
	support = color.support = {},
4905
4906
	// element for support tests
4907
	supportElem = jQuery( "<p>" )[ 0 ],
4908
4909
	// colors = jQuery.Color.names
4910
	colors,
4911
4912
	// local aliases of functions called often
4913
	each = jQuery.each;
4914
4915
// determine rgba support immediately
4916
supportElem.style.cssText = "background-color:rgba(1,1,1,.5)";
4917
support.rgba = supportElem.style.backgroundColor.indexOf( "rgba" ) > -1;
4918
4919
// define cache name and alpha properties
4920
// for rgba and hsla spaces
4921
each( spaces, function( spaceName, space ) {
4922
	space.cache = "_" + spaceName;
4923
	space.props.alpha = {
4924
		idx: 3,
4925
		type: "percent",
4926
		def: 1
4927
	};
4928
});
4929
4930
function clamp( value, prop, allowEmpty ) {
4931
	var type = propTypes[ prop.type ] || {};
4932
4933
	if ( value == null ) {
4934
		return (allowEmpty || !prop.def) ? null : prop.def;
4935
	}
4936
4937
	// ~~ is an short way of doing floor for positive numbers
4938
	value = type.floor ? ~~value : parseFloat( value );
4939
4940
	// IE will pass in empty strings as value for alpha,
4941
	// which will hit this case
4942
	if ( isNaN( value ) ) {
4943
		return prop.def;
4944
	}
4945
4946
	if ( type.mod ) {
4947
		// we add mod before modding to make sure that negatives values
4948
		// get converted properly: -10 -> 350
4949
		return (value + type.mod) % type.mod;
4950
	}
4951
4952
	// for now all property types without mod have min and max
4953
	return 0 > value ? 0 : type.max < value ? type.max : value;
4954
}
4955
4956
function stringParse( string ) {
4957
	var inst = color(),
4958
		rgba = inst._rgba = [];
4959
4960
	string = string.toLowerCase();
4961
4962
	each( stringParsers, function( i, parser ) {
4963
		var parsed,
4964
			match = parser.re.exec( string ),
4965
			values = match && parser.parse( match ),
4966
			spaceName = parser.space || "rgba";
4967
4968
		if ( values ) {
4969
			parsed = inst[ spaceName ]( values );
4970
4971
			// if this was an rgba parse the assignment might happen twice
4972
			// oh well....
4973
			inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ];
4974
			rgba = inst._rgba = parsed._rgba;
4975
4976
			// exit each( stringParsers ) here because we matched
4977
			return false;
4978
		}
4979
	});
4980
4981
	// Found a stringParser that handled it
4982
	if ( rgba.length ) {
4983
4984
		// if this came from a parsed string, force "transparent" when alpha is 0
4985
		// chrome, (and maybe others) return "transparent" as rgba(0,0,0,0)
4986
		if ( rgba.join() === "0,0,0,0" ) {
4987
			jQuery.extend( rgba, colors.transparent );
4988
		}
4989
		return inst;
4990
	}
4991
4992
	// named colors
4993
	return colors[ string ];
4994
}
4995
4996
color.fn = jQuery.extend( color.prototype, {
4997
	parse: function( red, green, blue, alpha ) {
4998
		if ( red === undefined ) {
4999
			this._rgba = [ null, null, null, null ];
5000
			return this;
5001
		}
5002
		if ( red.jquery || red.nodeType ) {
5003
			red = jQuery( red ).css( green );
5004
			green = undefined;
5005
		}
5006
5007
		var inst = this,
5008
			type = jQuery.type( red ),
5009
			rgba = this._rgba = [];
5010
5011
		// more than 1 argument specified - assume ( red, green, blue, alpha )
5012
		if ( green !== undefined ) {
5013
			red = [ red, green, blue, alpha ];
5014
			type = "array";
5015
		}
5016
5017
		if ( type === "string" ) {
5018
			return this.parse( stringParse( red ) || colors._default );
5019
		}
5020
5021
		if ( type === "array" ) {
5022
			each( spaces.rgba.props, function( key, prop ) {
5023
				rgba[ prop.idx ] = clamp( red[ prop.idx ], prop );
5024
			});
5025
			return this;
5026
		}
5027
5028
		if ( type === "object" ) {
5029
			if ( red instanceof color ) {
5030
				each( spaces, function( spaceName, space ) {
5031
					if ( red[ space.cache ] ) {
5032
						inst[ space.cache ] = red[ space.cache ].slice();
5033
					}
5034
				});
5035
			} else {
5036
				each( spaces, function( spaceName, space ) {
5037
					var cache = space.cache;
5038
					each( space.props, function( key, prop ) {
5039
5040
						// if the cache doesn't exist, and we know how to convert
5041
						if ( !inst[ cache ] && space.to ) {
5042
5043
							// if the value was null, we don't need to copy it
5044
							// if the key was alpha, we don't need to copy it either
5045
							if ( key === "alpha" || red[ key ] == null ) {
5046
								return;
5047
							}
5048
							inst[ cache ] = space.to( inst._rgba );
5049
						}
5050
5051
						// this is the only case where we allow nulls for ALL properties.
5052
						// call clamp with alwaysAllowEmpty
5053
						inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true );
5054
					});
5055
5056
					// everything defined but alpha?
5057
					if ( inst[ cache ] && jQuery.inArray( null, inst[ cache ].slice( 0, 3 ) ) < 0 ) {
5058
						// use the default of 1
5059
						inst[ cache ][ 3 ] = 1;
5060
						if ( space.from ) {
5061
							inst._rgba = space.from( inst[ cache ] );
5062
						}
5063
					}
5064
				});
5065
			}
5066
			return this;
5067
		}
5068
	},
5069
	is: function( compare ) {
5070
		var is = color( compare ),
5071
			same = true,
5072
			inst = this;
5073
5074
		each( spaces, function( _, space ) {
5075
			var localCache,
5076
				isCache = is[ space.cache ];
5077
			if (isCache) {
5078
				localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || [];
5079
				each( space.props, function( _, prop ) {
5080
					if ( isCache[ prop.idx ] != null ) {
5081
						same = ( isCache[ prop.idx ] === localCache[ prop.idx ] );
5082
						return same;
5083
					}
5084
				});
5085
			}
5086
			return same;
5087
		});
5088
		return same;
5089
	},
5090
	_space: function() {
5091
		var used = [],
5092
			inst = this;
5093
		each( spaces, function( spaceName, space ) {
5094
			if ( inst[ space.cache ] ) {
5095
				used.push( spaceName );
5096
			}
5097
		});
5098
		return used.pop();
5099
	},
5100
	transition: function( other, distance ) {
5101
		var end = color( other ),
5102
			spaceName = end._space(),
5103
			space = spaces[ spaceName ],
5104
			startColor = this.alpha() === 0 ? color( "transparent" ) : this,
5105
			start = startColor[ space.cache ] || space.to( startColor._rgba ),
5106
			result = start.slice();
5107
5108
		end = end[ space.cache ];
5109
		each( space.props, function( key, prop ) {
5110
			var index = prop.idx,
5111
				startValue = start[ index ],
5112
				endValue = end[ index ],
5113
				type = propTypes[ prop.type ] || {};
5114
5115
			// if null, don't override start value
5116
			if ( endValue === null ) {
5117
				return;
5118
			}
5119
			// if null - use end
5120
			if ( startValue === null ) {
5121
				result[ index ] = endValue;
5122
			} else {
5123
				if ( type.mod ) {
5124
					if ( endValue - startValue > type.mod / 2 ) {
5125
						startValue += type.mod;
5126
					} else if ( startValue - endValue > type.mod / 2 ) {
5127
						startValue -= type.mod;
5128
					}
5129
				}
5130
				result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop );
5131
			}
5132
		});
5133
		return this[ spaceName ]( result );
5134
	},
5135
	blend: function( opaque ) {
5136
		// if we are already opaque - return ourself
5137
		if ( this._rgba[ 3 ] === 1 ) {
5138
			return this;
5139
		}
5140
5141
		var rgb = this._rgba.slice(),
5142
			a = rgb.pop(),
5143
			blend = color( opaque )._rgba;
5144
5145
		return color( jQuery.map( rgb, function( v, i ) {
5146
			return ( 1 - a ) * blend[ i ] + a * v;
5147
		}));
5148
	},
5149
	toRgbaString: function() {
5150
		var prefix = "rgba(",
5151
			rgba = jQuery.map( this._rgba, function( v, i ) {
5152
				return v == null ? ( i > 2 ? 1 : 0 ) : v;
5153
			});
5154
5155
		if ( rgba[ 3 ] === 1 ) {
5156
			rgba.pop();
5157
			prefix = "rgb(";
5158
		}
5159
5160
		return prefix + rgba.join() + ")";
5161
	},
5162
	toHslaString: function() {
5163
		var prefix = "hsla(",
5164
			hsla = jQuery.map( this.hsla(), function( v, i ) {
5165
				if ( v == null ) {
5166
					v = i > 2 ? 1 : 0;
5167
				}
5168
5169
				// catch 1 and 2
5170
				if ( i && i < 3 ) {
5171
					v = Math.round( v * 100 ) + "%";
5172
				}
5173
				return v;
5174
			});
5175
5176
		if ( hsla[ 3 ] === 1 ) {
5177
			hsla.pop();
5178
			prefix = "hsl(";
5179
		}
5180
		return prefix + hsla.join() + ")";
5181
	},
5182
	toHexString: function( includeAlpha ) {
5183
		var rgba = this._rgba.slice(),
5184
			alpha = rgba.pop();
5185
5186
		if ( includeAlpha ) {
5187
			rgba.push( ~~( alpha * 255 ) );
5188
		}
5189
5190
		return "#" + jQuery.map( rgba, function( v ) {
5191
5192
			// default to 0 when nulls exist
5193
			v = ( v || 0 ).toString( 16 );
5194
			return v.length === 1 ? "0" + v : v;
5195
		}).join("");
5196
	},
5197
	toString: function() {
5198
		return this._rgba[ 3 ] === 0 ? "transparent" : this.toRgbaString();
5199
	}
5200
});
5201
color.fn.parse.prototype = color.fn;
5202
5203
// hsla conversions adapted from:
5204
// https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021
5205
5206
function hue2rgb( p, q, h ) {
5207
	h = ( h + 1 ) % 1;
5208
	if ( h * 6 < 1 ) {
5209
		return p + (q - p) * h * 6;
5210
	}
5211
	if ( h * 2 < 1) {
5212
		return q;
5213
	}
5214
	if ( h * 3 < 2 ) {
5215
		return p + (q - p) * ((2/3) - h) * 6;
5216
	}
5217
	return p;
5218
}
5219
5220
spaces.hsla.to = function ( rgba ) {
5221
	if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) {
5222
		return [ null, null, null, rgba[ 3 ] ];
5223
	}
5224
	var r = rgba[ 0 ] / 255,
5225
		g = rgba[ 1 ] / 255,
5226
		b = rgba[ 2 ] / 255,
5227
		a = rgba[ 3 ],
5228
		max = Math.max( r, g, b ),
5229
		min = Math.min( r, g, b ),
5230
		diff = max - min,
5231
		add = max + min,
5232
		l = add * 0.5,
5233
		h, s;
5234
5235
	if ( min === max ) {
5236
		h = 0;
5237
	} else if ( r === max ) {
5238
		h = ( 60 * ( g - b ) / diff ) + 360;
5239
	} else if ( g === max ) {
5240
		h = ( 60 * ( b - r ) / diff ) + 120;
5241
	} else {
5242
		h = ( 60 * ( r - g ) / diff ) + 240;
5243
	}
5244
5245
	// chroma (diff) == 0 means greyscale which, by definition, saturation = 0%
5246
	// otherwise, saturation is based on the ratio of chroma (diff) to lightness (add)
5247
	if ( diff === 0 ) {
5248
		s = 0;
5249
	} else if ( l <= 0.5 ) {
5250
		s = diff / add;
5251
	} else {
5252
		s = diff / ( 2 - add );
5253
	}
5254
	return [ Math.round(h) % 360, s, l, a == null ? 1 : a ];
5255
};
5256
5257
spaces.hsla.from = function ( hsla ) {
5258
	if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) {
5259
		return [ null, null, null, hsla[ 3 ] ];
5260
	}
5261
	var h = hsla[ 0 ] / 360,
5262
		s = hsla[ 1 ],
5263
		l = hsla[ 2 ],
5264
		a = hsla[ 3 ],
5265
		q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s,
5266
		p = 2 * l - q;
5267
5268
	return [
5269
		Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ),
5270
		Math.round( hue2rgb( p, q, h ) * 255 ),
5271
		Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ),
5272
		a
5273
	];
5274
};
5275
5276
5277
each( spaces, function( spaceName, space ) {
5278
	var props = space.props,
5279
		cache = space.cache,
5280
		to = space.to,
5281
		from = space.from;
5282
5283
	// makes rgba() and hsla()
5284
	color.fn[ spaceName ] = function( value ) {
5285
5286
		// generate a cache for this space if it doesn't exist
5287
		if ( to && !this[ cache ] ) {
5288
			this[ cache ] = to( this._rgba );
5289
		}
5290
		if ( value === undefined ) {
5291
			return this[ cache ].slice();
5292
		}
5293
5294
		var ret,
5295
			type = jQuery.type( value ),
5296
			arr = ( type === "array" || type === "object" ) ? value : arguments,
5297
			local = this[ cache ].slice();
5298
5299
		each( props, function( key, prop ) {
5300
			var val = arr[ type === "object" ? key : prop.idx ];
5301
			if ( val == null ) {
5302
				val = local[ prop.idx ];
5303
			}
5304
			local[ prop.idx ] = clamp( val, prop );
5305
		});
5306
5307
		if ( from ) {
5308
			ret = color( from( local ) );
5309
			ret[ cache ] = local;
5310
			return ret;
5311
		} else {
5312
			return color( local );
5313
		}
5314
	};
5315
5316
	// makes red() green() blue() alpha() hue() saturation() lightness()
5317
	each( props, function( key, prop ) {
5318
		// alpha is included in more than one space
5319
		if ( color.fn[ key ] ) {
5320
			return;
5321
		}
5322
		color.fn[ key ] = function( value ) {
5323
			var vtype = jQuery.type( value ),
5324
				fn = ( key === "alpha" ? ( this._hsla ? "hsla" : "rgba" ) : spaceName ),
5325
				local = this[ fn ](),
5326
				cur = local[ prop.idx ],
5327
				match;
5328
5329
			if ( vtype === "undefined" ) {
5330
				return cur;
5331
			}
5332
5333
			if ( vtype === "function" ) {
5334
				value = value.call( this, cur );
5335
				vtype = jQuery.type( value );
5336
			}
5337
			if ( value == null && prop.empty ) {
5338
				return this;
5339
			}
5340
			if ( vtype === "string" ) {
5341
				match = rplusequals.exec( value );
5342
				if ( match ) {
5343
					value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 );
5344
				}
5345
			}
5346
			local[ prop.idx ] = value;
5347
			return this[ fn ]( local );
5348
		};
5349
	});
5350
});
5351
5352
// add cssHook and .fx.step function for each named hook.
5353
// accept a space separated string of properties
5354
color.hook = function( hook ) {
5355
	var hooks = hook.split( " " );
5356
	each( hooks, function( i, hook ) {
5357
		jQuery.cssHooks[ hook ] = {
5358
			set: function( elem, value ) {
5359
				var parsed, curElem,
5360
					backgroundColor = "";
5361
5362
				if ( value !== "transparent" && ( jQuery.type( value ) !== "string" || ( parsed = stringParse( value ) ) ) ) {
5363
					value = color( parsed || value );
5364
					if ( !support.rgba && value._rgba[ 3 ] !== 1 ) {
5365
						curElem = hook === "backgroundColor" ? elem.parentNode : elem;
5366
						while (
5367
							(backgroundColor === "" || backgroundColor === "transparent") &&
5368
							curElem && curElem.style
5369
						) {
5370
							try {
5371
								backgroundColor = jQuery.css( curElem, "backgroundColor" );
5372
								curElem = curElem.parentNode;
5373
							} catch ( e ) {
5374
							}
5375
						}
5376
5377
						value = value.blend( backgroundColor && backgroundColor !== "transparent" ?
5378
							backgroundColor :
5379
							"_default" );
5380
					}
5381
5382
					value = value.toRgbaString();
5383
				}
5384
				try {
5385
					elem.style[ hook ] = value;
5386
				} catch( e ) {
5387
					// wrapped to prevent IE from throwing errors on "invalid" values like 'auto' or 'inherit'
5388
				}
5389
			}
5390
		};
5391
		jQuery.fx.step[ hook ] = function( fx ) {
5392
			if ( !fx.colorInit ) {
5393
				fx.start = color( fx.elem, hook );
5394
				fx.end = color( fx.end );
5395
				fx.colorInit = true;
5396
			}
5397
			jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) );
5398
		};
5399
	});
5400
5401
};
5402
5403
color.hook( stepHooks );
5404
5405
jQuery.cssHooks.borderColor = {
5406
	expand: function( value ) {
5407
		var expanded = {};
5408
5409
		each( [ "Top", "Right", "Bottom", "Left" ], function( i, part ) {
5410
			expanded[ "border" + part + "Color" ] = value;
5411
		});
5412
		return expanded;
5413
	}
5414
};
5415
5416
// Basic color names only.
5417
// Usage of any of the other color names requires adding yourself or including
5418
// jquery.color.svg-names.js.
5419
colors = jQuery.Color.names = {
5420
	// 4.1. Basic color keywords
5421
	aqua: "#00ffff",
5422
	black: "#000000",
5423
	blue: "#0000ff",
5424
	fuchsia: "#ff00ff",
5425
	gray: "#808080",
5426
	green: "#008000",
5427
	lime: "#00ff00",
5428
	maroon: "#800000",
5429
	navy: "#000080",
5430
	olive: "#808000",
5431
	purple: "#800080",
5432
	red: "#ff0000",
5433
	silver: "#c0c0c0",
5434
	teal: "#008080",
5435
	white: "#ffffff",
5436
	yellow: "#ffff00",
5437
5438
	// 4.2.3. "transparent" color keyword
5439
	transparent: [ null, null, null, 0 ],
5440
5441
	_default: "#ffffff"
5442
};
5443
5444
})( jQuery );
5445
5446
5447
/******************************************************************************/
5448
/****************************** CLASS ANIMATIONS ******************************/
5449
/******************************************************************************/
5450
(function() {
5451
5452
var classAnimationActions = [ "add", "remove", "toggle" ],
5453
	shorthandStyles = {
5454
		border: 1,
5455
		borderBottom: 1,
5456
		borderColor: 1,
5457
		borderLeft: 1,
5458
		borderRight: 1,
5459
		borderTop: 1,
5460
		borderWidth: 1,
5461
		margin: 1,
5462
		padding: 1
5463
	};
5464
5465
$.each([ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ], function( _, prop ) {
5466
	$.fx.step[ prop ] = function( fx ) {
5467
		if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) {
5468
			jQuery.style( fx.elem, prop, fx.end );
5469
			fx.setAttr = true;
5470
		}
5471
	};
5472
});
5473
5474
function getElementStyles( elem ) {
5475
	var key, len,
5476
		style = elem.ownerDocument.defaultView ?
5477
			elem.ownerDocument.defaultView.getComputedStyle( elem, null ) :
5478
			elem.currentStyle,
5479
		styles = {};
5480
5481
	if ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) {
5482
		len = style.length;
5483
		while ( len-- ) {
5484
			key = style[ len ];
5485
			if ( typeof style[ key ] === "string" ) {
5486
				styles[ $.camelCase( key ) ] = style[ key ];
5487
			}
5488
		}
5489
	// support: Opera, IE <9
5490
	} else {
5491
		for ( key in style ) {
5492
			if ( typeof style[ key ] === "string" ) {
5493
				styles[ key ] = style[ key ];
5494
			}
5495
		}
5496
	}
5497
5498
	return styles;
5499
}
5500
5501
5502
function styleDifference( oldStyle, newStyle ) {
5503
	var diff = {},
5504
		name, value;
5505
5506
	for ( name in newStyle ) {
5507
		value = newStyle[ name ];
5508
		if ( oldStyle[ name ] !== value ) {
5509
			if ( !shorthandStyles[ name ] ) {
5510
				if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) {
5511
					diff[ name ] = value;
5512
				}
5513
			}
5514
		}
5515
	}
5516
5517
	return diff;
5518
}
5519
5520
// support: jQuery <1.8
5521
if ( !$.fn.addBack ) {
5522
	$.fn.addBack = function( selector ) {
5523
		return this.add( selector == null ?
5524
			this.prevObject : this.prevObject.filter( selector )
5525
		);
5526
	};
5527
}
5528
5529
$.effects.animateClass = function( value, duration, easing, callback ) {
5530
	var o = $.speed( duration, easing, callback );
5531
5532
	return this.queue( function() {
5533
		var animated = $( this ),
5534
			baseClass = animated.attr( "class" ) || "",
5535
			applyClassChange,
5536
			allAnimations = o.children ? animated.find( "*" ).addBack() : animated;
5537
5538
		// map the animated objects to store the original styles.
5539
		allAnimations = allAnimations.map(function() {
5540
			var el = $( this );
5541
			return {
5542
				el: el,
5543
				start: getElementStyles( this )
5544
			};
5545
		});
5546
5547
		// apply class change
5548
		applyClassChange = function() {
5549
			$.each( classAnimationActions, function(i, action) {
5550
				if ( value[ action ] ) {
5551
					animated[ action + "Class" ]( value[ action ] );
5552
				}
5553
			});
5554
		};
5555
		applyClassChange();
5556
5557
		// map all animated objects again - calculate new styles and diff
5558
		allAnimations = allAnimations.map(function() {
5559
			this.end = getElementStyles( this.el[ 0 ] );
5560
			this.diff = styleDifference( this.start, this.end );
5561
			return this;
5562
		});
5563
5564
		// apply original class
5565
		animated.attr( "class", baseClass );
5566
5567
		// map all animated objects again - this time collecting a promise
5568
		allAnimations = allAnimations.map(function() {
5569
			var styleInfo = this,
5570
				dfd = $.Deferred(),
5571
				opts = $.extend({}, o, {
5572
					queue: false,
5573
					complete: function() {
5574
						dfd.resolve( styleInfo );
5575
					}
5576
				});
5577
5578
			this.el.animate( this.diff, opts );
5579
			return dfd.promise();
5580
		});
5581
5582
		// once all animations have completed:
5583
		$.when.apply( $, allAnimations.get() ).done(function() {
5584
5585
			// set the final class
5586
			applyClassChange();
5587
5588
			// for each animated element,
5589
			// clear all css properties that were animated
5590
			$.each( arguments, function() {
5591
				var el = this.el;
5592
				$.each( this.diff, function(key) {
5593
					el.css( key, "" );
5594
				});
5595
			});
5596
5597
			// this is guarnteed to be there if you use jQuery.speed()
5598
			// it also handles dequeuing the next anim...
5599
			o.complete.call( animated[ 0 ] );
5600
		});
5601
	});
5602
};
5603
5604
$.fn.extend({
5605
	addClass: (function( orig ) {
5606
		return function( classNames, speed, easing, callback ) {
5607
			return speed ?
5608
				$.effects.animateClass.call( this,
5609
					{ add: classNames }, speed, easing, callback ) :
5610
				orig.apply( this, arguments );
5611
		};
5612
	})( $.fn.addClass ),
5613
5614
	removeClass: (function( orig ) {
5615
		return function( classNames, speed, easing, callback ) {
5616
			return arguments.length > 1 ?
5617
				$.effects.animateClass.call( this,
5618
					{ remove: classNames }, speed, easing, callback ) :
5619
				orig.apply( this, arguments );
5620
		};
5621
	})( $.fn.removeClass ),
5622
5623
	toggleClass: (function( orig ) {
5624
		return function( classNames, force, speed, easing, callback ) {
5625
			if ( typeof force === "boolean" || force === undefined ) {
5626
				if ( !speed ) {
5627
					// without speed parameter
5628
					return orig.apply( this, arguments );
5629
				} else {
5630
					return $.effects.animateClass.call( this,
5631
						(force ? { add: classNames } : { remove: classNames }),
5632
						speed, easing, callback );
5633
				}
5634
			} else {
5635
				// without force parameter
5636
				return $.effects.animateClass.call( this,
5637
					{ toggle: classNames }, force, speed, easing );
5638
			}
5639
		};
5640
	})( $.fn.toggleClass ),
5641
5642
	switchClass: function( remove, add, speed, easing, callback) {
5643
		return $.effects.animateClass.call( this, {
5644
			add: add,
5645
			remove: remove
5646
		}, speed, easing, callback );
5647
	}
5648
});
5649
5650
})();
5651
5652
/******************************************************************************/
5653
/*********************************** EFFECTS **********************************/
5654
/******************************************************************************/
5655
5656
(function() {
5657
5658
$.extend( $.effects, {
5659
	version: "1.10.3",
5660
5661
	// Saves a set of properties in a data storage
5662
	save: function( element, set ) {
5663
		for( var i=0; i < set.length; i++ ) {
5664
			if ( set[ i ] !== null ) {
5665
				element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] );
5666
			}
5667
		}
5668
	},
5669
5670
	// Restores a set of previously saved properties from a data storage
5671
	restore: function( element, set ) {
5672
		var val, i;
5673
		for( i=0; i < set.length; i++ ) {
5674
			if ( set[ i ] !== null ) {
5675
				val = element.data( dataSpace + set[ i ] );
5676
				// support: jQuery 1.6.2
5677
				// http://bugs.jquery.com/ticket/9917
5678
				// jQuery 1.6.2 incorrectly returns undefined for any falsy value.
5679
				// We can't differentiate between "" and 0 here, so we just assume
5680
				// empty string since it's likely to be a more common value...
5681
				if ( val === undefined ) {
5682
					val = "";
5683
				}
5684
				element.css( set[ i ], val );
5685
			}
5686
		}
5687
	},
5688
5689
	setMode: function( el, mode ) {
5690
		if (mode === "toggle") {
5691
			mode = el.is( ":hidden" ) ? "show" : "hide";
5692
		}
5693
		return mode;
5694
	},
5695
5696
	// Translates a [top,left] array into a baseline value
5697
	// this should be a little more flexible in the future to handle a string & hash
5698
	getBaseline: function( origin, original ) {
5699
		var y, x;
5700
		switch ( origin[ 0 ] ) {
5701
			case "top": y = 0; break;
5702
			case "middle": y = 0.5; break;
5703
			case "bottom": y = 1; break;
5704
			default: y = origin[ 0 ] / original.height;
5705
		}
5706
		switch ( origin[ 1 ] ) {
5707
			case "left": x = 0; break;
5708
			case "center": x = 0.5; break;
5709
			case "right": x = 1; break;
5710
			default: x = origin[ 1 ] / original.width;
5711
		}
5712
		return {
5713
			x: x,
5714
			y: y
5715
		};
5716
	},
5717
5718
	// Wraps the element around a wrapper that copies position properties
5719
	createWrapper: function( element ) {
5720
5721
		// if the element is already wrapped, return it
5722
		if ( element.parent().is( ".ui-effects-wrapper" )) {
5723
			return element.parent();
5724
		}
5725
5726
		// wrap the element
5727
		var props = {
5728
				width: element.outerWidth(true),
5729
				height: element.outerHeight(true),
5730
				"float": element.css( "float" )
5731
			},
5732
			wrapper = $( "<div></div>" )
5733
				.addClass( "ui-effects-wrapper" )
5734
				.css({
5735
					fontSize: "100%",
5736
					background: "transparent",
5737
					border: "none",
5738
					margin: 0,
5739
					padding: 0
5740
				}),
5741
			// Store the size in case width/height are defined in % - Fixes #5245
5742
			size = {
5743
				width: element.width(),
5744
				height: element.height()
5745
			},
5746
			active = document.activeElement;
5747
5748
		// support: Firefox
5749
		// Firefox incorrectly exposes anonymous content
5750
		// https://bugzilla.mozilla.org/show_bug.cgi?id=561664
5751
		try {
5752
			active.id;
5753
		} catch( e ) {
5754
			active = document.body;
5755
		}
5756
5757
		element.wrap( wrapper );
5758
5759
		// Fixes #7595 - Elements lose focus when wrapped.
5760
		if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
5761
			$( active ).focus();
5762
		}
5763
5764
		wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually lose the reference to the wrapped element
5765
5766
		// transfer positioning properties to the wrapper
5767
		if ( element.css( "position" ) === "static" ) {
5768
			wrapper.css({ position: "relative" });
5769
			element.css({ position: "relative" });
5770
		} else {
5771
			$.extend( props, {
5772
				position: element.css( "position" ),
5773
				zIndex: element.css( "z-index" )
5774
			});
5775
			$.each([ "top", "left", "bottom", "right" ], function(i, pos) {
5776
				props[ pos ] = element.css( pos );
5777
				if ( isNaN( parseInt( props[ pos ], 10 ) ) ) {
5778
					props[ pos ] = "auto";
5779
				}
5780
			});
5781
			element.css({
5782
				position: "relative",
5783
				top: 0,
5784
				left: 0,
5785
				right: "auto",
5786
				bottom: "auto"
5787
			});
5788
		}
5789
		element.css(size);
5790
5791
		return wrapper.css( props ).show();
5792
	},
5793
5794
	removeWrapper: function( element ) {
5795
		var active = document.activeElement;
5796
5797
		if ( element.parent().is( ".ui-effects-wrapper" ) ) {
5798
			element.parent().replaceWith( element );
5799
5800
			// Fixes #7595 - Elements lose focus when wrapped.
5801
			if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
5802
				$( active ).focus();
5803
			}
5804
		}
5805
5806
5807
		return element;
5808
	},
5809
5810
	setTransition: function( element, list, factor, value ) {
5811
		value = value || {};
5812
		$.each( list, function( i, x ) {
5813
			var unit = element.cssUnit( x );
5814
			if ( unit[ 0 ] > 0 ) {
5815
				value[ x ] = unit[ 0 ] * factor + unit[ 1 ];
5816
			}
5817
		});
5818
		return value;
5819
	}
5820
});
5821
5822
// return an effect options object for the given parameters:
5823
function _normalizeArguments( effect, options, speed, callback ) {
5824
5825
	// allow passing all options as the first parameter
5826
	if ( $.isPlainObject( effect ) ) {
5827
		options = effect;
5828
		effect = effect.effect;
5829
	}
5830
5831
	// convert to an object
5832
	effect = { effect: effect };
5833
5834
	// catch (effect, null, ...)
5835
	if ( options == null ) {
5836
		options = {};
5837
	}
5838
5839
	// catch (effect, callback)
5840
	if ( $.isFunction( options ) ) {
5841
		callback = options;
5842
		speed = null;
5843
		options = {};
5844
	}
5845
5846
	// catch (effect, speed, ?)
5847
	if ( typeof options === "number" || $.fx.speeds[ options ] ) {
5848
		callback = speed;
5849
		speed = options;
5850
		options = {};
5851
	}
5852
5853
	// catch (effect, options, callback)
5854
	if ( $.isFunction( speed ) ) {
5855
		callback = speed;
5856
		speed = null;
5857
	}
5858
5859
	// add options to effect
5860
	if ( options ) {
5861
		$.extend( effect, options );
5862
	}
5863
5864
	speed = speed || options.duration;
5865
	effect.duration = $.fx.off ? 0 :
5866
		typeof speed === "number" ? speed :
5867
		speed in $.fx.speeds ? $.fx.speeds[ speed ] :
5868
		$.fx.speeds._default;
5869
5870
	effect.complete = callback || options.complete;
5871
5872
	return effect;
5873
}
5874
5875
function standardAnimationOption( option ) {
5876
	// Valid standard speeds (nothing, number, named speed)
5877
	if ( !option || typeof option === "number" || $.fx.speeds[ option ] ) {
5878
		return true;
5879
	}
5880
5881
	// Invalid strings - treat as "normal" speed
5882
	if ( typeof option === "string" && !$.effects.effect[ option ] ) {
5883
		return true;
5884
	}
5885
5886
	// Complete callback
5887
	if ( $.isFunction( option ) ) {
5888
		return true;
5889
	}
5890
5891
	// Options hash (but not naming an effect)
5892
	if ( typeof option === "object" && !option.effect ) {
5893
		return true;
5894
	}
5895
5896
	// Didn't match any standard API
5897
	return false;
5898
}
5899
5900
$.fn.extend({
5901
	effect: function( /* effect, options, speed, callback */ ) {
5902
		var args = _normalizeArguments.apply( this, arguments ),
5903
			mode = args.mode,
5904
			queue = args.queue,
5905
			effectMethod = $.effects.effect[ args.effect ];
5906
5907
		if ( $.fx.off || !effectMethod ) {
5908
			// delegate to the original method (e.g., .show()) if possible
5909
			if ( mode ) {
5910
				return this[ mode ]( args.duration, args.complete );
5911
			} else {
5912
				return this.each( function() {
5913
					if ( args.complete ) {
5914
						args.complete.call( this );
5915
					}
5916
				});
5917
			}
5918
		}
5919
5920
		function run( next ) {
5921
			var elem = $( this ),
5922
				complete = args.complete,
5923
				mode = args.mode;
5924
5925
			function done() {
5926
				if ( $.isFunction( complete ) ) {
5927
					complete.call( elem[0] );
5928
				}
5929
				if ( $.isFunction( next ) ) {
5930
					next();
5931
				}
5932
			}
5933
5934
			// If the element already has the correct final state, delegate to
5935
			// the core methods so the internal tracking of "olddisplay" works.
5936
			if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) {
5937
				elem[ mode ]();
5938
				done();
5939
			} else {
5940
				effectMethod.call( elem[0], args, done );
5941
			}
5942
		}
5943
5944
		return queue === false ? this.each( run ) : this.queue( queue || "fx", run );
5945
	},
5946
5947
	show: (function( orig ) {
5948
		return function( option ) {
5949
			if ( standardAnimationOption( option ) ) {
5950
				return orig.apply( this, arguments );
5951
			} else {
5952
				var args = _normalizeArguments.apply( this, arguments );
5953
				args.mode = "show";
5954
				return this.effect.call( this, args );
5955
			}
5956
		};
5957
	})( $.fn.show ),
5958
5959
	hide: (function( orig ) {
5960
		return function( option ) {
5961
			if ( standardAnimationOption( option ) ) {
5962
				return orig.apply( this, arguments );
5963
			} else {
5964
				var args = _normalizeArguments.apply( this, arguments );
5965
				args.mode = "hide";
5966
				return this.effect.call( this, args );
5967
			}
5968
		};
5969
	})( $.fn.hide ),
5970
5971
	toggle: (function( orig ) {
5972
		return function( option ) {
5973
			if ( standardAnimationOption( option ) || typeof option === "boolean" ) {
5974
				return orig.apply( this, arguments );
5975
			} else {
5976
				var args = _normalizeArguments.apply( this, arguments );
5977
				args.mode = "toggle";
5978
				return this.effect.call( this, args );
5979
			}
5980
		};
5981
	})( $.fn.toggle ),
5982
5983
	// helper functions
5984
	cssUnit: function(key) {
5985
		var style = this.css( key ),
5986
			val = [];
5987
5988
		$.each( [ "em", "px", "%", "pt" ], function( i, unit ) {
5989
			if ( style.indexOf( unit ) > 0 ) {
5990
				val = [ parseFloat( style ), unit ];
5991
			}
5992
		});
5993
		return val;
5994
	}
5995
});
5996
5997
})();
5998
5999
/******************************************************************************/
6000
/*********************************** EASING ***********************************/
6001
/******************************************************************************/
6002
6003
(function() {
6004
6005
// based on easing equations from Robert Penner (http://www.robertpenner.com/easing)
6006
6007
var baseEasings = {};
6008
6009
$.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) {
6010
	baseEasings[ name ] = function( p ) {
6011
		return Math.pow( p, i + 2 );
6012
	};
6013
});
6014
6015
$.extend( baseEasings, {
6016
	Sine: function ( p ) {
6017
		return 1 - Math.cos( p * Math.PI / 2 );
6018
	},
6019
	Circ: function ( p ) {
6020
		return 1 - Math.sqrt( 1 - p * p );
6021
	},
6022
	Elastic: function( p ) {
6023
		return p === 0 || p === 1 ? p :
6024
			-Math.pow( 2, 8 * (p - 1) ) * Math.sin( ( (p - 1) * 80 - 7.5 ) * Math.PI / 15 );
6025
	},
6026
	Back: function( p ) {
6027
		return p * p * ( 3 * p - 2 );
6028
	},
6029
	Bounce: function ( p ) {
6030
		var pow2,
6031
			bounce = 4;
6032
6033
		while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {}
0 ignored issues
show
Comprehensibility Documentation Best Practice introduced by
This code block is empty. Consider removing it or adding a comment to explain.
Loading history...
6034
		return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 );
6035
	}
6036
});
6037
6038
$.each( baseEasings, function( name, easeIn ) {
6039
	$.easing[ "easeIn" + name ] = easeIn;
6040
	$.easing[ "easeOut" + name ] = function( p ) {
6041
		return 1 - easeIn( 1 - p );
6042
	};
6043
	$.easing[ "easeInOut" + name ] = function( p ) {
6044
		return p < 0.5 ?
6045
			easeIn( p * 2 ) / 2 :
6046
			1 - easeIn( p * -2 + 2 ) / 2;
6047
	};
6048
});
6049
6050
})();
6051
6052
})(jQuery);
6053
6054
(function( $, undefined ) {
6055
6056
var uid = 0,
6057
	hideProps = {},
6058
	showProps = {};
6059
6060
hideProps.height = hideProps.paddingTop = hideProps.paddingBottom =
6061
	hideProps.borderTopWidth = hideProps.borderBottomWidth = "hide";
6062
showProps.height = showProps.paddingTop = showProps.paddingBottom =
6063
	showProps.borderTopWidth = showProps.borderBottomWidth = "show";
6064
6065
$.widget( "ui.accordion", {
6066
	version: "1.10.3",
6067
	options: {
6068
		active: 0,
6069
		animate: {},
6070
		collapsible: false,
6071
		event: "click",
6072
		header: "> li > :first-child,> :not(li):even",
6073
		heightStyle: "auto",
6074
		icons: {
6075
			activeHeader: "ui-icon-triangle-1-s",
6076
			header: "ui-icon-triangle-1-e"
6077
		},
6078
6079
		// callbacks
6080
		activate: null,
6081
		beforeActivate: null
6082
	},
6083
6084
	_create: function() {
6085
		var options = this.options;
6086
		this.prevShow = this.prevHide = $();
6087
		this.element.addClass( "ui-accordion ui-widget ui-helper-reset" )
6088
			// ARIA
6089
			.attr( "role", "tablist" );
6090
6091
		// don't allow collapsible: false and active: false / null
6092
		if ( !options.collapsible && (options.active === false || options.active == null) ) {
6093
			options.active = 0;
6094
		}
6095
6096
		this._processPanels();
6097
		// handle negative values
6098
		if ( options.active < 0 ) {
6099
			options.active += this.headers.length;
6100
		}
6101
		this._refresh();
6102
	},
6103
6104
	_getCreateEventData: function() {
6105
		return {
6106
			header: this.active,
6107
			panel: !this.active.length ? $() : this.active.next(),
6108
			content: !this.active.length ? $() : this.active.next()
6109
		};
6110
	},
6111
6112
	_createIcons: function() {
6113
		var icons = this.options.icons;
6114
		if ( icons ) {
6115
			$( "<span>" )
6116
				.addClass( "ui-accordion-header-icon ui-icon " + icons.header )
6117
				.prependTo( this.headers );
6118
			this.active.children( ".ui-accordion-header-icon" )
6119
				.removeClass( icons.header )
6120
				.addClass( icons.activeHeader );
6121
			this.headers.addClass( "ui-accordion-icons" );
6122
		}
6123
	},
6124
6125
	_destroyIcons: function() {
6126
		this.headers
6127
			.removeClass( "ui-accordion-icons" )
6128
			.children( ".ui-accordion-header-icon" )
6129
				.remove();
6130
	},
6131
6132
	_destroy: function() {
6133
		var contents;
6134
6135
		// clean up main element
6136
		this.element
6137
			.removeClass( "ui-accordion ui-widget ui-helper-reset" )
6138
			.removeAttr( "role" );
6139
6140
		// clean up headers
6141
		this.headers
6142
			.removeClass( "ui-accordion-header ui-accordion-header-active ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top" )
6143
			.removeAttr( "role" )
6144
			.removeAttr( "aria-selected" )
6145
			.removeAttr( "aria-controls" )
6146
			.removeAttr( "tabIndex" )
6147
			.each(function() {
6148
				if ( /^ui-accordion/.test( this.id ) ) {
6149
					this.removeAttribute( "id" );
6150
				}
6151
			});
6152
		this._destroyIcons();
6153
6154
		// clean up content panels
6155
		contents = this.headers.next()
6156
			.css( "display", "" )
6157
			.removeAttr( "role" )
6158
			.removeAttr( "aria-expanded" )
6159
			.removeAttr( "aria-hidden" )
6160
			.removeAttr( "aria-labelledby" )
6161
			.removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-state-disabled" )
6162
			.each(function() {
6163
				if ( /^ui-accordion/.test( this.id ) ) {
6164
					this.removeAttribute( "id" );
6165
				}
6166
			});
6167
		if ( this.options.heightStyle !== "content" ) {
6168
			contents.css( "height", "" );
6169
		}
6170
	},
6171
6172
	_setOption: function( key, value ) {
6173
		if ( key === "active" ) {
6174
			// _activate() will handle invalid values and update this.options
6175
			this._activate( value );
6176
			return;
6177
		}
6178
6179
		if ( key === "event" ) {
6180
			if ( this.options.event ) {
6181
				this._off( this.headers, this.options.event );
6182
			}
6183
			this._setupEvents( value );
6184
		}
6185
6186
		this._super( key, value );
6187
6188
		// setting collapsible: false while collapsed; open first panel
6189
		if ( key === "collapsible" && !value && this.options.active === false ) {
6190
			this._activate( 0 );
6191
		}
6192
6193
		if ( key === "icons" ) {
6194
			this._destroyIcons();
6195
			if ( value ) {
6196
				this._createIcons();
6197
			}
6198
		}
6199
6200
		// #5332 - opacity doesn't cascade to positioned elements in IE
6201
		// so we need to add the disabled class to the headers and panels
6202
		if ( key === "disabled" ) {
6203
			this.headers.add( this.headers.next() )
6204
				.toggleClass( "ui-state-disabled", !!value );
6205
		}
6206
	},
6207
6208
	_keydown: function( event ) {
6209
		/*jshint maxcomplexity:15*/
6210
		if ( event.altKey || event.ctrlKey ) {
6211
			return;
6212
		}
6213
6214
		var keyCode = $.ui.keyCode,
6215
			length = this.headers.length,
6216
			currentIndex = this.headers.index( event.target ),
6217
			toFocus = false;
6218
6219
		switch ( event.keyCode ) {
6220
			case keyCode.RIGHT:
6221
			case keyCode.DOWN:
6222
				toFocus = this.headers[ ( currentIndex + 1 ) % length ];
6223
				break;
6224
			case keyCode.LEFT:
6225
			case keyCode.UP:
6226
				toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
6227
				break;
6228
			case keyCode.SPACE:
6229
			case keyCode.ENTER:
6230
				this._eventHandler( event );
6231
				break;
6232
			case keyCode.HOME:
6233
				toFocus = this.headers[ 0 ];
6234
				break;
6235
			case keyCode.END:
6236
				toFocus = this.headers[ length - 1 ];
6237
				break;
6238
		}
6239
6240
		if ( toFocus ) {
6241
			$( event.target ).attr( "tabIndex", -1 );
6242
			$( toFocus ).attr( "tabIndex", 0 );
6243
			toFocus.focus();
6244
			event.preventDefault();
6245
		}
6246
	},
6247
6248
	_panelKeyDown : function( event ) {
6249
		if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) {
6250
			$( event.currentTarget ).prev().focus();
6251
		}
6252
	},
6253
6254
	refresh: function() {
6255
		var options = this.options;
6256
		this._processPanels();
6257
6258
		// was collapsed or no panel
6259
		if ( ( options.active === false && options.collapsible === true ) || !this.headers.length ) {
6260
			options.active = false;
6261
			this.active = $();
6262
		// active false only when collapsible is true
6263
		} else if ( options.active === false ) {
6264
			this._activate( 0 );
6265
		// was active, but active panel is gone
6266
		} else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
6267
			// all remaining panel are disabled
6268
			if ( this.headers.length === this.headers.find(".ui-state-disabled").length ) {
6269
				options.active = false;
6270
				this.active = $();
6271
			// activate previous panel
6272
			} else {
6273
				this._activate( Math.max( 0, options.active - 1 ) );
6274
			}
6275
		// was active, active panel still exists
6276
		} else {
6277
			// make sure active index is correct
6278
			options.active = this.headers.index( this.active );
6279
		}
6280
6281
		this._destroyIcons();
6282
6283
		this._refresh();
6284
	},
6285
6286
	_processPanels: function() {
6287
		this.headers = this.element.find( this.options.header )
6288
			.addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" );
6289
6290
		this.headers.next()
6291
			.addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" )
6292
			.filter(":not(.ui-accordion-content-active)")
6293
			.hide();
6294
	},
6295
6296
	_refresh: function() {
6297
		var maxHeight,
6298
			options = this.options,
6299
			heightStyle = options.heightStyle,
6300
			parent = this.element.parent(),
6301
			accordionId = this.accordionId = "ui-accordion-" +
6302
				(this.element.attr( "id" ) || ++uid);
6303
6304
		this.active = this._findActive( options.active )
6305
			.addClass( "ui-accordion-header-active ui-state-active ui-corner-top" )
6306
			.removeClass( "ui-corner-all" );
6307
		this.active.next()
6308
			.addClass( "ui-accordion-content-active" )
6309
			.show();
6310
6311
		this.headers
6312
			.attr( "role", "tab" )
6313
			.each(function( i ) {
6314
				var header = $( this ),
6315
					headerId = header.attr( "id" ),
6316
					panel = header.next(),
6317
					panelId = panel.attr( "id" );
6318
				if ( !headerId ) {
6319
					headerId = accordionId + "-header-" + i;
6320
					header.attr( "id", headerId );
6321
				}
6322
				if ( !panelId ) {
6323
					panelId = accordionId + "-panel-" + i;
6324
					panel.attr( "id", panelId );
6325
				}
6326
				header.attr( "aria-controls", panelId );
6327
				panel.attr( "aria-labelledby", headerId );
6328
			})
6329
			.next()
6330
				.attr( "role", "tabpanel" );
6331
6332
		this.headers
6333
			.not( this.active )
6334
			.attr({
6335
				"aria-selected": "false",
6336
				tabIndex: -1
6337
			})
6338
			.next()
6339
				.attr({
6340
					"aria-expanded": "false",
6341
					"aria-hidden": "true"
6342
				})
6343
				.hide();
6344
6345
		// make sure at least one header is in the tab order
6346
		if ( !this.active.length ) {
6347
			this.headers.eq( 0 ).attr( "tabIndex", 0 );
6348
		} else {
6349
			this.active.attr({
6350
				"aria-selected": "true",
6351
				tabIndex: 0
6352
			})
6353
			.next()
6354
				.attr({
6355
					"aria-expanded": "true",
6356
					"aria-hidden": "false"
6357
				});
6358
		}
6359
6360
		this._createIcons();
6361
6362
		this._setupEvents( options.event );
6363
6364
		if ( heightStyle === "fill" ) {
6365
			maxHeight = parent.height();
6366
			this.element.siblings( ":visible" ).each(function() {
6367
				var elem = $( this ),
6368
					position = elem.css( "position" );
6369
6370
				if ( position === "absolute" || position === "fixed" ) {
6371
					return;
6372
				}
6373
				maxHeight -= elem.outerHeight( true );
6374
			});
6375
6376
			this.headers.each(function() {
6377
				maxHeight -= $( this ).outerHeight( true );
6378
			});
6379
6380
			this.headers.next()
6381
				.each(function() {
6382
					$( this ).height( Math.max( 0, maxHeight -
6383
						$( this ).innerHeight() + $( this ).height() ) );
6384
				})
6385
				.css( "overflow", "auto" );
6386
		} else if ( heightStyle === "auto" ) {
6387
			maxHeight = 0;
6388
			this.headers.next()
6389
				.each(function() {
6390
					maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() );
6391
				})
6392
				.height( maxHeight );
6393
		}
6394
	},
6395
6396
	_activate: function( index ) {
6397
		var active = this._findActive( index )[ 0 ];
6398
6399
		// trying to activate the already active panel
6400
		if ( active === this.active[ 0 ] ) {
6401
			return;
6402
		}
6403
6404
		// trying to collapse, simulate a click on the currently active header
6405
		active = active || this.active[ 0 ];
6406
6407
		this._eventHandler({
6408
			target: active,
6409
			currentTarget: active,
6410
			preventDefault: $.noop
6411
		});
6412
	},
6413
6414
	_findActive: function( selector ) {
6415
		return typeof selector === "number" ? this.headers.eq( selector ) : $();
6416
	},
6417
6418
	_setupEvents: function( event ) {
6419
		var events = {
6420
			keydown: "_keydown"
6421
		};
6422
		if ( event ) {
6423
			$.each( event.split(" "), function( index, eventName ) {
6424
				events[ eventName ] = "_eventHandler";
6425
			});
6426
		}
6427
6428
		this._off( this.headers.add( this.headers.next() ) );
6429
		this._on( this.headers, events );
6430
		this._on( this.headers.next(), { keydown: "_panelKeyDown" });
6431
		this._hoverable( this.headers );
6432
		this._focusable( this.headers );
6433
	},
6434
6435
	_eventHandler: function( event ) {
6436
		var options = this.options,
6437
			active = this.active,
6438
			clicked = $( event.currentTarget ),
6439
			clickedIsActive = clicked[ 0 ] === active[ 0 ],
6440
			collapsing = clickedIsActive && options.collapsible,
6441
			toShow = collapsing ? $() : clicked.next(),
6442
			toHide = active.next(),
6443
			eventData = {
6444
				oldHeader: active,
6445
				oldPanel: toHide,
6446
				newHeader: collapsing ? $() : clicked,
6447
				newPanel: toShow
6448
			};
6449
6450
		event.preventDefault();
6451
6452
		if (
6453
				// click on active header, but not collapsible
6454
				( clickedIsActive && !options.collapsible ) ||
6455
				// allow canceling activation
6456
				( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
6457
			return;
6458
		}
6459
6460
		options.active = collapsing ? false : this.headers.index( clicked );
6461
6462
		// when the call to ._toggle() comes after the class changes
6463
		// it causes a very odd bug in IE 8 (see #6720)
6464
		this.active = clickedIsActive ? $() : clicked;
6465
		this._toggle( eventData );
6466
6467
		// switch classes
6468
		// corner classes on the previously active header stay after the animation
6469
		active.removeClass( "ui-accordion-header-active ui-state-active" );
6470
		if ( options.icons ) {
6471
			active.children( ".ui-accordion-header-icon" )
6472
				.removeClass( options.icons.activeHeader )
6473
				.addClass( options.icons.header );
6474
		}
6475
6476
		if ( !clickedIsActive ) {
6477
			clicked
6478
				.removeClass( "ui-corner-all" )
6479
				.addClass( "ui-accordion-header-active ui-state-active ui-corner-top" );
6480
			if ( options.icons ) {
6481
				clicked.children( ".ui-accordion-header-icon" )
6482
					.removeClass( options.icons.header )
6483
					.addClass( options.icons.activeHeader );
6484
			}
6485
6486
			clicked
6487
				.next()
6488
				.addClass( "ui-accordion-content-active" );
6489
		}
6490
	},
6491
6492
	_toggle: function( data ) {
6493
		var toShow = data.newPanel,
6494
			toHide = this.prevShow.length ? this.prevShow : data.oldPanel;
6495
6496
		// handle activating a panel during the animation for another activation
6497
		this.prevShow.add( this.prevHide ).stop( true, true );
6498
		this.prevShow = toShow;
6499
		this.prevHide = toHide;
6500
6501
		if ( this.options.animate ) {
6502
			this._animate( toShow, toHide, data );
6503
		} else {
6504
			toHide.hide();
6505
			toShow.show();
6506
			this._toggleComplete( data );
6507
		}
6508
6509
		toHide.attr({
6510
			"aria-expanded": "false",
6511
			"aria-hidden": "true"
6512
		});
6513
		toHide.prev().attr( "aria-selected", "false" );
6514
		// if we're switching panels, remove the old header from the tab order
6515
		// if we're opening from collapsed state, remove the previous header from the tab order
6516
		// if we're collapsing, then keep the collapsing header in the tab order
6517
		if ( toShow.length && toHide.length ) {
6518
			toHide.prev().attr( "tabIndex", -1 );
6519
		} else if ( toShow.length ) {
6520
			this.headers.filter(function() {
6521
				return $( this ).attr( "tabIndex" ) === 0;
6522
			})
6523
			.attr( "tabIndex", -1 );
6524
		}
6525
6526
		toShow
6527
			.attr({
6528
				"aria-expanded": "true",
6529
				"aria-hidden": "false"
6530
			})
6531
			.prev()
6532
				.attr({
6533
					"aria-selected": "true",
6534
					tabIndex: 0
6535
				});
6536
	},
6537
6538
	_animate: function( toShow, toHide, data ) {
6539
		var total, easing, duration,
6540
			that = this,
6541
			adjust = 0,
6542
			down = toShow.length &&
6543
				( !toHide.length || ( toShow.index() < toHide.index() ) ),
6544
			animate = this.options.animate || {},
6545
			options = down && animate.down || animate,
6546
			complete = function() {
6547
				that._toggleComplete( data );
6548
			};
6549
6550
		if ( typeof options === "number" ) {
6551
			duration = options;
6552
		}
6553
		if ( typeof options === "string" ) {
6554
			easing = options;
6555
		}
6556
		// fall back from options to animation in case of partial down settings
6557
		easing = easing || options.easing || animate.easing;
6558
		duration = duration || options.duration || animate.duration;
6559
6560
		if ( !toHide.length ) {
6561
			return toShow.animate( showProps, duration, easing, complete );
6562
		}
6563
		if ( !toShow.length ) {
6564
			return toHide.animate( hideProps, duration, easing, complete );
6565
		}
6566
6567
		total = toShow.show().outerHeight();
6568
		toHide.animate( hideProps, {
6569
			duration: duration,
6570
			easing: easing,
6571
			step: function( now, fx ) {
6572
				fx.now = Math.round( now );
6573
			}
6574
		});
6575
		toShow
6576
			.hide()
6577
			.animate( showProps, {
6578
				duration: duration,
6579
				easing: easing,
6580
				complete: complete,
6581
				step: function( now, fx ) {
6582
					fx.now = Math.round( now );
6583
					if ( fx.prop !== "height" ) {
6584
						adjust += fx.now;
6585
					} else if ( that.options.heightStyle !== "content" ) {
6586
						fx.now = Math.round( total - toHide.outerHeight() - adjust );
6587
						adjust = 0;
6588
					}
6589
				}
6590
			});
6591
	},
6592
6593
	_toggleComplete: function( data ) {
6594
		var toHide = data.oldPanel;
6595
6596
		toHide
6597
			.removeClass( "ui-accordion-content-active" )
6598
			.prev()
6599
				.removeClass( "ui-corner-top" )
6600
				.addClass( "ui-corner-all" );
6601
6602
		// Work around for rendering bug in IE (#5421)
6603
		if ( toHide.length ) {
6604
			toHide.parent()[0].className = toHide.parent()[0].className;
6605
		}
6606
6607
		this._trigger( "activate", null, data );
6608
	}
6609
});
6610
6611
})( jQuery );
6612
6613
(function( $, undefined ) {
6614
6615
// used to prevent race conditions with remote data sources
6616
var requestIndex = 0;
6617
6618
$.widget( "ui.autocomplete", {
6619
	version: "1.10.3",
6620
	defaultElement: "<input>",
6621
	options: {
6622
		appendTo: null,
6623
		autoFocus: false,
6624
		delay: 300,
6625
		minLength: 1,
6626
		position: {
6627
			my: "left top",
6628
			at: "left bottom",
6629
			collision: "none"
6630
		},
6631
		source: null,
6632
6633
		// callbacks
6634
		change: null,
6635
		close: null,
6636
		focus: null,
6637
		open: null,
6638
		response: null,
6639
		search: null,
6640
		select: null
6641
	},
6642
6643
	pending: 0,
6644
6645
	_create: function() {
6646
		// Some browsers only repeat keydown events, not keypress events,
6647
		// so we use the suppressKeyPress flag to determine if we've already
6648
		// handled the keydown event. #7269
6649
		// Unfortunately the code for & in keypress is the same as the up arrow,
6650
		// so we use the suppressKeyPressRepeat flag to avoid handling keypress
6651
		// events when we know the keydown event was used to modify the
6652
		// search term. #7799
6653
		var suppressKeyPress, suppressKeyPressRepeat, suppressInput,
6654
			nodeName = this.element[0].nodeName.toLowerCase(),
6655
			isTextarea = nodeName === "textarea",
6656
			isInput = nodeName === "input";
6657
6658
		this.isMultiLine =
6659
			// Textareas are always multi-line
6660
			isTextarea ? true :
6661
			// Inputs are always single-line, even if inside a contentEditable element
6662
			// IE also treats inputs as contentEditable
6663
			isInput ? false :
6664
			// All other element types are determined by whether or not they're contentEditable
6665
			this.element.prop( "isContentEditable" );
6666
6667
		this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ];
6668
		this.isNewMenu = true;
6669
6670
		this.element
6671
			.addClass( "ui-autocomplete-input" )
6672
			.attr( "autocomplete", "off" );
6673
6674
		this._on( this.element, {
6675
			keydown: function( event ) {
6676
				/*jshint maxcomplexity:15*/
6677
				if ( this.element.prop( "readOnly" ) ) {
6678
					suppressKeyPress = true;
6679
					suppressInput = true;
6680
					suppressKeyPressRepeat = true;
6681
					return;
6682
				}
6683
6684
				suppressKeyPress = false;
6685
				suppressInput = false;
6686
				suppressKeyPressRepeat = false;
6687
				var keyCode = $.ui.keyCode;
6688
				switch( event.keyCode ) {
6689
				case keyCode.PAGE_UP:
6690
					suppressKeyPress = true;
6691
					this._move( "previousPage", event );
6692
					break;
6693
				case keyCode.PAGE_DOWN:
6694
					suppressKeyPress = true;
6695
					this._move( "nextPage", event );
6696
					break;
6697
				case keyCode.UP:
6698
					suppressKeyPress = true;
6699
					this._keyEvent( "previous", event );
6700
					break;
6701
				case keyCode.DOWN:
6702
					suppressKeyPress = true;
6703
					this._keyEvent( "next", event );
6704
					break;
6705
				case keyCode.ENTER:
6706
				case keyCode.NUMPAD_ENTER:
6707
					// when menu is open and has focus
6708
					if ( this.menu.active ) {
6709
						// #6055 - Opera still allows the keypress to occur
6710
						// which causes forms to submit
6711
						suppressKeyPress = true;
6712
						event.preventDefault();
6713
						this.menu.select( event );
6714
					}
6715
					break;
6716
				case keyCode.TAB:
6717
					if ( this.menu.active ) {
6718
						this.menu.select( event );
6719
					}
6720
					break;
6721
				case keyCode.ESCAPE:
6722
					if ( this.menu.element.is( ":visible" ) ) {
6723
						this._value( this.term );
6724
						this.close( event );
6725
						// Different browsers have different default behavior for escape
6726
						// Single press can mean undo or clear
6727
						// Double press in IE means clear the whole form
6728
						event.preventDefault();
6729
					}
6730
					break;
6731
				default:
6732
					suppressKeyPressRepeat = true;
6733
					// search timeout should be triggered before the input value is changed
6734
					this._searchTimeout( event );
6735
					break;
6736
				}
6737
			},
6738
			keypress: function( event ) {
6739
				if ( suppressKeyPress ) {
6740
					suppressKeyPress = false;
6741
					if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
6742
						event.preventDefault();
6743
					}
6744
					return;
6745
				}
6746
				if ( suppressKeyPressRepeat ) {
6747
					return;
6748
				}
6749
6750
				// replicate some key handlers to allow them to repeat in Firefox and Opera
6751
				var keyCode = $.ui.keyCode;
6752
				switch( event.keyCode ) {
6753
				case keyCode.PAGE_UP:
6754
					this._move( "previousPage", event );
6755
					break;
6756
				case keyCode.PAGE_DOWN:
6757
					this._move( "nextPage", event );
6758
					break;
6759
				case keyCode.UP:
6760
					this._keyEvent( "previous", event );
6761
					break;
6762
				case keyCode.DOWN:
6763
					this._keyEvent( "next", event );
6764
					break;
6765
				}
6766
			},
6767
			input: function( event ) {
6768
				if ( suppressInput ) {
6769
					suppressInput = false;
6770
					event.preventDefault();
6771
					return;
6772
				}
6773
				this._searchTimeout( event );
6774
			},
6775
			focus: function() {
6776
				this.selectedItem = null;
6777
				this.previous = this._value();
6778
			},
6779
			blur: function( event ) {
6780
				if ( this.cancelBlur ) {
6781
					delete this.cancelBlur;
6782
					return;
6783
				}
6784
6785
				clearTimeout( this.searching );
6786
				this.close( event );
6787
				this._change( event );
6788
			}
6789
		});
6790
6791
		this._initSource();
6792
		this.menu = $( "<ul>" )
6793
			.addClass( "ui-autocomplete ui-front" )
6794
			.appendTo( this._appendTo() )
6795
			.menu({
6796
				// disable ARIA support, the live region takes care of that
6797
				role: null
6798
			})
6799
			.hide()
6800
			.data( "ui-menu" );
6801
6802
		this._on( this.menu.element, {
6803
			mousedown: function( event ) {
6804
				// prevent moving focus out of the text field
6805
				event.preventDefault();
6806
6807
				// IE doesn't prevent moving focus even with event.preventDefault()
6808
				// so we set a flag to know when we should ignore the blur event
6809
				this.cancelBlur = true;
6810
				this._delay(function() {
6811
					delete this.cancelBlur;
6812
				});
6813
6814
				// clicking on the scrollbar causes focus to shift to the body
6815
				// but we can't detect a mouseup or a click immediately afterward
6816
				// so we have to track the next mousedown and close the menu if
6817
				// the user clicks somewhere outside of the autocomplete
6818
				var menuElement = this.menu.element[ 0 ];
6819
				if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
6820
					this._delay(function() {
6821
						var that = this;
6822
						this.document.one( "mousedown", function( event ) {
6823
							if ( event.target !== that.element[ 0 ] &&
6824
									event.target !== menuElement &&
6825
									!$.contains( menuElement, event.target ) ) {
6826
								that.close();
6827
							}
6828
						});
6829
					});
6830
				}
6831
			},
6832
			menufocus: function( event, ui ) {
6833
				// support: Firefox
6834
				// Prevent accidental activation of menu items in Firefox (#7024 #9118)
6835
				if ( this.isNewMenu ) {
6836
					this.isNewMenu = false;
6837
					if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) {
6838
						this.menu.blur();
6839
6840
						this.document.one( "mousemove", function() {
6841
							$( event.target ).trigger( event.originalEvent );
6842
						});
6843
6844
						return;
6845
					}
6846
				}
6847
6848
				var item = ui.item.data( "ui-autocomplete-item" );
6849
				if ( false !== this._trigger( "focus", event, { item: item } ) ) {
6850
					// use value to match what will end up in the input, if it was a key event
6851
					if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) {
6852
						this._value( item.value );
6853
					}
6854
				} else {
6855
					// Normally the input is populated with the item's value as the
6856
					// menu is navigated, causing screen readers to notice a change and
6857
					// announce the item. Since the focus event was canceled, this doesn't
6858
					// happen, so we update the live region so that screen readers can
6859
					// still notice the change and announce it.
6860
					this.liveRegion.text( item.value );
6861
				}
6862
			},
6863
			menuselect: function( event, ui ) {
6864
				var item = ui.item.data( "ui-autocomplete-item" ),
6865
					previous = this.previous;
6866
6867
				// only trigger when focus was lost (click on menu)
6868
				if ( this.element[0] !== this.document[0].activeElement ) {
6869
					this.element.focus();
6870
					this.previous = previous;
6871
					// #6109 - IE triggers two focus events and the second
6872
					// is asynchronous, so we need to reset the previous
6873
					// term synchronously and asynchronously :-(
6874
					this._delay(function() {
6875
						this.previous = previous;
6876
						this.selectedItem = item;
6877
					});
6878
				}
6879
6880
				if ( false !== this._trigger( "select", event, { item: item } ) ) {
6881
					this._value( item.value );
6882
				}
6883
				// reset the term after the select event
6884
				// this allows custom select handling to work properly
6885
				this.term = this._value();
6886
6887
				this.close( event );
6888
				this.selectedItem = item;
6889
			}
6890
		});
6891
6892
		this.liveRegion = $( "<span>", {
6893
				role: "status",
6894
				"aria-live": "polite"
6895
			})
6896
			.addClass( "ui-helper-hidden-accessible" )
6897
			.insertBefore( this.element );
6898
6899
		// turning off autocomplete prevents the browser from remembering the
6900
		// value when navigating through history, so we re-enable autocomplete
6901
		// if the page is unloaded before the widget is destroyed. #7790
6902
		this._on( this.window, {
6903
			beforeunload: function() {
6904
				this.element.removeAttr( "autocomplete" );
6905
			}
6906
		});
6907
	},
6908
6909
	_destroy: function() {
6910
		clearTimeout( this.searching );
6911
		this.element
6912
			.removeClass( "ui-autocomplete-input" )
6913
			.removeAttr( "autocomplete" );
6914
		this.menu.element.remove();
6915
		this.liveRegion.remove();
6916
	},
6917
6918
	_setOption: function( key, value ) {
6919
		this._super( key, value );
6920
		if ( key === "source" ) {
6921
			this._initSource();
6922
		}
6923
		if ( key === "appendTo" ) {
6924
			this.menu.element.appendTo( this._appendTo() );
6925
		}
6926
		if ( key === "disabled" && value && this.xhr ) {
6927
			this.xhr.abort();
6928
		}
6929
	},
6930
6931
	_appendTo: function() {
6932
		var element = this.options.appendTo;
6933
6934
		if ( element ) {
6935
			element = element.jquery || element.nodeType ?
6936
				$( element ) :
6937
				this.document.find( element ).eq( 0 );
6938
		}
6939
6940
		if ( !element ) {
6941
			element = this.element.closest( ".ui-front" );
6942
		}
6943
6944
		if ( !element.length ) {
6945
			element = this.document[0].body;
6946
		}
6947
6948
		return element;
6949
	},
6950
6951
	_initSource: function() {
6952
		var array, url,
6953
			that = this;
6954
		if ( $.isArray(this.options.source) ) {
6955
			array = this.options.source;
6956
			this.source = function( request, response ) {
6957
				response( $.ui.autocomplete.filter( array, request.term ) );
6958
			};
6959
		} else if ( typeof this.options.source === "string" ) {
6960
			url = this.options.source;
6961
			this.source = function( request, response ) {
6962
				if ( that.xhr ) {
6963
					that.xhr.abort();
6964
				}
6965
				that.xhr = $.ajax({
6966
					url: url,
6967
					data: request,
6968
					dataType: "json",
6969
					success: function( data ) {
6970
						response( data );
6971
					},
6972
					error: function() {
6973
						response( [] );
6974
					}
6975
				});
6976
			};
6977
		} else {
6978
			this.source = this.options.source;
6979
		}
6980
	},
6981
6982
	_searchTimeout: function( event ) {
6983
		clearTimeout( this.searching );
6984
		this.searching = this._delay(function() {
6985
			// only search if the value has changed
6986
			if ( this.term !== this._value() ) {
6987
				this.selectedItem = null;
6988
				this.search( null, event );
6989
			}
6990
		}, this.options.delay );
6991
	},
6992
6993
	search: function( value, event ) {
6994
		value = value != null ? value : this._value();
6995
6996
		// always save the actual value, not the one passed as an argument
6997
		this.term = this._value();
6998
6999
		if ( value.length < this.options.minLength ) {
7000
			return this.close( event );
7001
		}
7002
7003
		if ( this._trigger( "search", event ) === false ) {
7004
			return;
7005
		}
7006
7007
		return this._search( value );
7008
	},
7009
7010
	_search: function( value ) {
7011
		this.pending++;
7012
		this.element.addClass( "ui-autocomplete-loading" );
7013
		this.cancelSearch = false;
7014
7015
		this.source( { term: value }, this._response() );
7016
	},
7017
7018
	_response: function() {
7019
		var that = this,
7020
			index = ++requestIndex;
7021
7022
		return function( content ) {
7023
			if ( index === requestIndex ) {
7024
				that.__response( content );
7025
			}
7026
7027
			that.pending--;
7028
			if ( !that.pending ) {
7029
				that.element.removeClass( "ui-autocomplete-loading" );
7030
			}
7031
		};
7032
	},
7033
7034
	__response: function( content ) {
7035
		if ( content ) {
7036
			content = this._normalize( content );
7037
		}
7038
		this._trigger( "response", null, { content: content } );
7039
		if ( !this.options.disabled && content && content.length && !this.cancelSearch ) {
7040
			this._suggest( content );
7041
			this._trigger( "open" );
7042
		} else {
7043
			// use ._close() instead of .close() so we don't cancel future searches
7044
			this._close();
7045
		}
7046
	},
7047
7048
	close: function( event ) {
7049
		this.cancelSearch = true;
7050
		this._close( event );
7051
	},
7052
7053
	_close: function( event ) {
7054
		if ( this.menu.element.is( ":visible" ) ) {
7055
			this.menu.element.hide();
7056
			this.menu.blur();
7057
			this.isNewMenu = true;
7058
			this._trigger( "close", event );
7059
		}
7060
	},
7061
7062
	_change: function( event ) {
7063
		if ( this.previous !== this._value() ) {
7064
			this._trigger( "change", event, { item: this.selectedItem } );
7065
		}
7066
	},
7067
7068
	_normalize: function( items ) {
7069
		// assume all items have the right format when the first item is complete
7070
		if ( items.length && items[0].label && items[0].value ) {
7071
			return items;
7072
		}
7073
		return $.map( items, function( item ) {
7074
			if ( typeof item === "string" ) {
7075
				return {
7076
					label: item,
7077
					value: item
7078
				};
7079
			}
7080
			return $.extend({
7081
				label: item.label || item.value,
7082
				value: item.value || item.label
7083
			}, item );
7084
		});
7085
	},
7086
7087
	_suggest: function( items ) {
7088
		var ul = this.menu.element.empty();
7089
		this._renderMenu( ul, items );
7090
		this.isNewMenu = true;
7091
		this.menu.refresh();
7092
7093
		// size and position menu
7094
		ul.show();
7095
		this._resizeMenu();
7096
		ul.position( $.extend({
7097
			of: this.element
7098
		}, this.options.position ));
7099
7100
		if ( this.options.autoFocus ) {
7101
			this.menu.next();
7102
		}
7103
	},
7104
7105
	_resizeMenu: function() {
7106
		var ul = this.menu.element;
7107
		ul.outerWidth( Math.max(
7108
			// Firefox wraps long text (possibly a rounding bug)
7109
			// so we add 1px to avoid the wrapping (#7513)
7110
			ul.width( "" ).outerWidth() + 1,
7111
			this.element.outerWidth()
7112
		) );
7113
	},
7114
7115
	_renderMenu: function( ul, items ) {
7116
		var that = this;
7117
		$.each( items, function( index, item ) {
7118
			that._renderItemData( ul, item );
7119
		});
7120
	},
7121
7122
	_renderItemData: function( ul, item ) {
7123
		return this._renderItem( ul, item ).data( "ui-autocomplete-item", item );
7124
	},
7125
7126
	_renderItem: function( ul, item ) {
7127
		return $( "<li>" )
7128
			.append( $( "<a>" ).text( item.label ) )
7129
			.appendTo( ul );
7130
	},
7131
7132
	_move: function( direction, event ) {
7133
		if ( !this.menu.element.is( ":visible" ) ) {
7134
			this.search( null, event );
7135
			return;
7136
		}
7137
		if ( this.menu.isFirstItem() && /^previous/.test( direction ) ||
7138
				this.menu.isLastItem() && /^next/.test( direction ) ) {
7139
			this._value( this.term );
7140
			this.menu.blur();
7141
			return;
7142
		}
7143
		this.menu[ direction ]( event );
7144
	},
7145
7146
	widget: function() {
7147
		return this.menu.element;
7148
	},
7149
7150
	_value: function() {
7151
		return this.valueMethod.apply( this.element, arguments );
7152
	},
7153
7154
	_keyEvent: function( keyEvent, event ) {
7155
		if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
7156
			this._move( keyEvent, event );
7157
7158
			// prevents moving cursor to beginning/end of the text field in some browsers
7159
			event.preventDefault();
7160
		}
7161
	}
7162
});
7163
7164
$.extend( $.ui.autocomplete, {
7165
	escapeRegex: function( value ) {
7166
		return value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&");
7167
	},
7168
	filter: function(array, term) {
7169
		var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" );
7170
		return $.grep( array, function(value) {
7171
			return matcher.test( value.label || value.value || value );
7172
		});
7173
	}
7174
});
7175
7176
7177
// live region extension, adding a `messages` option
7178
// NOTE: This is an experimental API. We are still investigating
7179
// a full solution for string manipulation and internationalization.
7180
$.widget( "ui.autocomplete", $.ui.autocomplete, {
7181
	options: {
7182
		messages: {
7183
			noResults: "No search results.",
7184
			results: function( amount ) {
7185
				return amount + ( amount > 1 ? " results are" : " result is" ) +
7186
					" available, use up and down arrow keys to navigate.";
7187
			}
7188
		}
7189
	},
7190
7191
	__response: function( content ) {
7192
		var message;
7193
		this._superApply( arguments );
7194
		if ( this.options.disabled || this.cancelSearch ) {
7195
			return;
7196
		}
7197
		if ( content && content.length ) {
7198
			message = this.options.messages.results( content.length );
7199
		} else {
7200
			message = this.options.messages.noResults;
7201
		}
7202
		this.liveRegion.text( message );
7203
	}
7204
});
7205
7206
}( jQuery ));
7207
7208
(function( $, undefined ) {
7209
7210
var lastActive, startXPos, startYPos, clickDragged,
7211
	baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
7212
	stateClasses = "ui-state-hover ui-state-active ",
7213
	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",
7214
	formResetHandler = function() {
7215
		var form = $( this );
7216
		setTimeout(function() {
7217
			form.find( ":ui-button" ).button( "refresh" );
7218
		}, 1 );
7219
	},
7220
	radioGroup = function( radio ) {
7221
		var name = radio.name,
7222
			form = radio.form,
7223
			radios = $( [] );
7224
		if ( name ) {
7225
			name = name.replace( /'/g, "\\'" );
7226
			if ( form ) {
7227
				radios = $( form ).find( "[name='" + name + "']" );
7228
			} else {
7229
				radios = $( "[name='" + name + "']", radio.ownerDocument )
7230
					.filter(function() {
7231
						return !this.form;
7232
					});
7233
			}
7234
		}
7235
		return radios;
7236
	};
7237
7238
$.widget( "ui.button", {
7239
	version: "1.10.3",
7240
	defaultElement: "<button>",
7241
	options: {
7242
		disabled: null,
7243
		text: true,
7244
		label: null,
7245
		icons: {
7246
			primary: null,
7247
			secondary: null
7248
		}
7249
	},
7250
	_create: function() {
7251
		this.element.closest( "form" )
7252
			.unbind( "reset" + this.eventNamespace )
7253
			.bind( "reset" + this.eventNamespace, formResetHandler );
7254
7255
		if ( typeof this.options.disabled !== "boolean" ) {
7256
			this.options.disabled = !!this.element.prop( "disabled" );
7257
		} else {
7258
			this.element.prop( "disabled", this.options.disabled );
7259
		}
7260
7261
		this._determineButtonType();
7262
		this.hasTitle = !!this.buttonElement.attr( "title" );
7263
7264
		var that = this,
7265
			options = this.options,
7266
			toggleButton = this.type === "checkbox" || this.type === "radio",
7267
			activeClass = !toggleButton ? "ui-state-active" : "",
7268
			focusClass = "ui-state-focus";
7269
7270
		if ( options.label === null ) {
7271
			options.label = (this.type === "input" ? this.buttonElement.val() : this.buttonElement.html());
7272
		}
7273
7274
		this._hoverable( this.buttonElement );
7275
7276
		this.buttonElement
7277
			.addClass( baseClasses )
7278
			.attr( "role", "button" )
7279
			.bind( "mouseenter" + this.eventNamespace, function() {
7280
				if ( options.disabled ) {
7281
					return;
7282
				}
7283
				if ( this === lastActive ) {
7284
					$( this ).addClass( "ui-state-active" );
7285
				}
7286
			})
7287
			.bind( "mouseleave" + this.eventNamespace, function() {
7288
				if ( options.disabled ) {
7289
					return;
7290
				}
7291
				$( this ).removeClass( activeClass );
7292
			})
7293
			.bind( "click" + this.eventNamespace, function( event ) {
7294
				if ( options.disabled ) {
7295
					event.preventDefault();
7296
					event.stopImmediatePropagation();
7297
				}
7298
			});
7299
7300
		this.element
7301
			.bind( "focus" + this.eventNamespace, function() {
7302
				// no need to check disabled, focus won't be triggered anyway
7303
				that.buttonElement.addClass( focusClass );
7304
			})
7305
			.bind( "blur" + this.eventNamespace, function() {
7306
				that.buttonElement.removeClass( focusClass );
7307
			});
7308
7309
		if ( toggleButton ) {
7310
			this.element.bind( "change" + this.eventNamespace, function() {
7311
				if ( clickDragged ) {
7312
					return;
7313
				}
7314
				that.refresh();
7315
			});
7316
			// if mouse moves between mousedown and mouseup (drag) set clickDragged flag
7317
			// prevents issue where button state changes but checkbox/radio checked state
7318
			// does not in Firefox (see ticket #6970)
7319
			this.buttonElement
7320
				.bind( "mousedown" + this.eventNamespace, function( event ) {
7321
					if ( options.disabled ) {
7322
						return;
7323
					}
7324
					clickDragged = false;
7325
					startXPos = event.pageX;
7326
					startYPos = event.pageY;
7327
				})
7328
				.bind( "mouseup" + this.eventNamespace, function( event ) {
7329
					if ( options.disabled ) {
7330
						return;
7331
					}
7332
					if ( startXPos !== event.pageX || startYPos !== event.pageY ) {
7333
						clickDragged = true;
7334
					}
7335
			});
7336
		}
7337
7338
		if ( this.type === "checkbox" ) {
7339
			this.buttonElement.bind( "click" + this.eventNamespace, function() {
7340
				if ( options.disabled || clickDragged ) {
7341
					return false;
7342
				}
7343
			});
7344
		} else if ( this.type === "radio" ) {
7345
			this.buttonElement.bind( "click" + this.eventNamespace, function() {
7346
				if ( options.disabled || clickDragged ) {
7347
					return false;
7348
				}
7349
				$( this ).addClass( "ui-state-active" );
7350
				that.buttonElement.attr( "aria-pressed", "true" );
7351
7352
				var radio = that.element[ 0 ];
7353
				radioGroup( radio )
7354
					.not( radio )
7355
					.map(function() {
7356
						return $( this ).button( "widget" )[ 0 ];
7357
					})
7358
					.removeClass( "ui-state-active" )
7359
					.attr( "aria-pressed", "false" );
7360
			});
7361
		} else {
7362
			this.buttonElement
7363
				.bind( "mousedown" + this.eventNamespace, function() {
7364
					if ( options.disabled ) {
7365
						return false;
7366
					}
7367
					$( this ).addClass( "ui-state-active" );
7368
					lastActive = this;
7369
					that.document.one( "mouseup", function() {
7370
						lastActive = null;
7371
					});
7372
				})
7373
				.bind( "mouseup" + this.eventNamespace, function() {
7374
					if ( options.disabled ) {
7375
						return false;
7376
					}
7377
					$( this ).removeClass( "ui-state-active" );
7378
				})
7379
				.bind( "keydown" + this.eventNamespace, function(event) {
7380
					if ( options.disabled ) {
7381
						return false;
7382
					}
7383
					if ( event.keyCode === $.ui.keyCode.SPACE || event.keyCode === $.ui.keyCode.ENTER ) {
7384
						$( this ).addClass( "ui-state-active" );
7385
					}
7386
				})
7387
				// see #8559, we bind to blur here in case the button element loses
7388
				// focus between keydown and keyup, it would be left in an "active" state
7389
				.bind( "keyup" + this.eventNamespace + " blur" + this.eventNamespace, function() {
7390
					$( this ).removeClass( "ui-state-active" );
7391
				});
7392
7393
			if ( this.buttonElement.is("a") ) {
7394
				this.buttonElement.keyup(function(event) {
7395
					if ( event.keyCode === $.ui.keyCode.SPACE ) {
7396
						// TODO pass through original event correctly (just as 2nd argument doesn't work)
7397
						$( this ).click();
7398
					}
7399
				});
7400
			}
7401
		}
7402
7403
		// TODO: pull out $.Widget's handling for the disabled option into
7404
		// $.Widget.prototype._setOptionDisabled so it's easy to proxy and can
7405
		// be overridden by individual plugins
7406
		this._setOption( "disabled", options.disabled );
7407
		this._resetButton();
7408
	},
7409
7410
	_determineButtonType: function() {
7411
		var ancestor, labelSelector, checked;
7412
7413
		if ( this.element.is("[type=checkbox]") ) {
7414
			this.type = "checkbox";
7415
		} else if ( this.element.is("[type=radio]") ) {
7416
			this.type = "radio";
7417
		} else if ( this.element.is("input") ) {
7418
			this.type = "input";
7419
		} else {
7420
			this.type = "button";
7421
		}
7422
7423
		if ( this.type === "checkbox" || this.type === "radio" ) {
7424
			// we don't search against the document in case the element
7425
			// is disconnected from the DOM
7426
			ancestor = this.element.parents().last();
7427
			labelSelector = "label[for='" + this.element.attr("id") + "']";
7428
			this.buttonElement = ancestor.find( labelSelector );
7429
			if ( !this.buttonElement.length ) {
7430
				ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings();
7431
				this.buttonElement = ancestor.filter( labelSelector );
7432
				if ( !this.buttonElement.length ) {
7433
					this.buttonElement = ancestor.find( labelSelector );
7434
				}
7435
			}
7436
			this.element.addClass( "ui-helper-hidden-accessible" );
7437
7438
			checked = this.element.is( ":checked" );
7439
			if ( checked ) {
7440
				this.buttonElement.addClass( "ui-state-active" );
7441
			}
7442
			this.buttonElement.prop( "aria-pressed", checked );
7443
		} else {
7444
			this.buttonElement = this.element;
7445
		}
7446
	},
7447
7448
	widget: function() {
7449
		return this.buttonElement;
7450
	},
7451
7452
	_destroy: function() {
7453
		this.element
7454
			.removeClass( "ui-helper-hidden-accessible" );
7455
		this.buttonElement
7456
			.removeClass( baseClasses + " " + stateClasses + " " + typeClasses )
7457
			.removeAttr( "role" )
7458
			.removeAttr( "aria-pressed" )
7459
			.html( this.buttonElement.find(".ui-button-text").html() );
7460
7461
		if ( !this.hasTitle ) {
7462
			this.buttonElement.removeAttr( "title" );
7463
		}
7464
	},
7465
7466
	_setOption: function( key, value ) {
7467
		this._super( key, value );
7468
		if ( key === "disabled" ) {
7469
			if ( value ) {
7470
				this.element.prop( "disabled", true );
7471
			} else {
7472
				this.element.prop( "disabled", false );
7473
			}
7474
			return;
7475
		}
7476
		this._resetButton();
7477
	},
7478
7479
	refresh: function() {
7480
		//See #8237 & #8828
7481
		var isDisabled = this.element.is( "input, button" ) ? this.element.is( ":disabled" ) : this.element.hasClass( "ui-button-disabled" );
7482
7483
		if ( isDisabled !== this.options.disabled ) {
7484
			this._setOption( "disabled", isDisabled );
7485
		}
7486
		if ( this.type === "radio" ) {
7487
			radioGroup( this.element[0] ).each(function() {
7488
				if ( $( this ).is( ":checked" ) ) {
7489
					$( this ).button( "widget" )
7490
						.addClass( "ui-state-active" )
7491
						.attr( "aria-pressed", "true" );
7492
				} else {
7493
					$( this ).button( "widget" )
7494
						.removeClass( "ui-state-active" )
7495
						.attr( "aria-pressed", "false" );
7496
				}
7497
			});
7498
		} else if ( this.type === "checkbox" ) {
7499
			if ( this.element.is( ":checked" ) ) {
7500
				this.buttonElement
7501
					.addClass( "ui-state-active" )
7502
					.attr( "aria-pressed", "true" );
7503
			} else {
7504
				this.buttonElement
7505
					.removeClass( "ui-state-active" )
7506
					.attr( "aria-pressed", "false" );
7507
			}
7508
		}
7509
	},
7510
7511
	_resetButton: function() {
7512
		if ( this.type === "input" ) {
7513
			if ( this.options.label ) {
7514
				this.element.val( this.options.label );
7515
			}
7516
			return;
7517
		}
7518
		var buttonElement = this.buttonElement.removeClass( typeClasses ),
7519
			buttonText = $( "<span></span>", this.document[0] )
7520
				.addClass( "ui-button-text" )
7521
				.html( this.options.label )
7522
				.appendTo( buttonElement.empty() )
7523
				.text(),
7524
			icons = this.options.icons,
7525
			multipleIcons = icons.primary && icons.secondary,
7526
			buttonClasses = [];
7527
7528
		if ( icons.primary || icons.secondary ) {
7529
			if ( this.options.text ) {
7530
				buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
7531
			}
7532
7533
			if ( icons.primary ) {
7534
				buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
7535
			}
7536
7537
			if ( icons.secondary ) {
7538
				buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
7539
			}
7540
7541
			if ( !this.options.text ) {
7542
				buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" );
7543
7544
				if ( !this.hasTitle ) {
7545
					buttonElement.attr( "title", $.trim( buttonText ) );
7546
				}
7547
			}
7548
		} else {
7549
			buttonClasses.push( "ui-button-text-only" );
7550
		}
7551
		buttonElement.addClass( buttonClasses.join( " " ) );
7552
	}
7553
});
7554
7555
$.widget( "ui.buttonset", {
7556
	version: "1.10.3",
7557
	options: {
7558
		items: "button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(ui-button)"
7559
	},
7560
7561
	_create: function() {
7562
		this.element.addClass( "ui-buttonset" );
7563
	},
7564
7565
	_init: function() {
7566
		this.refresh();
7567
	},
7568
7569
	_setOption: function( key, value ) {
7570
		if ( key === "disabled" ) {
7571
			this.buttons.button( "option", key, value );
7572
		}
7573
7574
		this._super( key, value );
7575
	},
7576
7577
	refresh: function() {
7578
		var rtl = this.element.css( "direction" ) === "rtl";
7579
7580
		this.buttons = this.element.find( this.options.items )
7581
			.filter( ":ui-button" )
7582
				.button( "refresh" )
7583
			.end()
7584
			.not( ":ui-button" )
7585
				.button()
7586
			.end()
7587
			.map(function() {
7588
				return $( this ).button( "widget" )[ 0 ];
7589
			})
7590
				.removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
7591
				.filter( ":first" )
7592
					.addClass( rtl ? "ui-corner-right" : "ui-corner-left" )
7593
				.end()
7594
				.filter( ":last" )
7595
					.addClass( rtl ? "ui-corner-left" : "ui-corner-right" )
7596
				.end()
7597
			.end();
7598
	},
7599
7600
	_destroy: function() {
7601
		this.element.removeClass( "ui-buttonset" );
7602
		this.buttons
7603
			.map(function() {
7604
				return $( this ).button( "widget" )[ 0 ];
7605
			})
7606
				.removeClass( "ui-corner-left ui-corner-right" )
7607
			.end()
7608
			.button( "destroy" );
7609
	}
7610
});
7611
7612
}( jQuery ) );
7613
7614
(function( $, undefined ) {
7615
7616
$.extend($.ui, { datepicker: { version: "1.10.3" } });
7617
7618
var PROP_NAME = "datepicker",
7619
	instActive;
7620
7621
/* Date picker manager.
7622
   Use the singleton instance of this class, $.datepicker, to interact with the date picker.
7623
   Settings for (groups of) date pickers are maintained in an instance object,
7624
   allowing multiple different settings on the same page. */
7625
7626
function Datepicker() {
7627
	this._curInst = null; // The current instance in use
7628
	this._keyEvent = false; // If the last event was a key event
7629
	this._disabledInputs = []; // List of date picker inputs that have been disabled
7630
	this._datepickerShowing = false; // True if the popup picker is showing , false if not
7631
	this._inDialog = false; // True if showing within a "dialog", false if not
7632
	this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division
7633
	this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class
7634
	this._appendClass = "ui-datepicker-append"; // The name of the append marker class
7635
	this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class
7636
	this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class
7637
	this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class
7638
	this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class
7639
	this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class
7640
	this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class
7641
	this.regional = []; // Available regional settings, indexed by language code
7642
	this.regional[""] = { // Default regional settings
7643
		closeText: "Done", // Display text for close link
7644
		prevText: "Prev", // Display text for previous month link
7645
		nextText: "Next", // Display text for next month link
7646
		currentText: "Today", // Display text for current month link
7647
		monthNames: ["January","February","March","April","May","June",
7648
			"July","August","September","October","November","December"], // Names of months for drop-down and formatting
7649
		monthNamesShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], // For formatting
7650
		dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], // For formatting
7651
		dayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], // For formatting
7652
		dayNamesMin: ["Su","Mo","Tu","We","Th","Fr","Sa"], // Column headings for days starting at Sunday
7653
		weekHeader: "Wk", // Column header for week of the year
7654
		dateFormat: "mm/dd/yy", // See format options on parseDate
7655
		firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
7656
		isRTL: false, // True if right-to-left language, false if left-to-right
7657
		showMonthAfterYear: false, // True if the year select precedes month, false for month then year
7658
		yearSuffix: "" // Additional text to append to the year in the month headers
7659
	};
7660
	this._defaults = { // Global defaults for all the date picker instances
7661
		showOn: "focus", // "focus" for popup on focus,
7662
			// "button" for trigger button, or "both" for either
7663
		showAnim: "fadeIn", // Name of jQuery animation for popup
7664
		showOptions: {}, // Options for enhanced animations
7665
		defaultDate: null, // Used when field is blank: actual date,
7666
			// +/-number for offset from today, null for today
7667
		appendText: "", // Display text following the input box, e.g. showing the format
7668
		buttonText: "...", // Text for trigger button
7669
		buttonImage: "", // URL for trigger button image
7670
		buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
7671
		hideIfNoPrevNext: false, // True to hide next/previous month links
7672
			// if not applicable, false to just disable them
7673
		navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
7674
		gotoCurrent: false, // True if today link goes back to current selection instead
7675
		changeMonth: false, // True if month can be selected directly, false if only prev/next
7676
		changeYear: false, // True if year can be selected directly, false if only prev/next
7677
		yearRange: "c-10:c+10", // Range of years to display in drop-down,
7678
			// either relative to today's year (-nn:+nn), relative to currently displayed year
7679
			// (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
7680
		showOtherMonths: false, // True to show dates in other months, false to leave blank
7681
		selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
7682
		showWeek: false, // True to show week of the year, false to not show it
7683
		calculateWeek: this.iso8601Week, // How to calculate the week of the year,
7684
			// takes a Date and returns the number of the week for it
7685
		shortYearCutoff: "+10", // Short year values < this are in the current century,
7686
			// > this are in the previous century,
7687
			// string value starting with "+" for current year + value
7688
		minDate: null, // The earliest selectable date, or null for no limit
7689
		maxDate: null, // The latest selectable date, or null for no limit
7690
		duration: "fast", // Duration of display/closure
7691
		beforeShowDay: null, // Function that takes a date and returns an array with
7692
			// [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "",
7693
			// [2] = cell title (optional), e.g. $.datepicker.noWeekends
7694
		beforeShow: null, // Function that takes an input field and
7695
			// returns a set of custom settings for the date picker
7696
		onSelect: null, // Define a callback function when a date is selected
7697
		onChangeMonthYear: null, // Define a callback function when the month or year is changed
7698
		onClose: null, // Define a callback function when the datepicker is closed
7699
		numberOfMonths: 1, // Number of months to show at a time
7700
		showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
7701
		stepMonths: 1, // Number of months to step back/forward
7702
		stepBigMonths: 12, // Number of months to step back/forward for the big links
7703
		altField: "", // Selector for an alternate field to store selected dates into
7704
		altFormat: "", // The date format to use for the alternate field
7705
		constrainInput: true, // The input is constrained by the current date format
7706
		showButtonPanel: false, // True to show button panel, false to not show it
7707
		autoSize: false, // True to size the input for the date format, false to leave as is
7708
		disabled: false // The initial disabled state
7709
	};
7710
	$.extend(this._defaults, this.regional[""]);
7711
	this.dpDiv = bindHover($("<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>"));
7712
}
7713
7714
$.extend(Datepicker.prototype, {
7715
	/* Class name added to elements to indicate already configured with a date picker. */
7716
	markerClassName: "hasDatepicker",
7717
7718
	//Keep track of the maximum number of rows displayed (see #7043)
7719
	maxRows: 4,
7720
7721
	// TODO rename to "widget" when switching to widget factory
7722
	_widgetDatepicker: function() {
7723
		return this.dpDiv;
7724
	},
7725
7726
	/* Override the default settings for all instances of the date picker.
7727
	 * @param  settings  object - the new settings to use as defaults (anonymous object)
7728
	 * @return the manager object
7729
	 */
7730
	setDefaults: function(settings) {
7731
		extendRemove(this._defaults, settings || {});
7732
		return this;
7733
	},
7734
7735
	/* Attach the date picker to a jQuery selection.
7736
	 * @param  target	element - the target input field or division or span
7737
	 * @param  settings  object - the new settings to use for this date picker instance (anonymous)
7738
	 */
7739
	_attachDatepicker: function(target, settings) {
7740
		var nodeName, inline, inst;
7741
		nodeName = target.nodeName.toLowerCase();
7742
		inline = (nodeName === "div" || nodeName === "span");
7743
		if (!target.id) {
7744
			this.uuid += 1;
7745
			target.id = "dp" + this.uuid;
7746
		}
7747
		inst = this._newInst($(target), inline);
7748
		inst.settings = $.extend({}, settings || {});
7749
		if (nodeName === "input") {
7750
			this._connectDatepicker(target, inst);
7751
		} else if (inline) {
7752
			this._inlineDatepicker(target, inst);
7753
		}
7754
	},
7755
7756
	/* Create a new instance object. */
7757
	_newInst: function(target, inline) {
7758
		var id = target[0].id.replace(/([^A-Za-z0-9_\-])/g, "\\\\$1"); // escape jQuery meta chars
7759
		return {id: id, input: target, // associated target
7760
			selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
7761
			drawMonth: 0, drawYear: 0, // month being drawn
7762
			inline: inline, // is datepicker inline or not
7763
			dpDiv: (!inline ? this.dpDiv : // presentation div
7764
			bindHover($("<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")))};
7765
	},
7766
7767
	/* Attach the date picker to an input field. */
7768
	_connectDatepicker: function(target, inst) {
7769
		var input = $(target);
7770
		inst.append = $([]);
7771
		inst.trigger = $([]);
7772
		if (input.hasClass(this.markerClassName)) {
7773
			return;
7774
		}
7775
		this._attachments(input, inst);
7776
		input.addClass(this.markerClassName).keydown(this._doKeyDown).
7777
			keypress(this._doKeyPress).keyup(this._doKeyUp);
7778
		this._autoSize(inst);
7779
		$.data(target, PROP_NAME, inst);
7780
		//If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
7781
		if( inst.settings.disabled ) {
7782
			this._disableDatepicker( target );
7783
		}
7784
	},
7785
7786
	/* Make attachments based on settings. */
7787
	_attachments: function(input, inst) {
7788
		var showOn, buttonText, buttonImage,
7789
			appendText = this._get(inst, "appendText"),
7790
			isRTL = this._get(inst, "isRTL");
7791
7792
		if (inst.append) {
7793
			inst.append.remove();
7794
		}
7795
		if (appendText) {
7796
			inst.append = $("<span class='" + this._appendClass + "'>" + appendText + "</span>");
7797
			input[isRTL ? "before" : "after"](inst.append);
7798
		}
7799
7800
		input.unbind("focus", this._showDatepicker);
7801
7802
		if (inst.trigger) {
7803
			inst.trigger.remove();
7804
		}
7805
7806
		showOn = this._get(inst, "showOn");
7807
		if (showOn === "focus" || showOn === "both") { // pop-up date picker when in the marked field
7808
			input.focus(this._showDatepicker);
7809
		}
7810
		if (showOn === "button" || showOn === "both") { // pop-up date picker when button clicked
7811
			buttonText = this._get(inst, "buttonText");
7812
			buttonImage = this._get(inst, "buttonImage");
7813
			inst.trigger = $(this._get(inst, "buttonImageOnly") ?
7814
				$("<img/>").addClass(this._triggerClass).
7815
					attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
7816
				$("<button type='button'></button>").addClass(this._triggerClass).
7817
					html(!buttonImage ? buttonText : $("<img/>").attr(
7818
					{ src:buttonImage, alt:buttonText, title:buttonText })));
7819
			input[isRTL ? "before" : "after"](inst.trigger);
7820
			inst.trigger.click(function() {
7821
				if ($.datepicker._datepickerShowing && $.datepicker._lastInput === input[0]) {
7822
					$.datepicker._hideDatepicker();
7823
				} else if ($.datepicker._datepickerShowing && $.datepicker._lastInput !== input[0]) {
7824
					$.datepicker._hideDatepicker();
7825
					$.datepicker._showDatepicker(input[0]);
7826
				} else {
7827
					$.datepicker._showDatepicker(input[0]);
7828
				}
7829
				return false;
7830
			});
7831
		}
7832
	},
7833
7834
	/* Apply the maximum length for the date format. */
7835
	_autoSize: function(inst) {
7836
		if (this._get(inst, "autoSize") && !inst.inline) {
7837
			var findMax, max, maxI, i,
7838
				date = new Date(2009, 12 - 1, 20), // Ensure double digits
7839
				dateFormat = this._get(inst, "dateFormat");
7840
7841
			if (dateFormat.match(/[DM]/)) {
7842
				findMax = function(names) {
7843
					max = 0;
7844
					maxI = 0;
7845
					for (i = 0; i < names.length; i++) {
7846
						if (names[i].length > max) {
7847
							max = names[i].length;
7848
							maxI = i;
7849
						}
7850
					}
7851
					return maxI;
7852
				};
7853
				date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
7854
					"monthNames" : "monthNamesShort"))));
7855
				date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
7856
					"dayNames" : "dayNamesShort"))) + 20 - date.getDay());
7857
			}
7858
			inst.input.attr("size", this._formatDate(inst, date).length);
7859
		}
7860
	},
7861
7862
	/* Attach an inline date picker to a div. */
7863
	_inlineDatepicker: function(target, inst) {
7864
		var divSpan = $(target);
7865
		if (divSpan.hasClass(this.markerClassName)) {
7866
			return;
7867
		}
7868
		divSpan.addClass(this.markerClassName).append(inst.dpDiv);
7869
		$.data(target, PROP_NAME, inst);
7870
		this._setDate(inst, this._getDefaultDate(inst), true);
7871
		this._updateDatepicker(inst);
7872
		this._updateAlternate(inst);
7873
		//If disabled option is true, disable the datepicker before showing it (see ticket #5665)
7874
		if( inst.settings.disabled ) {
7875
			this._disableDatepicker( target );
7876
		}
7877
		// Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
7878
		// http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
7879
		inst.dpDiv.css( "display", "block" );
7880
	},
7881
7882
	/* Pop-up the date picker in a "dialog" box.
7883
	 * @param  input element - ignored
7884
	 * @param  date	string or Date - the initial date to display
7885
	 * @param  onSelect  function - the function to call when a date is selected
7886
	 * @param  settings  object - update the dialog date picker instance's settings (anonymous object)
7887
	 * @param  pos int[2] - coordinates for the dialog's position within the screen or
7888
	 *					event - with x/y coordinates or
7889
	 *					leave empty for default (screen centre)
7890
	 * @return the manager object
7891
	 */
7892
	_dialogDatepicker: function(input, date, onSelect, settings, pos) {
7893
		var id, browserWidth, browserHeight, scrollX, scrollY,
7894
			inst = this._dialogInst; // internal instance
7895
7896
		if (!inst) {
7897
			this.uuid += 1;
7898
			id = "dp" + this.uuid;
7899
			this._dialogInput = $("<input type='text' id='" + id +
7900
				"' style='position: absolute; top: -100px; width: 0px;'/>");
7901
			this._dialogInput.keydown(this._doKeyDown);
7902
			$("body").append(this._dialogInput);
7903
			inst = this._dialogInst = this._newInst(this._dialogInput, false);
7904
			inst.settings = {};
7905
			$.data(this._dialogInput[0], PROP_NAME, inst);
7906
		}
7907
		extendRemove(inst.settings, settings || {});
7908
		date = (date && date.constructor === Date ? this._formatDate(inst, date) : date);
7909
		this._dialogInput.val(date);
7910
7911
		this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
7912
		if (!this._pos) {
7913
			browserWidth = document.documentElement.clientWidth;
7914
			browserHeight = document.documentElement.clientHeight;
7915
			scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
7916
			scrollY = document.documentElement.scrollTop || document.body.scrollTop;
7917
			this._pos = // should use actual width/height below
7918
				[(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
7919
		}
7920
7921
		// move input on screen for focus, but hidden behind dialog
7922
		this._dialogInput.css("left", (this._pos[0] + 20) + "px").css("top", this._pos[1] + "px");
7923
		inst.settings.onSelect = onSelect;
7924
		this._inDialog = true;
7925
		this.dpDiv.addClass(this._dialogClass);
7926
		this._showDatepicker(this._dialogInput[0]);
7927
		if ($.blockUI) {
7928
			$.blockUI(this.dpDiv);
7929
		}
7930
		$.data(this._dialogInput[0], PROP_NAME, inst);
7931
		return this;
7932
	},
7933
7934
	/* Detach a datepicker from its control.
7935
	 * @param  target	element - the target input field or division or span
7936
	 */
7937
	_destroyDatepicker: function(target) {
7938
		var nodeName,
7939
			$target = $(target),
7940
			inst = $.data(target, PROP_NAME);
7941
7942
		if (!$target.hasClass(this.markerClassName)) {
7943
			return;
7944
		}
7945
7946
		nodeName = target.nodeName.toLowerCase();
7947
		$.removeData(target, PROP_NAME);
7948
		if (nodeName === "input") {
7949
			inst.append.remove();
7950
			inst.trigger.remove();
7951
			$target.removeClass(this.markerClassName).
7952
				unbind("focus", this._showDatepicker).
7953
				unbind("keydown", this._doKeyDown).
7954
				unbind("keypress", this._doKeyPress).
7955
				unbind("keyup", this._doKeyUp);
7956
		} else if (nodeName === "div" || nodeName === "span") {
7957
			$target.removeClass(this.markerClassName).empty();
7958
		}
7959
	},
7960
7961
	/* Enable the date picker to a jQuery selection.
7962
	 * @param  target	element - the target input field or division or span
7963
	 */
7964
	_enableDatepicker: function(target) {
7965
		var nodeName, inline,
7966
			$target = $(target),
7967
			inst = $.data(target, PROP_NAME);
7968
7969
		if (!$target.hasClass(this.markerClassName)) {
7970
			return;
7971
		}
7972
7973
		nodeName = target.nodeName.toLowerCase();
7974
		if (nodeName === "input") {
7975
			target.disabled = false;
7976
			inst.trigger.filter("button").
7977
				each(function() { this.disabled = false; }).end().
7978
				filter("img").css({opacity: "1.0", cursor: ""});
7979
		} else if (nodeName === "div" || nodeName === "span") {
7980
			inline = $target.children("." + this._inlineClass);
7981
			inline.children().removeClass("ui-state-disabled");
7982
			inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
7983
				prop("disabled", false);
7984
		}
7985
		this._disabledInputs = $.map(this._disabledInputs,
7986
			function(value) { return (value === target ? null : value); }); // delete entry
7987
	},
7988
7989
	/* Disable the date picker to a jQuery selection.
7990
	 * @param  target	element - the target input field or division or span
7991
	 */
7992
	_disableDatepicker: function(target) {
7993
		var nodeName, inline,
7994
			$target = $(target),
7995
			inst = $.data(target, PROP_NAME);
7996
7997
		if (!$target.hasClass(this.markerClassName)) {
7998
			return;
7999
		}
8000
8001
		nodeName = target.nodeName.toLowerCase();
8002
		if (nodeName === "input") {
8003
			target.disabled = true;
8004
			inst.trigger.filter("button").
8005
				each(function() { this.disabled = true; }).end().
8006
				filter("img").css({opacity: "0.5", cursor: "default"});
8007
		} else if (nodeName === "div" || nodeName === "span") {
8008
			inline = $target.children("." + this._inlineClass);
8009
			inline.children().addClass("ui-state-disabled");
8010
			inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
8011
				prop("disabled", true);
8012
		}
8013
		this._disabledInputs = $.map(this._disabledInputs,
8014
			function(value) { return (value === target ? null : value); }); // delete entry
8015
		this._disabledInputs[this._disabledInputs.length] = target;
8016
	},
8017
8018
	/* Is the first field in a jQuery collection disabled as a datepicker?
8019
	 * @param  target	element - the target input field or division or span
8020
	 * @return boolean - true if disabled, false if enabled
8021
	 */
8022
	_isDisabledDatepicker: function(target) {
8023
		if (!target) {
8024
			return false;
8025
		}
8026
		for (var i = 0; i < this._disabledInputs.length; i++) {
8027
			if (this._disabledInputs[i] === target) {
8028
				return true;
8029
			}
8030
		}
8031
		return false;
8032
	},
8033
8034
	/* Retrieve the instance data for the target control.
8035
	 * @param  target  element - the target input field or division or span
8036
	 * @return  object - the associated instance data
8037
	 * @throws  error if a jQuery problem getting data
8038
	 */
8039
	_getInst: function(target) {
8040
		try {
8041
			return $.data(target, PROP_NAME);
8042
		}
8043
		catch (err) {
8044
			throw "Missing instance data for this datepicker";
8045
		}
8046
	},
8047
8048
	/* Update or retrieve the settings for a date picker attached to an input field or division.
8049
	 * @param  target  element - the target input field or division or span
8050
	 * @param  name	object - the new settings to update or
8051
	 *				string - the name of the setting to change or retrieve,
8052
	 *				when retrieving also "all" for all instance settings or
8053
	 *				"defaults" for all global defaults
8054
	 * @param  value   any - the new value for the setting
8055
	 *				(omit if above is an object or to retrieve a value)
8056
	 */
8057
	_optionDatepicker: function(target, name, value) {
8058
		var settings, date, minDate, maxDate,
8059
			inst = this._getInst(target);
8060
8061
		if (arguments.length === 2 && typeof name === "string") {
8062
			return (name === "defaults" ? $.extend({}, $.datepicker._defaults) :
8063
				(inst ? (name === "all" ? $.extend({}, inst.settings) :
8064
				this._get(inst, name)) : null));
8065
		}
8066
8067
		settings = name || {};
8068
		if (typeof name === "string") {
8069
			settings = {};
8070
			settings[name] = value;
8071
		}
8072
8073
		if (inst) {
8074
			if (this._curInst === inst) {
8075
				this._hideDatepicker();
8076
			}
8077
8078
			date = this._getDateDatepicker(target, true);
8079
			minDate = this._getMinMaxDate(inst, "min");
8080
			maxDate = this._getMinMaxDate(inst, "max");
8081
			extendRemove(inst.settings, settings);
8082
			// reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
8083
			if (minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined) {
8084
				inst.settings.minDate = this._formatDate(inst, minDate);
8085
			}
8086
			if (maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined) {
8087
				inst.settings.maxDate = this._formatDate(inst, maxDate);
8088
			}
8089
			if ( "disabled" in settings ) {
8090
				if ( settings.disabled ) {
8091
					this._disableDatepicker(target);
8092
				} else {
8093
					this._enableDatepicker(target);
8094
				}
8095
			}
8096
			this._attachments($(target), inst);
8097
			this._autoSize(inst);
8098
			this._setDate(inst, date);
8099
			this._updateAlternate(inst);
8100
			this._updateDatepicker(inst);
8101
		}
8102
	},
8103
8104
	// change method deprecated
8105
	_changeDatepicker: function(target, name, value) {
8106
		this._optionDatepicker(target, name, value);
8107
	},
8108
8109
	/* Redraw the date picker attached to an input field or division.
8110
	 * @param  target  element - the target input field or division or span
8111
	 */
8112
	_refreshDatepicker: function(target) {
8113
		var inst = this._getInst(target);
8114
		if (inst) {
8115
			this._updateDatepicker(inst);
8116
		}
8117
	},
8118
8119
	/* Set the dates for a jQuery selection.
8120
	 * @param  target element - the target input field or division or span
8121
	 * @param  date	Date - the new date
8122
	 */
8123
	_setDateDatepicker: function(target, date) {
8124
		var inst = this._getInst(target);
8125
		if (inst) {
8126
			this._setDate(inst, date);
8127
			this._updateDatepicker(inst);
8128
			this._updateAlternate(inst);
8129
		}
8130
	},
8131
8132
	/* Get the date(s) for the first entry in a jQuery selection.
8133
	 * @param  target element - the target input field or division or span
8134
	 * @param  noDefault boolean - true if no default date is to be used
8135
	 * @return Date - the current date
8136
	 */
8137
	_getDateDatepicker: function(target, noDefault) {
8138
		var inst = this._getInst(target);
8139
		if (inst && !inst.inline) {
8140
			this._setDateFromField(inst, noDefault);
8141
		}
8142
		return (inst ? this._getDate(inst) : null);
8143
	},
8144
8145
	/* Handle keystrokes. */
8146
	_doKeyDown: function(event) {
8147
		var onSelect, dateStr, sel,
8148
			inst = $.datepicker._getInst(event.target),
8149
			handled = true,
8150
			isRTL = inst.dpDiv.is(".ui-datepicker-rtl");
8151
8152
		inst._keyEvent = true;
8153
		if ($.datepicker._datepickerShowing) {
8154
			switch (event.keyCode) {
8155
				case 9: $.datepicker._hideDatepicker();
8156
						handled = false;
8157
						break; // hide on tab out
8158
				case 13: sel = $("td." + $.datepicker._dayOverClass + ":not(." +
8159
									$.datepicker._currentClass + ")", inst.dpDiv);
8160
						if (sel[0]) {
8161
							$.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
8162
						}
8163
8164
						onSelect = $.datepicker._get(inst, "onSelect");
8165
						if (onSelect) {
8166
							dateStr = $.datepicker._formatDate(inst);
8167
8168
							// trigger custom callback
8169
							onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);
8170
						} else {
8171
							$.datepicker._hideDatepicker();
8172
						}
8173
8174
						return false; // don't submit the form
8175
				case 27: $.datepicker._hideDatepicker();
8176
						break; // hide on escape
8177
				case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
8178
							-$.datepicker._get(inst, "stepBigMonths") :
8179
							-$.datepicker._get(inst, "stepMonths")), "M");
8180
						break; // previous month/year on page up/+ ctrl
8181
				case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
8182
							+$.datepicker._get(inst, "stepBigMonths") :
8183
							+$.datepicker._get(inst, "stepMonths")), "M");
8184
						break; // next month/year on page down/+ ctrl
8185
				case 35: if (event.ctrlKey || event.metaKey) {
8186
							$.datepicker._clearDate(event.target);
8187
						}
8188
						handled = event.ctrlKey || event.metaKey;
8189
						break; // clear on ctrl or command +end
8190
				case 36: if (event.ctrlKey || event.metaKey) {
8191
							$.datepicker._gotoToday(event.target);
8192
						}
8193
						handled = event.ctrlKey || event.metaKey;
8194
						break; // current on ctrl or command +home
8195
				case 37: if (event.ctrlKey || event.metaKey) {
8196
							$.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), "D");
8197
						}
8198
						handled = event.ctrlKey || event.metaKey;
8199
						// -1 day on ctrl or command +left
8200
						if (event.originalEvent.altKey) {
8201
							$.datepicker._adjustDate(event.target, (event.ctrlKey ?
8202
								-$.datepicker._get(inst, "stepBigMonths") :
8203
								-$.datepicker._get(inst, "stepMonths")), "M");
8204
						}
8205
						// next month/year on alt +left on Mac
8206
						break;
8207
				case 38: if (event.ctrlKey || event.metaKey) {
8208
							$.datepicker._adjustDate(event.target, -7, "D");
8209
						}
8210
						handled = event.ctrlKey || event.metaKey;
8211
						break; // -1 week on ctrl or command +up
8212
				case 39: if (event.ctrlKey || event.metaKey) {
8213
							$.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), "D");
8214
						}
8215
						handled = event.ctrlKey || event.metaKey;
8216
						// +1 day on ctrl or command +right
8217
						if (event.originalEvent.altKey) {
8218
							$.datepicker._adjustDate(event.target, (event.ctrlKey ?
8219
								+$.datepicker._get(inst, "stepBigMonths") :
8220
								+$.datepicker._get(inst, "stepMonths")), "M");
8221
						}
8222
						// next month/year on alt +right
8223
						break;
8224
				case 40: if (event.ctrlKey || event.metaKey) {
8225
							$.datepicker._adjustDate(event.target, +7, "D");
8226
						}
8227
						handled = event.ctrlKey || event.metaKey;
8228
						break; // +1 week on ctrl or command +down
8229
				default: handled = false;
8230
			}
8231
		} else if (event.keyCode === 36 && event.ctrlKey) { // display the date picker on ctrl+home
8232
			$.datepicker._showDatepicker(this);
8233
		} else {
8234
			handled = false;
8235
		}
8236
8237
		if (handled) {
8238
			event.preventDefault();
8239
			event.stopPropagation();
8240
		}
8241
	},
8242
8243
	/* Filter entered characters - based on date format. */
8244
	_doKeyPress: function(event) {
8245
		var chars, chr,
8246
			inst = $.datepicker._getInst(event.target);
8247
8248
		if ($.datepicker._get(inst, "constrainInput")) {
8249
			chars = $.datepicker._possibleChars($.datepicker._get(inst, "dateFormat"));
8250
			chr = String.fromCharCode(event.charCode == null ? event.keyCode : event.charCode);
8251
			return event.ctrlKey || event.metaKey || (chr < " " || !chars || chars.indexOf(chr) > -1);
8252
		}
8253
	},
8254
8255
	/* Synchronise manual entry and field/alternate field. */
8256
	_doKeyUp: function(event) {
8257
		var date,
8258
			inst = $.datepicker._getInst(event.target);
8259
8260
		if (inst.input.val() !== inst.lastVal) {
8261
			try {
8262
				date = $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"),
8263
					(inst.input ? inst.input.val() : null),
8264
					$.datepicker._getFormatConfig(inst));
8265
8266
				if (date) { // only if valid
8267
					$.datepicker._setDateFromField(inst);
8268
					$.datepicker._updateAlternate(inst);
8269
					$.datepicker._updateDatepicker(inst);
8270
				}
8271
			}
8272
			catch (err) {
8273
			}
8274
		}
8275
		return true;
8276
	},
8277
8278
	/* Pop-up the date picker for a given input field.
8279
	 * If false returned from beforeShow event handler do not show.
8280
	 * @param  input  element - the input field attached to the date picker or
8281
	 *					event - if triggered by focus
8282
	 */
8283
	_showDatepicker: function(input) {
8284
		input = input.target || input;
8285
		if (input.nodeName.toLowerCase() !== "input") { // find from button/image trigger
8286
			input = $("input", input.parentNode)[0];
8287
		}
8288
8289
		if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput === input) { // already here
8290
			return;
8291
		}
8292
8293
		var inst, beforeShow, beforeShowSettings, isFixed,
8294
			offset, showAnim, duration;
8295
8296
		inst = $.datepicker._getInst(input);
8297
		if ($.datepicker._curInst && $.datepicker._curInst !== inst) {
8298
			$.datepicker._curInst.dpDiv.stop(true, true);
8299
			if ( inst && $.datepicker._datepickerShowing ) {
8300
				$.datepicker._hideDatepicker( $.datepicker._curInst.input[0] );
8301
			}
8302
		}
8303
8304
		beforeShow = $.datepicker._get(inst, "beforeShow");
8305
		beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {};
8306
		if(beforeShowSettings === false){
8307
			return;
8308
		}
8309
		extendRemove(inst.settings, beforeShowSettings);
8310
8311
		inst.lastVal = null;
8312
		$.datepicker._lastInput = input;
8313
		$.datepicker._setDateFromField(inst);
8314
8315
		if ($.datepicker._inDialog) { // hide cursor
8316
			input.value = "";
8317
		}
8318
		if (!$.datepicker._pos) { // position below input
8319
			$.datepicker._pos = $.datepicker._findPos(input);
8320
			$.datepicker._pos[1] += input.offsetHeight; // add the height
8321
		}
8322
8323
		isFixed = false;
8324
		$(input).parents().each(function() {
8325
			isFixed |= $(this).css("position") === "fixed";
8326
			return !isFixed;
8327
		});
8328
8329
		offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
8330
		$.datepicker._pos = null;
8331
		//to avoid flashes on Firefox
8332
		inst.dpDiv.empty();
8333
		// determine sizing offscreen
8334
		inst.dpDiv.css({position: "absolute", display: "block", top: "-1000px"});
8335
		$.datepicker._updateDatepicker(inst);
8336
		// fix width for dynamic number of date pickers
8337
		// and adjust position before showing
8338
		offset = $.datepicker._checkOffset(inst, offset, isFixed);
8339
		inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
8340
			"static" : (isFixed ? "fixed" : "absolute")), display: "none",
8341
			left: offset.left + "px", top: offset.top + "px"});
8342
8343
		if (!inst.inline) {
8344
			showAnim = $.datepicker._get(inst, "showAnim");
8345
			duration = $.datepicker._get(inst, "duration");
8346
			inst.dpDiv.zIndex($(input).zIndex()+1);
8347
			$.datepicker._datepickerShowing = true;
8348
8349
			if ( $.effects && $.effects.effect[ showAnim ] ) {
8350
				inst.dpDiv.show(showAnim, $.datepicker._get(inst, "showOptions"), duration);
8351
			} else {
8352
				inst.dpDiv[showAnim || "show"](showAnim ? duration : null);
8353
			}
8354
8355
			if ( $.datepicker._shouldFocusInput( inst ) ) {
8356
				inst.input.focus();
8357
			}
8358
8359
			$.datepicker._curInst = inst;
8360
		}
8361
	},
8362
8363
	/* Generate the date picker content. */
8364
	_updateDatepicker: function(inst) {
8365
		this.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
8366
		instActive = inst; // for delegate hover events
8367
		inst.dpDiv.empty().append(this._generateHTML(inst));
8368
		this._attachHandlers(inst);
8369
		inst.dpDiv.find("." + this._dayOverClass + " a").mouseover();
8370
8371
		var origyearshtml,
8372
			numMonths = this._getNumberOfMonths(inst),
8373
			cols = numMonths[1],
8374
			width = 17;
8375
8376
		inst.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width("");
8377
		if (cols > 1) {
8378
			inst.dpDiv.addClass("ui-datepicker-multi-" + cols).css("width", (width * cols) + "em");
8379
		}
8380
		inst.dpDiv[(numMonths[0] !== 1 || numMonths[1] !== 1 ? "add" : "remove") +
8381
			"Class"]("ui-datepicker-multi");
8382
		inst.dpDiv[(this._get(inst, "isRTL") ? "add" : "remove") +
8383
			"Class"]("ui-datepicker-rtl");
8384
8385
		if (inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) {
8386
			inst.input.focus();
8387
		}
8388
8389
		// deffered render of the years select (to avoid flashes on Firefox)
8390
		if( inst.yearshtml ){
8391
			origyearshtml = inst.yearshtml;
8392
			setTimeout(function(){
8393
				//assure that inst.yearshtml didn't change.
8394
				if( origyearshtml === inst.yearshtml && inst.yearshtml ){
8395
					inst.dpDiv.find("select.ui-datepicker-year:first").replaceWith(inst.yearshtml);
8396
				}
8397
				origyearshtml = inst.yearshtml = null;
8398
			}, 0);
8399
		}
8400
	},
8401
8402
	// #6694 - don't focus the input if it's already focused
8403
	// this breaks the change event in IE
8404
	// Support: IE and jQuery <1.9
8405
	_shouldFocusInput: function( inst ) {
8406
		return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" ) && !inst.input.is( ":focus" );
8407
	},
8408
8409
	/* Check positioning to remain on screen. */
8410
	_checkOffset: function(inst, offset, isFixed) {
8411
		var dpWidth = inst.dpDiv.outerWidth(),
8412
			dpHeight = inst.dpDiv.outerHeight(),
8413
			inputWidth = inst.input ? inst.input.outerWidth() : 0,
8414
			inputHeight = inst.input ? inst.input.outerHeight() : 0,
8415
			viewWidth = document.documentElement.clientWidth + (isFixed ? 0 : $(document).scrollLeft()),
8416
			viewHeight = document.documentElement.clientHeight + (isFixed ? 0 : $(document).scrollTop());
8417
8418
		offset.left -= (this._get(inst, "isRTL") ? (dpWidth - inputWidth) : 0);
8419
		offset.left -= (isFixed && offset.left === inst.input.offset().left) ? $(document).scrollLeft() : 0;
8420
		offset.top -= (isFixed && offset.top === (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
8421
8422
		// now check if datepicker is showing outside window viewport - move to a better place if so.
8423
		offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
8424
			Math.abs(offset.left + dpWidth - viewWidth) : 0);
8425
		offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
8426
			Math.abs(dpHeight + inputHeight) : 0);
8427
8428
		return offset;
8429
	},
8430
8431
	/* Find an object's position on the screen. */
8432
	_findPos: function(obj) {
8433
		var position,
8434
			inst = this._getInst(obj),
8435
			isRTL = this._get(inst, "isRTL");
8436
8437
		while (obj && (obj.type === "hidden" || obj.nodeType !== 1 || $.expr.filters.hidden(obj))) {
8438
			obj = obj[isRTL ? "previousSibling" : "nextSibling"];
8439
		}
8440
8441
		position = $(obj).offset();
8442
		return [position.left, position.top];
8443
	},
8444
8445
	/* Hide the date picker from view.
8446
	 * @param  input  element - the input field attached to the date picker
8447
	 */
8448
	_hideDatepicker: function(input) {
8449
		var showAnim, duration, postProcess, onClose,
8450
			inst = this._curInst;
8451
8452
		if (!inst || (input && inst !== $.data(input, PROP_NAME))) {
8453
			return;
8454
		}
8455
8456
		if (this._datepickerShowing) {
8457
			showAnim = this._get(inst, "showAnim");
8458
			duration = this._get(inst, "duration");
8459
			postProcess = function() {
8460
				$.datepicker._tidyDialog(inst);
8461
			};
8462
8463
			// DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed
8464
			if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) {
8465
				inst.dpDiv.hide(showAnim, $.datepicker._get(inst, "showOptions"), duration, postProcess);
8466
			} else {
8467
				inst.dpDiv[(showAnim === "slideDown" ? "slideUp" :
8468
					(showAnim === "fadeIn" ? "fadeOut" : "hide"))]((showAnim ? duration : null), postProcess);
8469
			}
8470
8471
			if (!showAnim) {
8472
				postProcess();
8473
			}
8474
			this._datepickerShowing = false;
8475
8476
			onClose = this._get(inst, "onClose");
8477
			if (onClose) {
8478
				onClose.apply((inst.input ? inst.input[0] : null), [(inst.input ? inst.input.val() : ""), inst]);
8479
			}
8480
8481
			this._lastInput = null;
8482
			if (this._inDialog) {
8483
				this._dialogInput.css({ position: "absolute", left: "0", top: "-100px" });
8484
				if ($.blockUI) {
8485
					$.unblockUI();
8486
					$("body").append(this.dpDiv);
8487
				}
8488
			}
8489
			this._inDialog = false;
8490
		}
8491
	},
8492
8493
	/* Tidy up after a dialog display. */
8494
	_tidyDialog: function(inst) {
8495
		inst.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar");
8496
	},
8497
8498
	/* Close date picker if clicked elsewhere. */
8499
	_checkExternalClick: function(event) {
8500
		if (!$.datepicker._curInst) {
8501
			return;
8502
		}
8503
8504
		var $target = $(event.target),
8505
			inst = $.datepicker._getInst($target[0]);
8506
8507
		if ( ( ( $target[0].id !== $.datepicker._mainDivId &&
8508
				$target.parents("#" + $.datepicker._mainDivId).length === 0 &&
8509
				!$target.hasClass($.datepicker.markerClassName) &&
8510
				!$target.closest("." + $.datepicker._triggerClass).length &&
8511
				$.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI) ) ) ||
8512
			( $target.hasClass($.datepicker.markerClassName) && $.datepicker._curInst !== inst ) ) {
8513
				$.datepicker._hideDatepicker();
8514
		}
8515
	},
8516
8517
	/* Adjust one of the date sub-fields. */
8518
	_adjustDate: function(id, offset, period) {
8519
		var target = $(id),
8520
			inst = this._getInst(target[0]);
8521
8522
		if (this._isDisabledDatepicker(target[0])) {
8523
			return;
8524
		}
8525
		this._adjustInstDate(inst, offset +
8526
			(period === "M" ? this._get(inst, "showCurrentAtPos") : 0), // undo positioning
8527
			period);
8528
		this._updateDatepicker(inst);
8529
	},
8530
8531
	/* Action for current link. */
8532
	_gotoToday: function(id) {
8533
		var date,
8534
			target = $(id),
8535
			inst = this._getInst(target[0]);
8536
8537
		if (this._get(inst, "gotoCurrent") && inst.currentDay) {
8538
			inst.selectedDay = inst.currentDay;
8539
			inst.drawMonth = inst.selectedMonth = inst.currentMonth;
8540
			inst.drawYear = inst.selectedYear = inst.currentYear;
8541
		} else {
8542
			date = new Date();
8543
			inst.selectedDay = date.getDate();
8544
			inst.drawMonth = inst.selectedMonth = date.getMonth();
8545
			inst.drawYear = inst.selectedYear = date.getFullYear();
8546
		}
8547
		this._notifyChange(inst);
8548
		this._adjustDate(target);
8549
	},
8550
8551
	/* Action for selecting a new month/year. */
8552
	_selectMonthYear: function(id, select, period) {
8553
		var target = $(id),
8554
			inst = this._getInst(target[0]);
8555
8556
		inst["selected" + (period === "M" ? "Month" : "Year")] =
8557
		inst["draw" + (period === "M" ? "Month" : "Year")] =
8558
			parseInt(select.options[select.selectedIndex].value,10);
8559
8560
		this._notifyChange(inst);
8561
		this._adjustDate(target);
8562
	},
8563
8564
	/* Action for selecting a day. */
8565
	_selectDay: function(id, month, year, td) {
8566
		var inst,
8567
			target = $(id);
8568
8569
		if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
8570
			return;
8571
		}
8572
8573
		inst = this._getInst(target[0]);
8574
		inst.selectedDay = inst.currentDay = $("a", td).html();
8575
		inst.selectedMonth = inst.currentMonth = month;
8576
		inst.selectedYear = inst.currentYear = year;
8577
		this._selectDate(id, this._formatDate(inst,
8578
			inst.currentDay, inst.currentMonth, inst.currentYear));
8579
	},
8580
8581
	/* Erase the input field and hide the date picker. */
8582
	_clearDate: function(id) {
8583
		var target = $(id);
8584
		this._selectDate(target, "");
8585
	},
8586
8587
	/* Update the input field with the selected date. */
8588
	_selectDate: function(id, dateStr) {
8589
		var onSelect,
8590
			target = $(id),
8591
			inst = this._getInst(target[0]);
8592
8593
		dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
8594
		if (inst.input) {
8595
			inst.input.val(dateStr);
8596
		}
8597
		this._updateAlternate(inst);
8598
8599
		onSelect = this._get(inst, "onSelect");
8600
		if (onSelect) {
8601
			onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);  // trigger custom callback
8602
		} else if (inst.input) {
8603
			inst.input.trigger("change"); // fire the change event
8604
		}
8605
8606
		if (inst.inline){
8607
			this._updateDatepicker(inst);
8608
		} else {
8609
			this._hideDatepicker();
8610
			this._lastInput = inst.input[0];
8611
			if (typeof(inst.input[0]) !== "object") {
8612
				inst.input.focus(); // restore focus
8613
			}
8614
			this._lastInput = null;
8615
		}
8616
	},
8617
8618
	/* Update any alternate field to synchronise with the main field. */
8619
	_updateAlternate: function(inst) {
8620
		var altFormat, date, dateStr,
8621
			altField = this._get(inst, "altField");
8622
8623
		if (altField) { // update alternate field too
8624
			altFormat = this._get(inst, "altFormat") || this._get(inst, "dateFormat");
8625
			date = this._getDate(inst);
8626
			dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
8627
			$(altField).each(function() { $(this).val(dateStr); });
8628
		}
8629
	},
8630
8631
	/* Set as beforeShowDay function to prevent selection of weekends.
8632
	 * @param  date  Date - the date to customise
8633
	 * @return [boolean, string] - is this date selectable?, what is its CSS class?
8634
	 */
8635
	noWeekends: function(date) {
8636
		var day = date.getDay();
8637
		return [(day > 0 && day < 6), ""];
8638
	},
8639
8640
	/* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
8641
	 * @param  date  Date - the date to get the week for
8642
	 * @return  number - the number of the week within the year that contains this date
8643
	 */
8644
	iso8601Week: function(date) {
8645
		var time,
8646
			checkDate = new Date(date.getTime());
8647
8648
		// Find Thursday of this week starting on Monday
8649
		checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
8650
8651
		time = checkDate.getTime();
8652
		checkDate.setMonth(0); // Compare with Jan 1
8653
		checkDate.setDate(1);
8654
		return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
8655
	},
8656
8657
	/* Parse a string value into a date object.
8658
	 * See formatDate below for the possible formats.
8659
	 *
8660
	 * @param  format string - the expected format of the date
8661
	 * @param  value string - the date in the above format
8662
	 * @param  settings Object - attributes include:
8663
	 *					shortYearCutoff  number - the cutoff year for determining the century (optional)
8664
	 *					dayNamesShort	string[7] - abbreviated names of the days from Sunday (optional)
8665
	 *					dayNames		string[7] - names of the days from Sunday (optional)
8666
	 *					monthNamesShort string[12] - abbreviated names of the months (optional)
8667
	 *					monthNames		string[12] - names of the months (optional)
8668
	 * @return  Date - the extracted date value or null if value is blank
8669
	 */
8670
	parseDate: function (format, value, settings) {
8671
		if (format == null || value == null) {
8672
			throw "Invalid arguments";
8673
		}
8674
8675
		value = (typeof value === "object" ? value.toString() : value + "");
8676
		if (value === "") {
8677
			return null;
8678
		}
8679
8680
		var iFormat, dim, extra,
8681
			iValue = 0,
8682
			shortYearCutoffTemp = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff,
8683
			shortYearCutoff = (typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp :
8684
				new Date().getFullYear() % 100 + parseInt(shortYearCutoffTemp, 10)),
8685
			dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort,
8686
			dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames,
8687
			monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort,
8688
			monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames,
8689
			year = -1,
8690
			month = -1,
8691
			day = -1,
8692
			doy = -1,
8693
			literal = false,
8694
			date,
8695
			// Check whether a format character is doubled
8696
			lookAhead = function(match) {
8697
				var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
8698
				if (matches) {
8699
					iFormat++;
8700
				}
8701
				return matches;
8702
			},
8703
			// Extract a number from the string value
8704
			getNumber = function(match) {
8705
				var isDoubled = lookAhead(match),
8706
					size = (match === "@" ? 14 : (match === "!" ? 20 :
8707
					(match === "y" && isDoubled ? 4 : (match === "o" ? 3 : 2)))),
8708
					digits = new RegExp("^\\d{1," + size + "}"),
8709
					num = value.substring(iValue).match(digits);
8710
				if (!num) {
8711
					throw "Missing number at position " + iValue;
8712
				}
8713
				iValue += num[0].length;
8714
				return parseInt(num[0], 10);
8715
			},
8716
			// Extract a name from the string value and convert to an index
8717
			getName = function(match, shortNames, longNames) {
8718
				var index = -1,
8719
					names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) {
8720
						return [ [k, v] ];
8721
					}).sort(function (a, b) {
8722
						return -(a[1].length - b[1].length);
8723
					});
8724
8725
				$.each(names, function (i, pair) {
8726
					var name = pair[1];
8727
					if (value.substr(iValue, name.length).toLowerCase() === name.toLowerCase()) {
8728
						index = pair[0];
8729
						iValue += name.length;
8730
						return false;
8731
					}
8732
				});
8733
				if (index !== -1) {
8734
					return index + 1;
8735
				} else {
8736
					throw "Unknown name at position " + iValue;
8737
				}
8738
			},
8739
			// Confirm that a literal character matches the string value
8740
			checkLiteral = function() {
8741
				if (value.charAt(iValue) !== format.charAt(iFormat)) {
8742
					throw "Unexpected literal at position " + iValue;
8743
				}
8744
				iValue++;
8745
			};
8746
8747
		for (iFormat = 0; iFormat < format.length; iFormat++) {
8748
			if (literal) {
8749
				if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
8750
					literal = false;
8751
				} else {
8752
					checkLiteral();
8753
				}
8754
			} else {
8755
				switch (format.charAt(iFormat)) {
8756
					case "d":
8757
						day = getNumber("d");
8758
						break;
8759
					case "D":
8760
						getName("D", dayNamesShort, dayNames);
8761
						break;
8762
					case "o":
8763
						doy = getNumber("o");
8764
						break;
8765
					case "m":
8766
						month = getNumber("m");
8767
						break;
8768
					case "M":
8769
						month = getName("M", monthNamesShort, monthNames);
8770
						break;
8771
					case "y":
8772
						year = getNumber("y");
8773
						break;
8774
					case "@":
8775
						date = new Date(getNumber("@"));
8776
						year = date.getFullYear();
8777
						month = date.getMonth() + 1;
8778
						day = date.getDate();
8779
						break;
8780
					case "!":
8781
						date = new Date((getNumber("!") - this._ticksTo1970) / 10000);
8782
						year = date.getFullYear();
8783
						month = date.getMonth() + 1;
8784
						day = date.getDate();
8785
						break;
8786
					case "'":
8787
						if (lookAhead("'")){
8788
							checkLiteral();
8789
						} else {
8790
							literal = true;
8791
						}
8792
						break;
8793
					default:
8794
						checkLiteral();
8795
				}
8796
			}
8797
		}
8798
8799
		if (iValue < value.length){
8800
			extra = value.substr(iValue);
8801
			if (!/^\s+/.test(extra)) {
8802
				throw "Extra/unparsed characters found in date: " + extra;
8803
			}
8804
		}
8805
8806
		if (year === -1) {
8807
			year = new Date().getFullYear();
8808
		} else if (year < 100) {
8809
			year += new Date().getFullYear() - new Date().getFullYear() % 100 +
8810
				(year <= shortYearCutoff ? 0 : -100);
8811
		}
8812
8813
		if (doy > -1) {
8814
			month = 1;
8815
			day = doy;
8816
			do {
8817
				dim = this._getDaysInMonth(year, month - 1);
8818
				if (day <= dim) {
8819
					break;
8820
				}
8821
				month++;
8822
				day -= dim;
8823
			} while (true);
8824
		}
8825
8826
		date = this._daylightSavingAdjust(new Date(year, month - 1, day));
8827
		if (date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day) {
8828
			throw "Invalid date"; // E.g. 31/02/00
8829
		}
8830
		return date;
8831
	},
8832
8833
	/* Standard date formats. */
8834
	ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601)
8835
	COOKIE: "D, dd M yy",
8836
	ISO_8601: "yy-mm-dd",
8837
	RFC_822: "D, d M y",
8838
	RFC_850: "DD, dd-M-y",
8839
	RFC_1036: "D, d M y",
8840
	RFC_1123: "D, d M yy",
8841
	RFC_2822: "D, d M yy",
8842
	RSS: "D, d M y", // RFC 822
8843
	TICKS: "!",
8844
	TIMESTAMP: "@",
8845
	W3C: "yy-mm-dd", // ISO 8601
8846
8847
	_ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
8848
		Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
8849
8850
	/* Format a date object into a string value.
8851
	 * The format can be combinations of the following:
8852
	 * d  - day of month (no leading zero)
8853
	 * dd - day of month (two digit)
8854
	 * o  - day of year (no leading zeros)
8855
	 * oo - day of year (three digit)
8856
	 * D  - day name short
8857
	 * DD - day name long
8858
	 * m  - month of year (no leading zero)
8859
	 * mm - month of year (two digit)
8860
	 * M  - month name short
8861
	 * MM - month name long
8862
	 * y  - year (two digit)
8863
	 * yy - year (four digit)
8864
	 * @ - Unix timestamp (ms since 01/01/1970)
8865
	 * ! - Windows ticks (100ns since 01/01/0001)
8866
	 * "..." - literal text
8867
	 * '' - single quote
8868
	 *
8869
	 * @param  format string - the desired format of the date
8870
	 * @param  date Date - the date value to format
8871
	 * @param  settings Object - attributes include:
8872
	 *					dayNamesShort	string[7] - abbreviated names of the days from Sunday (optional)
8873
	 *					dayNames		string[7] - names of the days from Sunday (optional)
8874
	 *					monthNamesShort string[12] - abbreviated names of the months (optional)
8875
	 *					monthNames		string[12] - names of the months (optional)
8876
	 * @return  string - the date in the above format
8877
	 */
8878
	formatDate: function (format, date, settings) {
8879
		if (!date) {
8880
			return "";
8881
		}
8882
8883
		var iFormat,
8884
			dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort,
8885
			dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames,
8886
			monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort,
8887
			monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames,
8888
			// Check whether a format character is doubled
8889
			lookAhead = function(match) {
8890
				var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
8891
				if (matches) {
8892
					iFormat++;
8893
				}
8894
				return matches;
8895
			},
8896
			// Format a number, with leading zero if necessary
8897
			formatNumber = function(match, value, len) {
8898
				var num = "" + value;
8899
				if (lookAhead(match)) {
8900
					while (num.length < len) {
8901
						num = "0" + num;
8902
					}
8903
				}
8904
				return num;
8905
			},
8906
			// Format a name, short or long as requested
8907
			formatName = function(match, value, shortNames, longNames) {
8908
				return (lookAhead(match) ? longNames[value] : shortNames[value]);
8909
			},
8910
			output = "",
8911
			literal = false;
8912
8913
		if (date) {
8914
			for (iFormat = 0; iFormat < format.length; iFormat++) {
8915
				if (literal) {
8916
					if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
8917
						literal = false;
8918
					} else {
8919
						output += format.charAt(iFormat);
8920
					}
8921
				} else {
8922
					switch (format.charAt(iFormat)) {
8923
						case "d":
8924
							output += formatNumber("d", date.getDate(), 2);
8925
							break;
8926
						case "D":
8927
							output += formatName("D", date.getDay(), dayNamesShort, dayNames);
8928
							break;
8929
						case "o":
8930
							output += formatNumber("o",
8931
								Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3);
8932
							break;
8933
						case "m":
8934
							output += formatNumber("m", date.getMonth() + 1, 2);
8935
							break;
8936
						case "M":
8937
							output += formatName("M", date.getMonth(), monthNamesShort, monthNames);
8938
							break;
8939
						case "y":
8940
							output += (lookAhead("y") ? date.getFullYear() :
8941
								(date.getYear() % 100 < 10 ? "0" : "") + date.getYear() % 100);
8942
							break;
8943
						case "@":
8944
							output += date.getTime();
8945
							break;
8946
						case "!":
8947
							output += date.getTime() * 10000 + this._ticksTo1970;
8948
							break;
8949
						case "'":
8950
							if (lookAhead("'")) {
8951
								output += "'";
8952
							} else {
8953
								literal = true;
8954
							}
8955
							break;
8956
						default:
8957
							output += format.charAt(iFormat);
8958
					}
8959
				}
8960
			}
8961
		}
8962
		return output;
8963
	},
8964
8965
	/* Extract all possible characters from the date format. */
8966
	_possibleChars: function (format) {
8967
		var iFormat,
8968
			chars = "",
8969
			literal = false,
8970
			// Check whether a format character is doubled
8971
			lookAhead = function(match) {
8972
				var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
8973
				if (matches) {
8974
					iFormat++;
8975
				}
8976
				return matches;
8977
			};
8978
8979
		for (iFormat = 0; iFormat < format.length; iFormat++) {
8980
			if (literal) {
8981
				if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
8982
					literal = false;
8983
				} else {
8984
					chars += format.charAt(iFormat);
8985
				}
8986
			} else {
8987
				switch (format.charAt(iFormat)) {
8988
					case "d": case "m": case "y": case "@":
8989
						chars += "0123456789";
8990
						break;
8991
					case "D": case "M":
8992
						return null; // Accept anything
8993
					case "'":
8994
						if (lookAhead("'")) {
8995
							chars += "'";
8996
						} else {
8997
							literal = true;
8998
						}
8999
						break;
9000
					default:
9001
						chars += format.charAt(iFormat);
9002
				}
9003
			}
9004
		}
9005
		return chars;
9006
	},
9007
9008
	/* Get a setting value, defaulting if necessary. */
9009
	_get: function(inst, name) {
9010
		return inst.settings[name] !== undefined ?
9011
			inst.settings[name] : this._defaults[name];
9012
	},
9013
9014
	/* Parse existing date and initialise date picker. */
9015
	_setDateFromField: function(inst, noDefault) {
9016
		if (inst.input.val() === inst.lastVal) {
9017
			return;
9018
		}
9019
9020
		var dateFormat = this._get(inst, "dateFormat"),
9021
			dates = inst.lastVal = inst.input ? inst.input.val() : null,
9022
			defaultDate = this._getDefaultDate(inst),
9023
			date = defaultDate,
9024
			settings = this._getFormatConfig(inst);
9025
9026
		try {
9027
			date = this.parseDate(dateFormat, dates, settings) || defaultDate;
9028
		} catch (event) {
9029
			dates = (noDefault ? "" : dates);
9030
		}
9031
		inst.selectedDay = date.getDate();
9032
		inst.drawMonth = inst.selectedMonth = date.getMonth();
9033
		inst.drawYear = inst.selectedYear = date.getFullYear();
9034
		inst.currentDay = (dates ? date.getDate() : 0);
9035
		inst.currentMonth = (dates ? date.getMonth() : 0);
9036
		inst.currentYear = (dates ? date.getFullYear() : 0);
9037
		this._adjustInstDate(inst);
9038
	},
9039
9040
	/* Retrieve the default date shown on opening. */
9041
	_getDefaultDate: function(inst) {
9042
		return this._restrictMinMax(inst,
9043
			this._determineDate(inst, this._get(inst, "defaultDate"), new Date()));
9044
	},
9045
9046
	/* A date may be specified as an exact value or a relative one. */
9047
	_determineDate: function(inst, date, defaultDate) {
9048
		var offsetNumeric = function(offset) {
9049
				var date = new Date();
9050
				date.setDate(date.getDate() + offset);
9051
				return date;
9052
			},
9053
			offsetString = function(offset) {
9054
				try {
9055
					return $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"),
9056
						offset, $.datepicker._getFormatConfig(inst));
9057
				}
9058
				catch (e) {
9059
					// Ignore
9060
				}
9061
9062
				var date = (offset.toLowerCase().match(/^c/) ?
9063
					$.datepicker._getDate(inst) : null) || new Date(),
9064
					year = date.getFullYear(),
9065
					month = date.getMonth(),
9066
					day = date.getDate(),
9067
					pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,
9068
					matches = pattern.exec(offset);
9069
9070
				while (matches) {
9071
					switch (matches[2] || "d") {
9072
						case "d" : case "D" :
9073
							day += parseInt(matches[1],10); break;
9074
						case "w" : case "W" :
9075
							day += parseInt(matches[1],10) * 7; break;
9076
						case "m" : case "M" :
9077
							month += parseInt(matches[1],10);
9078
							day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
9079
							break;
9080
						case "y": case "Y" :
9081
							year += parseInt(matches[1],10);
9082
							day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
9083
							break;
9084
					}
9085
					matches = pattern.exec(offset);
9086
				}
9087
				return new Date(year, month, day);
9088
			},
9089
			newDate = (date == null || date === "" ? defaultDate : (typeof date === "string" ? offsetString(date) :
9090
				(typeof date === "number" ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime()))));
9091
9092
		newDate = (newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate);
9093
		if (newDate) {
9094
			newDate.setHours(0);
9095
			newDate.setMinutes(0);
9096
			newDate.setSeconds(0);
9097
			newDate.setMilliseconds(0);
9098
		}
9099
		return this._daylightSavingAdjust(newDate);
9100
	},
9101
9102
	/* Handle switch to/from daylight saving.
9103
	 * Hours may be non-zero on daylight saving cut-over:
9104
	 * > 12 when midnight changeover, but then cannot generate
9105
	 * midnight datetime, so jump to 1AM, otherwise reset.
9106
	 * @param  date  (Date) the date to check
9107
	 * @return  (Date) the corrected date
9108
	 */
9109
	_daylightSavingAdjust: function(date) {
9110
		if (!date) {
9111
			return null;
9112
		}
9113
		date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
9114
		return date;
9115
	},
9116
9117
	/* Set the date(s) directly. */
9118
	_setDate: function(inst, date, noChange) {
9119
		var clear = !date,
9120
			origMonth = inst.selectedMonth,
9121
			origYear = inst.selectedYear,
9122
			newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
9123
9124
		inst.selectedDay = inst.currentDay = newDate.getDate();
9125
		inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
9126
		inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
9127
		if ((origMonth !== inst.selectedMonth || origYear !== inst.selectedYear) && !noChange) {
9128
			this._notifyChange(inst);
9129
		}
9130
		this._adjustInstDate(inst);
9131
		if (inst.input) {
9132
			inst.input.val(clear ? "" : this._formatDate(inst));
9133
		}
9134
	},
9135
9136
	/* Retrieve the date(s) directly. */
9137
	_getDate: function(inst) {
9138
		var startDate = (!inst.currentYear || (inst.input && inst.input.val() === "") ? null :
9139
			this._daylightSavingAdjust(new Date(
9140
			inst.currentYear, inst.currentMonth, inst.currentDay)));
9141
			return startDate;
9142
	},
9143
9144
	/* Attach the onxxx handlers.  These are declared statically so
9145
	 * they work with static code transformers like Caja.
9146
	 */
9147
	_attachHandlers: function(inst) {
9148
		var stepMonths = this._get(inst, "stepMonths"),
9149
			id = "#" + inst.id.replace( /\\\\/g, "\\" );
9150
		inst.dpDiv.find("[data-handler]").map(function () {
9151
			var handler = {
9152
				prev: function () {
9153
					$.datepicker._adjustDate(id, -stepMonths, "M");
9154
				},
9155
				next: function () {
9156
					$.datepicker._adjustDate(id, +stepMonths, "M");
9157
				},
9158
				hide: function () {
9159
					$.datepicker._hideDatepicker();
9160
				},
9161
				today: function () {
9162
					$.datepicker._gotoToday(id);
9163
				},
9164
				selectDay: function () {
9165
					$.datepicker._selectDay(id, +this.getAttribute("data-month"), +this.getAttribute("data-year"), this);
9166
					return false;
9167
				},
9168
				selectMonth: function () {
9169
					$.datepicker._selectMonthYear(id, this, "M");
9170
					return false;
9171
				},
9172
				selectYear: function () {
9173
					$.datepicker._selectMonthYear(id, this, "Y");
9174
					return false;
9175
				}
9176
			};
9177
			$(this).bind(this.getAttribute("data-event"), handler[this.getAttribute("data-handler")]);
9178
		});
9179
	},
9180
9181
	/* Generate the HTML for the current state of the date picker. */
9182
	_generateHTML: function(inst) {
9183
		var maxDraw, prevText, prev, nextText, next, currentText, gotoDate,
9184
			controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin,
9185
			monthNames, monthNamesShort, beforeShowDay, showOtherMonths,
9186
			selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate,
9187
			cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows,
9188
			printDate, dRow, tbody, daySettings, otherMonth, unselectable,
9189
			tempDate = new Date(),
9190
			today = this._daylightSavingAdjust(
9191
				new Date(tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate())), // clear time
9192
			isRTL = this._get(inst, "isRTL"),
9193
			showButtonPanel = this._get(inst, "showButtonPanel"),
9194
			hideIfNoPrevNext = this._get(inst, "hideIfNoPrevNext"),
9195
			navigationAsDateFormat = this._get(inst, "navigationAsDateFormat"),
9196
			numMonths = this._getNumberOfMonths(inst),
9197
			showCurrentAtPos = this._get(inst, "showCurrentAtPos"),
9198
			stepMonths = this._get(inst, "stepMonths"),
9199
			isMultiMonth = (numMonths[0] !== 1 || numMonths[1] !== 1),
9200
			currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
9201
				new Date(inst.currentYear, inst.currentMonth, inst.currentDay))),
9202
			minDate = this._getMinMaxDate(inst, "min"),
9203
			maxDate = this._getMinMaxDate(inst, "max"),
9204
			drawMonth = inst.drawMonth - showCurrentAtPos,
9205
			drawYear = inst.drawYear;
9206
9207
		if (drawMonth < 0) {
9208
			drawMonth += 12;
9209
			drawYear--;
9210
		}
9211
		if (maxDate) {
9212
			maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
9213
				maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
9214
			maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
9215
			while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
9216
				drawMonth--;
9217
				if (drawMonth < 0) {
9218
					drawMonth = 11;
9219
					drawYear--;
9220
				}
9221
			}
9222
		}
9223
		inst.drawMonth = drawMonth;
9224
		inst.drawYear = drawYear;
9225
9226
		prevText = this._get(inst, "prevText");
9227
		prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
9228
			this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
9229
			this._getFormatConfig(inst)));
9230
9231 View Code Duplication
		prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
9232
			"<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click'" +
9233
			" title='" + prevText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w") + "'>" + prevText + "</span></a>" :
9234
			(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>"));
9235
9236
		nextText = this._get(inst, "nextText");
9237
		nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
9238
			this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
9239
			this._getFormatConfig(inst)));
9240
9241 View Code Duplication
		next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
9242
			"<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click'" +
9243
			" title='" + nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e") + "'>" + nextText + "</span></a>" :
9244
			(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>"));
9245
9246
		currentText = this._get(inst, "currentText");
9247
		gotoDate = (this._get(inst, "gotoCurrent") && inst.currentDay ? currentDate : today);
9248
		currentText = (!navigationAsDateFormat ? currentText :
9249
			this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
9250
9251
		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'>" +
9252
			this._get(inst, "closeText") + "</button>" : "");
9253
9254
		buttonPanel = (showButtonPanel) ? "<div class='ui-datepicker-buttonpane ui-widget-content'>" + (isRTL ? controls : "") +
9255
			(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'" +
9256
			">" + currentText + "</button>" : "") + (isRTL ? "" : controls) + "</div>" : "";
9257
9258
		firstDay = parseInt(this._get(inst, "firstDay"),10);
9259
		firstDay = (isNaN(firstDay) ? 0 : firstDay);
9260
9261
		showWeek = this._get(inst, "showWeek");
9262
		dayNames = this._get(inst, "dayNames");
9263
		dayNamesMin = this._get(inst, "dayNamesMin");
9264
		monthNames = this._get(inst, "monthNames");
9265
		monthNamesShort = this._get(inst, "monthNamesShort");
9266
		beforeShowDay = this._get(inst, "beforeShowDay");
9267
		showOtherMonths = this._get(inst, "showOtherMonths");
9268
		selectOtherMonths = this._get(inst, "selectOtherMonths");
9269
		defaultDate = this._getDefaultDate(inst);
9270
		html = "";
9271
		dow;
9272
		for (row = 0; row < numMonths[0]; row++) {
9273
			group = "";
9274
			this.maxRows = 4;
9275
			for (col = 0; col < numMonths[1]; col++) {
9276
				selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
9277
				cornerClass = " ui-corner-all";
9278
				calender = "";
9279
				if (isMultiMonth) {
9280
					calender += "<div class='ui-datepicker-group";
9281
					if (numMonths[1] > 1) {
9282
						switch (col) {
9283
							case 0: calender += " ui-datepicker-group-first";
9284
								cornerClass = " ui-corner-" + (isRTL ? "right" : "left"); break;
9285
							case numMonths[1]-1: calender += " ui-datepicker-group-last";
9286
								cornerClass = " ui-corner-" + (isRTL ? "left" : "right"); break;
9287
							default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break;
9288
						}
9289
					}
9290
					calender += "'>";
9291
				}
9292
				calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" +
9293
					(/all|left/.test(cornerClass) && row === 0 ? (isRTL ? next : prev) : "") +
9294
					(/all|right/.test(cornerClass) && row === 0 ? (isRTL ? prev : next) : "") +
9295
					this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
9296
					row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
9297
					"</div><table class='ui-datepicker-calendar'><thead>" +
9298
					"<tr>";
9299
				thead = (showWeek ? "<th class='ui-datepicker-week-col'>" + this._get(inst, "weekHeader") + "</th>" : "");
9300
				for (dow = 0; dow < 7; dow++) { // days of the week
9301
					day = (dow + firstDay) % 7;
9302
					thead += "<th" + ((dow + firstDay + 6) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "") + ">" +
9303
						"<span title='" + dayNames[day] + "'>" + dayNamesMin[day] + "</span></th>";
9304
				}
9305
				calender += thead + "</tr></thead><tbody>";
9306
				daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
9307
				if (drawYear === inst.selectedYear && drawMonth === inst.selectedMonth) {
9308
					inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
9309
				}
9310
				leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
9311
				curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate
9312
				numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043)
9313
				this.maxRows = numRows;
9314
				printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
9315
				for (dRow = 0; dRow < numRows; dRow++) { // create date picker rows
9316
					calender += "<tr>";
9317
					tbody = (!showWeek ? "" : "<td class='ui-datepicker-week-col'>" +
9318
						this._get(inst, "calculateWeek")(printDate) + "</td>");
9319
					for (dow = 0; dow < 7; dow++) { // create date picker days
9320
						daySettings = (beforeShowDay ?
9321
							beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, ""]);
9322
						otherMonth = (printDate.getMonth() !== drawMonth);
9323
						unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
9324
							(minDate && printDate < minDate) || (maxDate && printDate > maxDate);
9325
						tbody += "<td class='" +
9326
							((dow + firstDay + 6) % 7 >= 5 ? " ui-datepicker-week-end" : "") + // highlight weekends
9327
							(otherMonth ? " ui-datepicker-other-month" : "") + // highlight days from other months
9328
							((printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent) || // user pressed key
9329
							(defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime()) ?
9330
							// or defaultDate is current printedDate and defaultDate is selectedDate
9331
							" " + this._dayOverClass : "") + // highlight selected day
9332
							(unselectable ? " " + this._unselectableClass + " ui-state-disabled": "") +  // highlight unselectable days
9333
							(otherMonth && !showOtherMonths ? "" : " " + daySettings[1] + // highlight custom dates
9334
							(printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "") + // highlight selected day
9335
							(printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "")) + "'" + // highlight today (if different)
9336
							((!otherMonth || showOtherMonths) && daySettings[2] ? " title='" + daySettings[2].replace(/'/g, "&#39;") + "'" : "") + // cell title
9337
							(unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'") + ">" + // actions
9338
							(otherMonth && !showOtherMonths ? "&#xa0;" : // display for other months
9339
							(unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" +
9340
							(printDate.getTime() === today.getTime() ? " ui-state-highlight" : "") +
9341
							(printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "") + // highlight selected day
9342
							(otherMonth ? " ui-priority-secondary" : "") + // distinguish dates from other months
9343
							"' href='#'>" + printDate.getDate() + "</a>")) + "</td>"; // display selectable date
9344
						printDate.setDate(printDate.getDate() + 1);
9345
						printDate = this._daylightSavingAdjust(printDate);
9346
					}
9347
					calender += tbody + "</tr>";
9348
				}
9349
				drawMonth++;
9350
				if (drawMonth > 11) {
9351
					drawMonth = 0;
9352
					drawYear++;
9353
				}
9354
				calender += "</tbody></table>" + (isMultiMonth ? "</div>" +
9355
							((numMonths[0] > 0 && col === numMonths[1]-1) ? "<div class='ui-datepicker-row-break'></div>" : "") : "");
9356
				group += calender;
9357
			}
9358
			html += group;
9359
		}
9360
		html += buttonPanel;
9361
		inst._keyEvent = false;
9362
		return html;
9363
	},
9364
9365
	/* Generate the month and year header. */
9366
	_generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
9367
			secondary, monthNames, monthNamesShort) {
9368
9369
		var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear,
9370
			changeMonth = this._get(inst, "changeMonth"),
9371
			changeYear = this._get(inst, "changeYear"),
9372
			showMonthAfterYear = this._get(inst, "showMonthAfterYear"),
9373
			html = "<div class='ui-datepicker-title'>",
9374
			monthHtml = "";
9375
9376
		// month selection
9377
		if (secondary || !changeMonth) {
9378
			monthHtml += "<span class='ui-datepicker-month'>" + monthNames[drawMonth] + "</span>";
9379
		} else {
9380
			inMinYear = (minDate && minDate.getFullYear() === drawYear);
9381
			inMaxYear = (maxDate && maxDate.getFullYear() === drawYear);
9382
			monthHtml += "<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>";
9383
			for ( month = 0; month < 12; month++) {
9384
				if ((!inMinYear || month >= minDate.getMonth()) && (!inMaxYear || month <= maxDate.getMonth())) {
9385
					monthHtml += "<option value='" + month + "'" +
9386
						(month === drawMonth ? " selected='selected'" : "") +
9387
						">" + monthNamesShort[month] + "</option>";
9388
				}
9389
			}
9390
			monthHtml += "</select>";
9391
		}
9392
9393
		if (!showMonthAfterYear) {
9394
			html += monthHtml + (secondary || !(changeMonth && changeYear) ? "&#xa0;" : "");
9395
		}
9396
9397
		// year selection
9398
		if ( !inst.yearshtml ) {
9399
			inst.yearshtml = "";
9400
			if (secondary || !changeYear) {
9401
				html += "<span class='ui-datepicker-year'>" + drawYear + "</span>";
9402
			} else {
9403
				// determine range of years to display
9404
				years = this._get(inst, "yearRange").split(":");
9405
				thisYear = new Date().getFullYear();
9406
				determineYear = function(value) {
9407
					var year = (value.match(/c[+\-].*/) ? drawYear + parseInt(value.substring(1), 10) :
9408
						(value.match(/[+\-].*/) ? thisYear + parseInt(value, 10) :
9409
						parseInt(value, 10)));
9410
					return (isNaN(year) ? thisYear : year);
9411
				};
9412
				year = determineYear(years[0]);
9413
				endYear = Math.max(year, determineYear(years[1] || ""));
9414
				year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
9415
				endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
9416
				inst.yearshtml += "<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>";
9417
				for (; year <= endYear; year++) {
9418
					inst.yearshtml += "<option value='" + year + "'" +
9419
						(year === drawYear ? " selected='selected'" : "") +
9420
						">" + year + "</option>";
9421
				}
9422
				inst.yearshtml += "</select>";
9423
9424
				html += inst.yearshtml;
9425
				inst.yearshtml = null;
9426
			}
9427
		}
9428
9429
		html += this._get(inst, "yearSuffix");
9430
		if (showMonthAfterYear) {
9431
			html += (secondary || !(changeMonth && changeYear) ? "&#xa0;" : "") + monthHtml;
9432
		}
9433
		html += "</div>"; // Close datepicker_header
9434
		return html;
9435
	},
9436
9437
	/* Adjust one of the date sub-fields. */
9438
	_adjustInstDate: function(inst, offset, period) {
9439
		var year = inst.drawYear + (period === "Y" ? offset : 0),
9440
			month = inst.drawMonth + (period === "M" ? offset : 0),
9441
			day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) + (period === "D" ? offset : 0),
9442
			date = this._restrictMinMax(inst, this._daylightSavingAdjust(new Date(year, month, day)));
9443
9444
		inst.selectedDay = date.getDate();
9445
		inst.drawMonth = inst.selectedMonth = date.getMonth();
9446
		inst.drawYear = inst.selectedYear = date.getFullYear();
9447
		if (period === "M" || period === "Y") {
9448
			this._notifyChange(inst);
9449
		}
9450
	},
9451
9452
	/* Ensure a date is within any min/max bounds. */
9453
	_restrictMinMax: function(inst, date) {
9454
		var minDate = this._getMinMaxDate(inst, "min"),
9455
			maxDate = this._getMinMaxDate(inst, "max"),
9456
			newDate = (minDate && date < minDate ? minDate : date);
9457
		return (maxDate && newDate > maxDate ? maxDate : newDate);
9458
	},
9459
9460
	/* Notify change of month/year. */
9461
	_notifyChange: function(inst) {
9462
		var onChange = this._get(inst, "onChangeMonthYear");
9463
		if (onChange) {
9464
			onChange.apply((inst.input ? inst.input[0] : null),
9465
				[inst.selectedYear, inst.selectedMonth + 1, inst]);
9466
		}
9467
	},
9468
9469
	/* Determine the number of months to show. */
9470
	_getNumberOfMonths: function(inst) {
9471
		var numMonths = this._get(inst, "numberOfMonths");
9472
		return (numMonths == null ? [1, 1] : (typeof numMonths === "number" ? [1, numMonths] : numMonths));
9473
	},
9474
9475
	/* Determine the current maximum date - ensure no time components are set. */
9476
	_getMinMaxDate: function(inst, minMax) {
9477
		return this._determineDate(inst, this._get(inst, minMax + "Date"), null);
9478
	},
9479
9480
	/* Find the number of days in a given month. */
9481
	_getDaysInMonth: function(year, month) {
9482
		return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate();
9483
	},
9484
9485
	/* Find the day of the week of the first of a month. */
9486
	_getFirstDayOfMonth: function(year, month) {
9487
		return new Date(year, month, 1).getDay();
9488
	},
9489
9490
	/* Determines if we should allow a "next/prev" month display change. */
9491
	_canAdjustMonth: function(inst, offset, curYear, curMonth) {
9492
		var numMonths = this._getNumberOfMonths(inst),
9493
			date = this._daylightSavingAdjust(new Date(curYear,
9494
			curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
9495
9496
		if (offset < 0) {
9497
			date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
9498
		}
9499
		return this._isInRange(inst, date);
9500
	},
9501
9502
	/* Is the given date in the accepted range? */
9503
	_isInRange: function(inst, date) {
9504
		var yearSplit, currentYear,
9505
			minDate = this._getMinMaxDate(inst, "min"),
9506
			maxDate = this._getMinMaxDate(inst, "max"),
9507
			minYear = null,
9508
			maxYear = null,
9509
			years = this._get(inst, "yearRange");
9510
			if (years){
9511
				yearSplit = years.split(":");
9512
				currentYear = new Date().getFullYear();
9513
				minYear = parseInt(yearSplit[0], 10);
9514
				maxYear = parseInt(yearSplit[1], 10);
9515
				if ( yearSplit[0].match(/[+\-].*/) ) {
9516
					minYear += currentYear;
9517
				}
9518
				if ( yearSplit[1].match(/[+\-].*/) ) {
9519
					maxYear += currentYear;
9520
				}
9521
			}
9522
9523
		return ((!minDate || date.getTime() >= minDate.getTime()) &&
9524
			(!maxDate || date.getTime() <= maxDate.getTime()) &&
9525
			(!minYear || date.getFullYear() >= minYear) &&
9526
			(!maxYear || date.getFullYear() <= maxYear));
9527
	},
9528
9529
	/* Provide the configuration settings for formatting/parsing. */
9530
	_getFormatConfig: function(inst) {
9531
		var shortYearCutoff = this._get(inst, "shortYearCutoff");
9532
		shortYearCutoff = (typeof shortYearCutoff !== "string" ? shortYearCutoff :
9533
			new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
9534
		return {shortYearCutoff: shortYearCutoff,
9535
			dayNamesShort: this._get(inst, "dayNamesShort"), dayNames: this._get(inst, "dayNames"),
9536
			monthNamesShort: this._get(inst, "monthNamesShort"), monthNames: this._get(inst, "monthNames")};
9537
	},
9538
9539
	/* Format the given date for display. */
9540
	_formatDate: function(inst, day, month, year) {
9541
		if (!day) {
9542
			inst.currentDay = inst.selectedDay;
9543
			inst.currentMonth = inst.selectedMonth;
9544
			inst.currentYear = inst.selectedYear;
9545
		}
9546
		var date = (day ? (typeof day === "object" ? day :
9547
			this._daylightSavingAdjust(new Date(year, month, day))) :
9548
			this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
9549
		return this.formatDate(this._get(inst, "dateFormat"), date, this._getFormatConfig(inst));
9550
	}
9551
});
9552
9553
/*
9554
 * Bind hover events for datepicker elements.
9555
 * Done via delegate so the binding only occurs once in the lifetime of the parent div.
9556
 * Global instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
9557
 */
9558
function bindHover(dpDiv) {
9559
	var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";
9560
	return dpDiv.delegate(selector, "mouseout", function() {
9561
			$(this).removeClass("ui-state-hover");
9562
			if (this.className.indexOf("ui-datepicker-prev") !== -1) {
9563
				$(this).removeClass("ui-datepicker-prev-hover");
9564
			}
9565
			if (this.className.indexOf("ui-datepicker-next") !== -1) {
9566
				$(this).removeClass("ui-datepicker-next-hover");
9567
			}
9568
		})
9569
		.delegate(selector, "mouseover", function(){
9570
			if (!$.datepicker._isDisabledDatepicker( instActive.inline ? dpDiv.parent()[0] : instActive.input[0])) {
9571
				$(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover");
9572
				$(this).addClass("ui-state-hover");
9573
				if (this.className.indexOf("ui-datepicker-prev") !== -1) {
9574
					$(this).addClass("ui-datepicker-prev-hover");
9575
				}
9576
				if (this.className.indexOf("ui-datepicker-next") !== -1) {
9577
					$(this).addClass("ui-datepicker-next-hover");
9578
				}
9579
			}
9580
		});
9581
}
9582
9583
/* jQuery extend now ignores nulls! */
9584
function extendRemove(target, props) {
9585
	$.extend(target, props);
9586
	for (var name in props) {
9587
		if (props[name] == null) {
9588
			target[name] = props[name];
9589
		}
9590
	}
9591
	return target;
9592
}
9593
9594
/* Invoke the datepicker functionality.
9595
   @param  options  string - a command, optionally followed by additional parameters or
9596
					Object - settings for attaching new datepicker functionality
9597
   @return  jQuery object */
9598
$.fn.datepicker = function(options){
9599
9600
	/* Verify an empty collection wasn't passed - Fixes #6976 */
9601
	if ( !this.length ) {
9602
		return this;
9603
	}
9604
9605
	/* Initialise the date picker. */
9606
	if (!$.datepicker.initialized) {
9607
		$(document).mousedown($.datepicker._checkExternalClick);
9608
		$.datepicker.initialized = true;
9609
	}
9610
9611
	/* Append datepicker main container to body if not exist. */
9612
	if ($("#"+$.datepicker._mainDivId).length === 0) {
9613
		$("body").append($.datepicker.dpDiv);
9614
	}
9615
9616
	var otherArgs = Array.prototype.slice.call(arguments, 1);
9617
	if (typeof options === "string" && (options === "isDisabled" || options === "getDate" || options === "widget")) {
9618
		return $.datepicker["_" + options + "Datepicker"].
9619
			apply($.datepicker, [this[0]].concat(otherArgs));
9620
	}
9621
	if (options === "option" && arguments.length === 2 && typeof arguments[1] === "string") {
9622
		return $.datepicker["_" + options + "Datepicker"].
9623
			apply($.datepicker, [this[0]].concat(otherArgs));
9624
	}
9625
	return this.each(function() {
9626
		typeof options === "string" ?
9627
			$.datepicker["_" + options + "Datepicker"].
9628
				apply($.datepicker, [this].concat(otherArgs)) :
9629
			$.datepicker._attachDatepicker(this, options);
9630
	});
9631
};
9632
9633
$.datepicker = new Datepicker(); // singleton instance
9634
$.datepicker.initialized = false;
9635
$.datepicker.uuid = new Date().getTime();
9636
$.datepicker.version = "1.10.3";
9637
9638
})(jQuery);
9639
9640
(function( $, undefined ) {
9641
9642
var sizeRelatedOptions = {
9643
		buttons: true,
9644
		height: true,
9645
		maxHeight: true,
9646
		maxWidth: true,
9647
		minHeight: true,
9648
		minWidth: true,
9649
		width: true
9650
	},
9651
	resizableRelatedOptions = {
9652
		maxHeight: true,
9653
		maxWidth: true,
9654
		minHeight: true,
9655
		minWidth: true
9656
	};
9657
9658
$.widget( "ui.dialog", {
9659
	version: "1.10.3",
9660
	options: {
9661
		appendTo: "body",
9662
		autoOpen: true,
9663
		buttons: [],
9664
		closeOnEscape: true,
9665
		closeText: "close",
9666
		dialogClass: "",
9667
		draggable: true,
9668
		hide: null,
9669
		height: "auto",
9670
		maxHeight: null,
9671
		maxWidth: null,
9672
		minHeight: 150,
9673
		minWidth: 150,
9674
		modal: false,
9675
		position: {
9676
			my: "center",
9677
			at: "center",
9678
			of: window,
9679
			collision: "fit",
9680
			// Ensure the titlebar is always visible
9681
			using: function( pos ) {
9682
				var topOffset = $( this ).css( pos ).offset().top;
9683
				if ( topOffset < 0 ) {
9684
					$( this ).css( "top", pos.top - topOffset );
9685
				}
9686
			}
9687
		},
9688
		resizable: true,
9689
		show: null,
9690
		title: null,
9691
		width: 300,
9692
9693
		// callbacks
9694
		beforeClose: null,
9695
		close: null,
9696
		drag: null,
9697
		dragStart: null,
9698
		dragStop: null,
9699
		focus: null,
9700
		open: null,
9701
		resize: null,
9702
		resizeStart: null,
9703
		resizeStop: null
9704
	},
9705
9706
	_create: function() {
9707
		this.originalCss = {
9708
			display: this.element[0].style.display,
9709
			width: this.element[0].style.width,
9710
			minHeight: this.element[0].style.minHeight,
9711
			maxHeight: this.element[0].style.maxHeight,
9712
			height: this.element[0].style.height
9713
		};
9714
		this.originalPosition = {
9715
			parent: this.element.parent(),
9716
			index: this.element.parent().children().index( this.element )
9717
		};
9718
		this.originalTitle = this.element.attr("title");
9719
		this.options.title = this.options.title || this.originalTitle;
9720
9721
		this._createWrapper();
9722
9723
		this.element
9724
			.show()
9725
			.removeAttr("title")
9726
			.addClass("ui-dialog-content ui-widget-content")
9727
			.appendTo( this.uiDialog );
9728
9729
		this._createTitlebar();
9730
		this._createButtonPane();
9731
9732
		if ( this.options.draggable && $.fn.draggable ) {
9733
			this._makeDraggable();
9734
		}
9735
		if ( this.options.resizable && $.fn.resizable ) {
9736
			this._makeResizable();
9737
		}
9738
9739
		this._isOpen = false;
9740
	},
9741
9742
	_init: function() {
9743
		if ( this.options.autoOpen ) {
9744
			this.open();
9745
		}
9746
	},
9747
9748
	_appendTo: function() {
9749
		var element = this.options.appendTo;
9750
		if ( element && (element.jquery || element.nodeType) ) {
9751
			return $( element );
9752
		}
9753
		return this.document.find( element || "body" ).eq( 0 );
9754
	},
9755
9756
	_destroy: function() {
9757
		var next,
9758
			originalPosition = this.originalPosition;
9759
9760
		this._destroyOverlay();
9761
9762
		this.element
9763
			.removeUniqueId()
9764
			.removeClass("ui-dialog-content ui-widget-content")
9765
			.css( this.originalCss )
9766
			// Without detaching first, the following becomes really slow
9767
			.detach();
9768
9769
		this.uiDialog.stop( true, true ).remove();
9770
9771
		if ( this.originalTitle ) {
9772
			this.element.attr( "title", this.originalTitle );
9773
		}
9774
9775
		next = originalPosition.parent.children().eq( originalPosition.index );
9776
		// Don't try to place the dialog next to itself (#8613)
9777
		if ( next.length && next[0] !== this.element[0] ) {
9778
			next.before( this.element );
9779
		} else {
9780
			originalPosition.parent.append( this.element );
9781
		}
9782
	},
9783
9784
	widget: function() {
9785
		return this.uiDialog;
9786
	},
9787
9788
	disable: $.noop,
9789
	enable: $.noop,
9790
9791
	close: function( event ) {
9792
		var that = this;
9793
9794
		if ( !this._isOpen || this._trigger( "beforeClose", event ) === false ) {
9795
			return;
9796
		}
9797
9798
		this._isOpen = false;
9799
		this._destroyOverlay();
9800
9801
		if ( !this.opener.filter(":focusable").focus().length ) {
9802
			// Hiding a focused element doesn't trigger blur in WebKit
9803
			// so in case we have nothing to focus on, explicitly blur the active element
9804
			// https://bugs.webkit.org/show_bug.cgi?id=47182
9805
			$( this.document[0].activeElement ).blur();
9806
		}
9807
9808
		this._hide( this.uiDialog, this.options.hide, function() {
9809
			that._trigger( "close", event );
9810
		});
9811
	},
9812
9813
	isOpen: function() {
9814
		return this._isOpen;
9815
	},
9816
9817
	moveToTop: function() {
9818
		this._moveToTop();
9819
	},
9820
9821
	_moveToTop: function( event, silent ) {
9822
		var moved = !!this.uiDialog.nextAll(":visible").insertBefore( this.uiDialog ).length;
9823
		if ( moved && !silent ) {
9824
			this._trigger( "focus", event );
9825
		}
9826
		return moved;
9827
	},
9828
9829
	open: function() {
9830
		var that = this;
9831
		if ( this._isOpen ) {
9832
			if ( this._moveToTop() ) {
9833
				this._focusTabbable();
9834
			}
9835
			return;
9836
		}
9837
9838
		this._isOpen = true;
9839
		this.opener = $( this.document[0].activeElement );
9840
9841
		this._size();
9842
		this._position();
9843
		this._createOverlay();
9844
		this._moveToTop( null, true );
9845
		this._show( this.uiDialog, this.options.show, function() {
9846
			that._focusTabbable();
9847
			that._trigger("focus");
9848
		});
9849
9850
		this._trigger("open");
9851
	},
9852
9853
	_focusTabbable: function() {
9854
		// Set focus to the first match:
9855
		// 1. First element inside the dialog matching [autofocus]
9856
		// 2. Tabbable element inside the content element
9857
		// 3. Tabbable element inside the buttonpane
9858
		// 4. The close button
9859
		// 5. The dialog itself
9860
		var hasFocus = this.element.find("[autofocus]");
9861
		if ( !hasFocus.length ) {
9862
			hasFocus = this.element.find(":tabbable");
9863
		}
9864
		if ( !hasFocus.length ) {
9865
			hasFocus = this.uiDialogButtonPane.find(":tabbable");
9866
		}
9867
		if ( !hasFocus.length ) {
9868
			hasFocus = this.uiDialogTitlebarClose.filter(":tabbable");
9869
		}
9870
		if ( !hasFocus.length ) {
9871
			hasFocus = this.uiDialog;
9872
		}
9873
		hasFocus.eq( 0 ).focus();
9874
	},
9875
9876
	_keepFocus: function( event ) {
9877
		function checkFocus() {
9878
			var activeElement = this.document[0].activeElement,
9879
				isActive = this.uiDialog[0] === activeElement ||
9880
					$.contains( this.uiDialog[0], activeElement );
9881
			if ( !isActive ) {
9882
				this._focusTabbable();
9883
			}
9884
		}
9885
		event.preventDefault();
9886
		checkFocus.call( this );
9887
		// support: IE
9888
		// IE <= 8 doesn't prevent moving focus even with event.preventDefault()
9889
		// so we check again later
9890
		this._delay( checkFocus );
9891
	},
9892
9893
	_createWrapper: function() {
9894
		this.uiDialog = $("<div>")
9895
			.addClass( "ui-dialog ui-widget ui-widget-content ui-corner-all ui-front " +
9896
				this.options.dialogClass )
9897
			.hide()
9898
			.attr({
9899
				// Setting tabIndex makes the div focusable
9900
				tabIndex: -1,
9901
				role: "dialog"
9902
			})
9903
			.appendTo( this._appendTo() );
9904
9905
		this._on( this.uiDialog, {
9906
			keydown: function( event ) {
9907
				if ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
9908
						event.keyCode === $.ui.keyCode.ESCAPE ) {
9909
					event.preventDefault();
9910
					this.close( event );
9911
					return;
9912
				}
9913
9914
				// prevent tabbing out of dialogs
9915
				if ( event.keyCode !== $.ui.keyCode.TAB ) {
9916
					return;
9917
				}
9918
				var tabbables = this.uiDialog.find(":tabbable"),
9919
					first = tabbables.filter(":first"),
9920
					last  = tabbables.filter(":last");
9921
9922
				if ( ( event.target === last[0] || event.target === this.uiDialog[0] ) && !event.shiftKey ) {
9923
					first.focus( 1 );
9924
					event.preventDefault();
9925
				} else if ( ( event.target === first[0] || event.target === this.uiDialog[0] ) && event.shiftKey ) {
9926
					last.focus( 1 );
9927
					event.preventDefault();
9928
				}
9929
			},
9930
			mousedown: function( event ) {
9931
				if ( this._moveToTop( event ) ) {
9932
					this._focusTabbable();
9933
				}
9934
			}
9935
		});
9936
9937
		// We assume that any existing aria-describedby attribute means
9938
		// that the dialog content is marked up properly
9939
		// otherwise we brute force the content as the description
9940
		if ( !this.element.find("[aria-describedby]").length ) {
9941
			this.uiDialog.attr({
9942
				"aria-describedby": this.element.uniqueId().attr("id")
9943
			});
9944
		}
9945
	},
9946
9947
	_createTitlebar: function() {
9948
		var uiDialogTitle;
9949
9950
		this.uiDialogTitlebar = $("<div>")
9951
			.addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix")
9952
			.prependTo( this.uiDialog );
9953
		this._on( this.uiDialogTitlebar, {
9954
			mousedown: function( event ) {
9955
				// Don't prevent click on close button (#8838)
9956
				// Focusing a dialog that is partially scrolled out of view
9957
				// causes the browser to scroll it into view, preventing the click event
9958
				if ( !$( event.target ).closest(".ui-dialog-titlebar-close") ) {
9959
					// Dialog isn't getting focus when dragging (#8063)
9960
					this.uiDialog.focus();
9961
				}
9962
			}
9963
		});
9964
9965
		this.uiDialogTitlebarClose = $("<button></button>")
9966
			.button({
9967
				label: this.options.closeText,
9968
				icons: {
9969
					primary: "ui-icon-closethick"
9970
				},
9971
				text: false
9972
			})
9973
			.addClass("ui-dialog-titlebar-close")
9974
			.appendTo( this.uiDialogTitlebar );
9975
		this._on( this.uiDialogTitlebarClose, {
9976
			click: function( event ) {
9977
				event.preventDefault();
9978
				this.close( event );
9979
			}
9980
		});
9981
9982
		uiDialogTitle = $("<span>")
9983
			.uniqueId()
9984
			.addClass("ui-dialog-title")
9985
			.prependTo( this.uiDialogTitlebar );
9986
		this._title( uiDialogTitle );
9987
9988
		this.uiDialog.attr({
9989
			"aria-labelledby": uiDialogTitle.attr("id")
9990
		});
9991
	},
9992
9993
	_title: function( title ) {
9994
		if ( !this.options.title ) {
9995
			title.html("&#160;");
9996
		}
9997
		title.text( this.options.title );
9998
	},
9999
10000
	_createButtonPane: function() {
10001
		this.uiDialogButtonPane = $("<div>")
10002
			.addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix");
10003
10004
		this.uiButtonSet = $("<div>")
10005
			.addClass("ui-dialog-buttonset")
10006
			.appendTo( this.uiDialogButtonPane );
10007
10008
		this._createButtons();
10009
	},
10010
10011
	_createButtons: function() {
10012
		var that = this,
10013
			buttons = this.options.buttons;
10014
10015
		// if we already have a button pane, remove it
10016
		this.uiDialogButtonPane.remove();
10017
		this.uiButtonSet.empty();
10018
10019
		if ( $.isEmptyObject( buttons ) || ($.isArray( buttons ) && !buttons.length) ) {
10020
			this.uiDialog.removeClass("ui-dialog-buttons");
10021
			return;
10022
		}
10023
10024
		$.each( buttons, function( name, props ) {
10025
			var click, buttonOptions;
10026
			props = $.isFunction( props ) ?
10027
				{ click: props, text: name } :
10028
				props;
10029
			// Default to a non-submitting button
10030
			props = $.extend( { type: "button" }, props );
10031
			// Change the context for the click callback to be the main element
10032
			click = props.click;
10033
			props.click = function() {
10034
				click.apply( that.element[0], arguments );
10035
			};
10036
			buttonOptions = {
10037
				icons: props.icons,
10038
				text: props.showText
10039
			};
10040
			delete props.icons;
10041
			delete props.showText;
10042
			$( "<button></button>", props )
10043
				.button( buttonOptions )
10044
				.appendTo( that.uiButtonSet );
10045
		});
10046
		this.uiDialog.addClass("ui-dialog-buttons");
10047
		this.uiDialogButtonPane.appendTo( this.uiDialog );
10048
	},
10049
10050
	_makeDraggable: function() {
10051
		var that = this,
10052
			options = this.options;
10053
10054
		function filteredUi( ui ) {
10055
			return {
10056
				position: ui.position,
10057
				offset: ui.offset
10058
			};
10059
		}
10060
10061
		this.uiDialog.draggable({
10062
			cancel: ".ui-dialog-content, .ui-dialog-titlebar-close",
10063
			handle: ".ui-dialog-titlebar",
10064
			containment: "document",
10065
			start: function( event, ui ) {
10066
				$( this ).addClass("ui-dialog-dragging");
10067
				that._blockFrames();
10068
				that._trigger( "dragStart", event, filteredUi( ui ) );
10069
			},
10070
			drag: function( event, ui ) {
10071
				that._trigger( "drag", event, filteredUi( ui ) );
10072
			},
10073
			stop: function( event, ui ) {
10074
				options.position = [
10075
					ui.position.left - that.document.scrollLeft(),
10076
					ui.position.top - that.document.scrollTop()
10077
				];
10078
				$( this ).removeClass("ui-dialog-dragging");
10079
				that._unblockFrames();
10080
				that._trigger( "dragStop", event, filteredUi( ui ) );
10081
			}
10082
		});
10083
	},
10084
10085
	_makeResizable: function() {
10086
		var that = this,
10087
			options = this.options,
10088
			handles = options.resizable,
10089
			// .ui-resizable has position: relative defined in the stylesheet
10090
			// but dialogs have to use absolute or fixed positioning
10091
			position = this.uiDialog.css("position"),
10092
			resizeHandles = typeof handles === "string" ?
10093
				handles	:
10094
				"n,e,s,w,se,sw,ne,nw";
10095
10096
		function filteredUi( ui ) {
10097
			return {
10098
				originalPosition: ui.originalPosition,
10099
				originalSize: ui.originalSize,
10100
				position: ui.position,
10101
				size: ui.size
10102
			};
10103
		}
10104
10105
		this.uiDialog.resizable({
10106
			cancel: ".ui-dialog-content",
10107
			containment: "document",
10108
			alsoResize: this.element,
10109
			maxWidth: options.maxWidth,
10110
			maxHeight: options.maxHeight,
10111
			minWidth: options.minWidth,
10112
			minHeight: this._minHeight(),
10113
			handles: resizeHandles,
10114
			start: function( event, ui ) {
10115
				$( this ).addClass("ui-dialog-resizing");
10116
				that._blockFrames();
10117
				that._trigger( "resizeStart", event, filteredUi( ui ) );
10118
			},
10119
			resize: function( event, ui ) {
10120
				that._trigger( "resize", event, filteredUi( ui ) );
10121
			},
10122
			stop: function( event, ui ) {
10123
				options.height = $( this ).height();
10124
				options.width = $( this ).width();
10125
				$( this ).removeClass("ui-dialog-resizing");
10126
				that._unblockFrames();
10127
				that._trigger( "resizeStop", event, filteredUi( ui ) );
10128
			}
10129
		})
10130
		.css( "position", position );
10131
	},
10132
10133
	_minHeight: function() {
10134
		var options = this.options;
10135
10136
		return options.height === "auto" ?
10137
			options.minHeight :
10138
			Math.min( options.minHeight, options.height );
10139
	},
10140
10141
	_position: function() {
10142
		// Need to show the dialog to get the actual offset in the position plugin
10143
		var isVisible = this.uiDialog.is(":visible");
10144
		if ( !isVisible ) {
10145
			this.uiDialog.show();
10146
		}
10147
		this.uiDialog.position( this.options.position );
10148
		if ( !isVisible ) {
10149
			this.uiDialog.hide();
10150
		}
10151
	},
10152
10153
	_setOptions: function( options ) {
10154
		var that = this,
10155
			resize = false,
10156
			resizableOptions = {};
10157
10158
		$.each( options, function( key, value ) {
10159
			that._setOption( key, value );
10160
10161
			if ( key in sizeRelatedOptions ) {
10162
				resize = true;
10163
			}
10164
			if ( key in resizableRelatedOptions ) {
10165
				resizableOptions[ key ] = value;
10166
			}
10167
		});
10168
10169
		if ( resize ) {
10170
			this._size();
10171
			this._position();
10172
		}
10173
		if ( this.uiDialog.is(":data(ui-resizable)") ) {
10174
			this.uiDialog.resizable( "option", resizableOptions );
10175
		}
10176
	},
10177
10178
	_setOption: function( key, value ) {
10179
		/*jshint maxcomplexity:15*/
10180
		var isDraggable, isResizable,
10181
			uiDialog = this.uiDialog;
10182
10183
		if ( key === "dialogClass" ) {
10184
			uiDialog
10185
				.removeClass( this.options.dialogClass )
10186
				.addClass( value );
10187
		}
10188
10189
		if ( key === "disabled" ) {
10190
			return;
10191
		}
10192
10193
		this._super( key, value );
10194
10195
		if ( key === "appendTo" ) {
10196
			this.uiDialog.appendTo( this._appendTo() );
10197
		}
10198
10199
		if ( key === "buttons" ) {
10200
			this._createButtons();
10201
		}
10202
10203
		if ( key === "closeText" ) {
10204
			this.uiDialogTitlebarClose.button({
10205
				// Ensure that we always pass a string
10206
				label: "" + value
10207
			});
10208
		}
10209
10210
		if ( key === "draggable" ) {
10211
			isDraggable = uiDialog.is(":data(ui-draggable)");
10212
			if ( isDraggable && !value ) {
10213
				uiDialog.draggable("destroy");
10214
			}
10215
10216
			if ( !isDraggable && value ) {
10217
				this._makeDraggable();
10218
			}
10219
		}
10220
10221
		if ( key === "position" ) {
10222
			this._position();
10223
		}
10224
10225
		if ( key === "resizable" ) {
10226
			// currently resizable, becoming non-resizable
10227
			isResizable = uiDialog.is(":data(ui-resizable)");
10228
			if ( isResizable && !value ) {
10229
				uiDialog.resizable("destroy");
10230
			}
10231
10232
			// currently resizable, changing handles
10233
			if ( isResizable && typeof value === "string" ) {
10234
				uiDialog.resizable( "option", "handles", value );
10235
			}
10236
10237
			// currently non-resizable, becoming resizable
10238
			if ( !isResizable && value !== false ) {
10239
				this._makeResizable();
10240
			}
10241
		}
10242
10243
		if ( key === "title" ) {
10244
			this._title( this.uiDialogTitlebar.find(".ui-dialog-title") );
10245
		}
10246
	},
10247
10248
	_size: function() {
10249
		// If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
10250
		// divs will both have width and height set, so we need to reset them
10251
		var nonContentHeight, minContentHeight, maxContentHeight,
10252
			options = this.options;
10253
10254
		// Reset content sizing
10255
		this.element.show().css({
10256
			width: "auto",
10257
			minHeight: 0,
10258
			maxHeight: "none",
10259
			height: 0
10260
		});
10261
10262
		if ( options.minWidth > options.width ) {
10263
			options.width = options.minWidth;
10264
		}
10265
10266
		// reset wrapper sizing
10267
		// determine the height of all the non-content elements
10268
		nonContentHeight = this.uiDialog.css({
10269
				height: "auto",
10270
				width: options.width
10271
			})
10272
			.outerHeight();
10273
		minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
10274
		maxContentHeight = typeof options.maxHeight === "number" ?
10275
			Math.max( 0, options.maxHeight - nonContentHeight ) :
10276
			"none";
10277
10278
		if ( options.height === "auto" ) {
10279
			this.element.css({
10280
				minHeight: minContentHeight,
10281
				maxHeight: maxContentHeight,
10282
				height: "auto"
10283
			});
10284
		} else {
10285
			this.element.height( Math.max( 0, options.height - nonContentHeight ) );
10286
		}
10287
10288
		if (this.uiDialog.is(":data(ui-resizable)") ) {
10289
			this.uiDialog.resizable( "option", "minHeight", this._minHeight() );
10290
		}
10291
	},
10292
10293
	_blockFrames: function() {
10294
		this.iframeBlocks = this.document.find( "iframe" ).map(function() {
10295
			var iframe = $( this );
10296
10297
			return $( "<div>" )
10298
				.css({
10299
					position: "absolute",
10300
					width: iframe.outerWidth(),
10301
					height: iframe.outerHeight()
10302
				})
10303
				.appendTo( iframe.parent() )
10304
				.offset( iframe.offset() )[0];
10305
		});
10306
	},
10307
10308
	_unblockFrames: function() {
10309
		if ( this.iframeBlocks ) {
10310
			this.iframeBlocks.remove();
10311
			delete this.iframeBlocks;
10312
		}
10313
	},
10314
10315
	_allowInteraction: function( event ) {
10316
		if ( $( event.target ).closest(".ui-dialog").length ) {
10317
			return true;
10318
		}
10319
10320
		// TODO: Remove hack when datepicker implements
10321
		// the .ui-front logic (#8989)
10322
		return !!$( event.target ).closest(".ui-datepicker").length;
10323
	},
10324
10325
	_createOverlay: function() {
10326
		if ( !this.options.modal ) {
10327
			return;
10328
		}
10329
10330
		var that = this,
10331
			widgetFullName = this.widgetFullName;
10332
		if ( !$.ui.dialog.overlayInstances ) {
10333
			// Prevent use of anchors and inputs.
10334
			// We use a delay in case the overlay is created from an
10335
			// event that we're going to be cancelling. (#2804)
10336
			this._delay(function() {
10337
				// Handle .dialog().dialog("close") (#4065)
10338
				if ( $.ui.dialog.overlayInstances ) {
10339
					this.document.bind( "focusin.dialog", function( event ) {
10340
						if ( !that._allowInteraction( event ) ) {
10341
							event.preventDefault();
10342
							$(".ui-dialog:visible:last .ui-dialog-content")
10343
								.data( widgetFullName )._focusTabbable();
10344
						}
10345
					});
10346
				}
10347
			});
10348
		}
10349
10350
		this.overlay = $("<div>")
10351
			.addClass("ui-widget-overlay ui-front")
10352
			.appendTo( this._appendTo() );
10353
		this._on( this.overlay, {
10354
			mousedown: "_keepFocus"
10355
		});
10356
		$.ui.dialog.overlayInstances++;
10357
	},
10358
10359
	_destroyOverlay: function() {
10360
		if ( !this.options.modal ) {
10361
			return;
10362
		}
10363
10364
		if ( this.overlay ) {
10365
			$.ui.dialog.overlayInstances--;
10366
10367
			if ( !$.ui.dialog.overlayInstances ) {
10368
				this.document.unbind( "focusin.dialog" );
10369
			}
10370
			this.overlay.remove();
10371
			this.overlay = null;
10372
		}
10373
	}
10374
});
10375
10376
$.ui.dialog.overlayInstances = 0;
10377
10378
// DEPRECATED
10379
if ( $.uiBackCompat !== false ) {
10380
	// position option with array notation
10381
	// just override with old implementation
10382
	$.widget( "ui.dialog", $.ui.dialog, {
10383
		_position: function() {
10384
			var position = this.options.position,
10385
				myAt = [],
10386
				offset = [ 0, 0 ],
10387
				isVisible;
10388
10389
			if ( position ) {
10390
				if ( typeof position === "string" || (typeof position === "object" && "0" in position ) ) {
10391
					myAt = position.split ? position.split(" ") : [ position[0], position[1] ];
10392
					if ( myAt.length === 1 ) {
10393
						myAt[1] = myAt[0];
10394
					}
10395
10396
					$.each( [ "left", "top" ], function( i, offsetPosition ) {
10397
						if ( +myAt[ i ] === myAt[ i ] ) {
10398
							offset[ i ] = myAt[ i ];
10399
							myAt[ i ] = offsetPosition;
10400
						}
10401
					});
10402
10403
					position = {
10404
						my: myAt[0] + (offset[0] < 0 ? offset[0] : "+" + offset[0]) + " " +
10405
							myAt[1] + (offset[1] < 0 ? offset[1] : "+" + offset[1]),
10406
						at: myAt.join(" ")
10407
					};
10408
				}
10409
10410
				position = $.extend( {}, $.ui.dialog.prototype.options.position, position );
10411
			} else {
10412
				position = $.ui.dialog.prototype.options.position;
10413
			}
10414
10415
			// need to show the dialog to get the actual offset in the position plugin
10416
			isVisible = this.uiDialog.is(":visible");
10417
			if ( !isVisible ) {
10418
				this.uiDialog.show();
10419
			}
10420
			this.uiDialog.position( position );
10421
			if ( !isVisible ) {
10422
				this.uiDialog.hide();
10423
			}
10424
		}
10425
	});
10426
}
10427
10428
}( jQuery ) );
10429
10430
(function( $, undefined ) {
10431
10432
var rvertical = /up|down|vertical/,
10433
	rpositivemotion = /up|left|vertical|horizontal/;
10434
10435
$.effects.effect.blind = function( o, done ) {
10436
	// Create element
10437
	var el = $( this ),
10438
		props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
10439
		mode = $.effects.setMode( el, o.mode || "hide" ),
10440
		direction = o.direction || "up",
10441
		vertical = rvertical.test( direction ),
10442
		ref = vertical ? "height" : "width",
10443
		ref2 = vertical ? "top" : "left",
10444
		motion = rpositivemotion.test( direction ),
10445
		animation = {},
10446
		show = mode === "show",
10447
		wrapper, distance, margin;
10448
10449
	// if already wrapped, the wrapper's properties are my property. #6245
10450
	if ( el.parent().is( ".ui-effects-wrapper" ) ) {
10451
		$.effects.save( el.parent(), props );
10452
	} else {
10453
		$.effects.save( el, props );
10454
	}
10455
	el.show();
10456
	wrapper = $.effects.createWrapper( el ).css({
10457
		overflow: "hidden"
10458
	});
10459
10460
	distance = wrapper[ ref ]();
10461
	margin = parseFloat( wrapper.css( ref2 ) ) || 0;
10462
10463
	animation[ ref ] = show ? distance : 0;
10464
	if ( !motion ) {
10465
		el
10466
			.css( vertical ? "bottom" : "right", 0 )
10467
			.css( vertical ? "top" : "left", "auto" )
10468
			.css({ position: "absolute" });
10469
10470
		animation[ ref2 ] = show ? margin : distance + margin;
10471
	}
10472
10473
	// start at 0 if we are showing
10474
	if ( show ) {
10475
		wrapper.css( ref, 0 );
10476
		if ( ! motion ) {
10477
			wrapper.css( ref2, margin + distance );
10478
		}
10479
	}
10480
10481
	// Animate
10482
	wrapper.animate( animation, {
10483
		duration: o.duration,
10484
		easing: o.easing,
10485
		queue: false,
10486
		complete: function() {
10487
			if ( mode === "hide" ) {
10488
				el.hide();
10489
			}
10490
			$.effects.restore( el, props );
10491
			$.effects.removeWrapper( el );
10492
			done();
10493
		}
10494
	});
10495
10496
};
10497
10498
})(jQuery);
10499
10500
(function( $, undefined ) {
10501
10502
$.effects.effect.bounce = function( o, done ) {
10503
	var el = $( this ),
10504
		props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
10505
10506
		// defaults:
10507
		mode = $.effects.setMode( el, o.mode || "effect" ),
10508
		hide = mode === "hide",
10509
		show = mode === "show",
10510
		direction = o.direction || "up",
10511
		distance = o.distance,
10512
		times = o.times || 5,
10513
10514
		// number of internal animations
10515
		anims = times * 2 + ( show || hide ? 1 : 0 ),
10516
		speed = o.duration / anims,
10517
		easing = o.easing,
10518
10519
		// utility:
10520
		ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
10521
		motion = ( direction === "up" || direction === "left" ),
10522
		i,
10523
		upAnim,
10524
		downAnim,
10525
10526
		// we will need to re-assemble the queue to stack our animations in place
10527
		queue = el.queue(),
10528
		queuelen = queue.length;
10529
10530
	// Avoid touching opacity to prevent clearType and PNG issues in IE
10531
	if ( show || hide ) {
10532
		props.push( "opacity" );
10533
	}
10534
10535
	$.effects.save( el, props );
10536
	el.show();
10537
	$.effects.createWrapper( el ); // Create Wrapper
10538
10539
	// default distance for the BIGGEST bounce is the outer Distance / 3
10540
	if ( !distance ) {
10541
		distance = el[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3;
10542
	}
10543
10544
	if ( show ) {
10545
		downAnim = { opacity: 1 };
10546
		downAnim[ ref ] = 0;
10547
10548
		// if we are showing, force opacity 0 and set the initial position
10549
		// then do the "first" animation
10550
		el.css( "opacity", 0 )
10551
			.css( ref, motion ? -distance * 2 : distance * 2 )
10552
			.animate( downAnim, speed, easing );
10553
	}
10554
10555
	// start at the smallest distance if we are hiding
10556
	if ( hide ) {
10557
		distance = distance / Math.pow( 2, times - 1 );
10558
	}
10559
10560
	downAnim = {};
10561
	downAnim[ ref ] = 0;
10562
	// Bounces up/down/left/right then back to 0 -- times * 2 animations happen here
10563
	for ( i = 0; i < times; i++ ) {
10564
		upAnim = {};
10565
		upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
10566
10567
		el.animate( upAnim, speed, easing )
10568
			.animate( downAnim, speed, easing );
10569
10570
		distance = hide ? distance * 2 : distance / 2;
10571
	}
10572
10573
	// Last Bounce when Hiding
10574
	if ( hide ) {
10575
		upAnim = { opacity: 0 };
10576
		upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
10577
10578
		el.animate( upAnim, speed, easing );
10579
	}
10580
10581
	el.queue(function() {
10582
		if ( hide ) {
10583
			el.hide();
10584
		}
10585
		$.effects.restore( el, props );
10586
		$.effects.removeWrapper( el );
10587
		done();
10588
	});
10589
10590
	// inject all the animations we just queued to be first in line (after "inprogress")
10591
	if ( queuelen > 1) {
10592
		queue.splice.apply( queue,
10593
			[ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
10594
	}
10595
	el.dequeue();
10596
10597
};
10598
10599
})(jQuery);
10600
10601
(function( $, undefined ) {
10602
10603
$.effects.effect.clip = function( o, done ) {
10604
	// Create element
10605
	var el = $( this ),
10606
		props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
10607
		mode = $.effects.setMode( el, o.mode || "hide" ),
10608
		show = mode === "show",
10609
		direction = o.direction || "vertical",
10610
		vert = direction === "vertical",
10611
		size = vert ? "height" : "width",
10612
		position = vert ? "top" : "left",
10613
		animation = {},
10614
		wrapper, animate, distance;
10615
10616
	// Save & Show
10617
	$.effects.save( el, props );
10618
	el.show();
10619
10620
	// Create Wrapper
10621
	wrapper = $.effects.createWrapper( el ).css({
10622
		overflow: "hidden"
10623
	});
10624
	animate = ( el[0].tagName === "IMG" ) ? wrapper : el;
10625
	distance = animate[ size ]();
10626
10627
	// Shift
10628
	if ( show ) {
10629
		animate.css( size, 0 );
10630
		animate.css( position, distance / 2 );
10631
	}
10632
10633
	// Create Animation Object:
10634
	animation[ size ] = show ? distance : 0;
10635
	animation[ position ] = show ? 0 : distance / 2;
10636
10637
	// Animate
10638
	animate.animate( animation, {
10639
		queue: false,
10640
		duration: o.duration,
10641
		easing: o.easing,
10642
		complete: function() {
10643
			if ( !show ) {
10644
				el.hide();
10645
			}
10646
			$.effects.restore( el, props );
10647
			$.effects.removeWrapper( el );
10648
			done();
10649
		}
10650
	});
10651
10652
};
10653
10654
})(jQuery);
10655
10656
(function( $, undefined ) {
10657
10658
$.effects.effect.drop = function( o, done ) {
10659
10660
	var el = $( this ),
10661
		props = [ "position", "top", "bottom", "left", "right", "opacity", "height", "width" ],
10662
		mode = $.effects.setMode( el, o.mode || "hide" ),
10663
		show = mode === "show",
10664
		direction = o.direction || "left",
10665
		ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
10666
		motion = ( direction === "up" || direction === "left" ) ? "pos" : "neg",
10667
		animation = {
10668
			opacity: show ? 1 : 0
10669
		},
10670
		distance;
10671
10672
	// Adjust
10673
	$.effects.save( el, props );
10674
	el.show();
10675
	$.effects.createWrapper( el );
10676
10677
	distance = o.distance || el[ ref === "top" ? "outerHeight": "outerWidth" ]( true ) / 2;
10678
10679
	if ( show ) {
10680
		el
10681
			.css( "opacity", 0 )
10682
			.css( ref, motion === "pos" ? -distance : distance );
10683
	}
10684
10685
	// Animation
10686
	animation[ ref ] = ( show ?
10687
		( motion === "pos" ? "+=" : "-=" ) :
10688
		( motion === "pos" ? "-=" : "+=" ) ) +
10689
		distance;
10690
10691
	// Animate
10692
	el.animate( animation, {
10693
		queue: false,
10694
		duration: o.duration,
10695
		easing: o.easing,
10696
		complete: function() {
10697
			if ( mode === "hide" ) {
10698
				el.hide();
10699
			}
10700
			$.effects.restore( el, props );
10701
			$.effects.removeWrapper( el );
10702
			done();
10703
		}
10704
	});
10705
};
10706
10707
})(jQuery);
10708
10709
(function( $, undefined ) {
10710
10711
$.effects.effect.explode = function( o, done ) {
10712
10713
	var rows = o.pieces ? Math.round( Math.sqrt( o.pieces ) ) : 3,
10714
		cells = rows,
10715
		el = $( this ),
10716
		mode = $.effects.setMode( el, o.mode || "hide" ),
10717
		show = mode === "show",
10718
10719
		// show and then visibility:hidden the element before calculating offset
10720
		offset = el.show().css( "visibility", "hidden" ).offset(),
10721
10722
		// width and height of a piece
10723
		width = Math.ceil( el.outerWidth() / cells ),
10724
		height = Math.ceil( el.outerHeight() / rows ),
10725
		pieces = [],
10726
10727
		// loop
10728
		i, j, left, top, mx, my;
10729
10730
	// children animate complete:
10731
	function childComplete() {
10732
		pieces.push( this );
10733
		if ( pieces.length === rows * cells ) {
10734
			animComplete();
10735
		}
10736
	}
10737
10738
	// clone the element for each row and cell.
10739
	for( i = 0; i < rows ; i++ ) { // ===>
10740
		top = offset.top + i * height;
10741
		my = i - ( rows - 1 ) / 2 ;
10742
10743
		for( j = 0; j < cells ; j++ ) { // |||
10744
			left = offset.left + j * width;
10745
			mx = j - ( cells - 1 ) / 2 ;
10746
10747
			// Create a clone of the now hidden main element that will be absolute positioned
10748
			// within a wrapper div off the -left and -top equal to size of our pieces
10749
			el
10750
				.clone()
10751
				.appendTo( "body" )
10752
				.wrap( "<div></div>" )
10753
				.css({
10754
					position: "absolute",
10755
					visibility: "visible",
10756
					left: -j * width,
10757
					top: -i * height
10758
				})
10759
10760
			// select the wrapper - make it overflow: hidden and absolute positioned based on
10761
			// where the original was located +left and +top equal to the size of pieces
10762
				.parent()
10763
				.addClass( "ui-effects-explode" )
10764
				.css({
10765
					position: "absolute",
10766
					overflow: "hidden",
10767
					width: width,
10768
					height: height,
10769
					left: left + ( show ? mx * width : 0 ),
10770
					top: top + ( show ? my * height : 0 ),
10771
					opacity: show ? 0 : 1
10772
				}).animate({
10773
					left: left + ( show ? 0 : mx * width ),
10774
					top: top + ( show ? 0 : my * height ),
10775
					opacity: show ? 1 : 0
10776
				}, o.duration || 500, o.easing, childComplete );
10777
		}
10778
	}
10779
10780
	function animComplete() {
10781
		el.css({
10782
			visibility: "visible"
10783
		});
10784
		$( pieces ).remove();
10785
		if ( !show ) {
10786
			el.hide();
10787
		}
10788
		done();
10789
	}
10790
};
10791
10792
})(jQuery);
10793
10794
(function( $, undefined ) {
10795
10796
$.effects.effect.fade = function( o, done ) {
10797
	var el = $( this ),
10798
		mode = $.effects.setMode( el, o.mode || "toggle" );
10799
10800
	el.animate({
10801
		opacity: mode
10802
	}, {
10803
		queue: false,
10804
		duration: o.duration,
10805
		easing: o.easing,
10806
		complete: done
10807
	});
10808
};
10809
10810
})( jQuery );
10811
10812
(function( $, undefined ) {
10813
10814
$.effects.effect.fold = function( o, done ) {
10815
10816
	// Create element
10817
	var el = $( this ),
10818
		props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
10819
		mode = $.effects.setMode( el, o.mode || "hide" ),
10820
		show = mode === "show",
10821
		hide = mode === "hide",
10822
		size = o.size || 15,
10823
		percent = /([0-9]+)%/.exec( size ),
10824
		horizFirst = !!o.horizFirst,
10825
		widthFirst = show !== horizFirst,
10826
		ref = widthFirst ? [ "width", "height" ] : [ "height", "width" ],
10827
		duration = o.duration / 2,
10828
		wrapper, distance,
10829
		animation1 = {},
10830
		animation2 = {};
10831
10832
	$.effects.save( el, props );
10833
	el.show();
10834
10835
	// Create Wrapper
10836
	wrapper = $.effects.createWrapper( el ).css({
10837
		overflow: "hidden"
10838
	});
10839
	distance = widthFirst ?
10840
		[ wrapper.width(), wrapper.height() ] :
10841
		[ wrapper.height(), wrapper.width() ];
10842
10843
	if ( percent ) {
10844
		size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ];
10845
	}
10846
	if ( show ) {
10847
		wrapper.css( horizFirst ? {
10848
			height: 0,
10849
			width: size
10850
		} : {
10851
			height: size,
10852
			width: 0
10853
		});
10854
	}
10855
10856
	// Animation
10857
	animation1[ ref[ 0 ] ] = show ? distance[ 0 ] : size;
10858
	animation2[ ref[ 1 ] ] = show ? distance[ 1 ] : 0;
10859
10860
	// Animate
10861
	wrapper
10862
		.animate( animation1, duration, o.easing )
10863
		.animate( animation2, duration, o.easing, function() {
10864
			if ( hide ) {
10865
				el.hide();
10866
			}
10867
			$.effects.restore( el, props );
10868
			$.effects.removeWrapper( el );
10869
			done();
10870
		});
10871
10872
};
10873
10874
})(jQuery);
10875
10876
(function( $, undefined ) {
10877
10878
$.effects.effect.highlight = function( o, done ) {
10879
	var elem = $( this ),
10880
		props = [ "backgroundImage", "backgroundColor", "opacity" ],
10881
		mode = $.effects.setMode( elem, o.mode || "show" ),
10882
		animation = {
10883
			backgroundColor: elem.css( "backgroundColor" )
10884
		};
10885
10886
	if (mode === "hide") {
10887
		animation.opacity = 0;
10888
	}
10889
10890
	$.effects.save( elem, props );
10891
10892
	elem
10893
		.show()
10894
		.css({
10895
			backgroundImage: "none",
10896
			backgroundColor: o.color || "#ffff99"
10897
		})
10898
		.animate( animation, {
10899
			queue: false,
10900
			duration: o.duration,
10901
			easing: o.easing,
10902
			complete: function() {
10903
				if ( mode === "hide" ) {
10904
					elem.hide();
10905
				}
10906
				$.effects.restore( elem, props );
10907
				done();
10908
			}
10909
		});
10910
};
10911
10912
})(jQuery);
10913
10914
(function( $, undefined ) {
10915
10916
$.effects.effect.pulsate = function( o, done ) {
10917
	var elem = $( this ),
10918
		mode = $.effects.setMode( elem, o.mode || "show" ),
10919
		show = mode === "show",
10920
		hide = mode === "hide",
10921
		showhide = ( show || mode === "hide" ),
10922
10923
		// showing or hiding leaves of the "last" animation
10924
		anims = ( ( o.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ),
10925
		duration = o.duration / anims,
10926
		animateTo = 0,
10927
		queue = elem.queue(),
10928
		queuelen = queue.length,
10929
		i;
10930
10931
	if ( show || !elem.is(":visible")) {
10932
		elem.css( "opacity", 0 ).show();
10933
		animateTo = 1;
10934
	}
10935
10936
	// anims - 1 opacity "toggles"
10937
	for ( i = 1; i < anims; i++ ) {
10938
		elem.animate({
10939
			opacity: animateTo
10940
		}, duration, o.easing );
10941
		animateTo = 1 - animateTo;
10942
	}
10943
10944
	elem.animate({
10945
		opacity: animateTo
10946
	}, duration, o.easing);
10947
10948
	elem.queue(function() {
10949
		if ( hide ) {
10950
			elem.hide();
10951
		}
10952
		done();
10953
	});
10954
10955
	// We just queued up "anims" animations, we need to put them next in the queue
10956
	if ( queuelen > 1 ) {
10957
		queue.splice.apply( queue,
10958
			[ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
10959
	}
10960
	elem.dequeue();
10961
};
10962
10963
})(jQuery);
10964
10965
(function( $, undefined ) {
10966
10967
$.effects.effect.puff = function( o, done ) {
10968
	var elem = $( this ),
10969
		mode = $.effects.setMode( elem, o.mode || "hide" ),
10970
		hide = mode === "hide",
10971
		percent = parseInt( o.percent, 10 ) || 150,
10972
		factor = percent / 100,
10973
		original = {
10974
			height: elem.height(),
10975
			width: elem.width(),
10976
			outerHeight: elem.outerHeight(),
10977
			outerWidth: elem.outerWidth()
10978
		};
10979
10980
	$.extend( o, {
10981
		effect: "scale",
10982
		queue: false,
10983
		fade: true,
10984
		mode: mode,
10985
		complete: done,
10986
		percent: hide ? percent : 100,
10987
		from: hide ?
10988
			original :
10989
			{
10990
				height: original.height * factor,
10991
				width: original.width * factor,
10992
				outerHeight: original.outerHeight * factor,
10993
				outerWidth: original.outerWidth * factor
10994
			}
10995
	});
10996
10997
	elem.effect( o );
10998
};
10999
11000
$.effects.effect.scale = function( o, done ) {
11001
11002
	// Create element
11003
	var el = $( this ),
11004
		options = $.extend( true, {}, o ),
11005
		mode = $.effects.setMode( el, o.mode || "effect" ),
11006
		percent = parseInt( o.percent, 10 ) ||
11007
			( parseInt( o.percent, 10 ) === 0 ? 0 : ( mode === "hide" ? 0 : 100 ) ),
11008
		direction = o.direction || "both",
11009
		origin = o.origin,
11010
		original = {
11011
			height: el.height(),
11012
			width: el.width(),
11013
			outerHeight: el.outerHeight(),
11014
			outerWidth: el.outerWidth()
11015
		},
11016
		factor = {
11017
			y: direction !== "horizontal" ? (percent / 100) : 1,
11018
			x: direction !== "vertical" ? (percent / 100) : 1
11019
		};
11020
11021
	// We are going to pass this effect to the size effect:
11022
	options.effect = "size";
11023
	options.queue = false;
11024
	options.complete = done;
11025
11026
	// Set default origin and restore for show/hide
11027
	if ( mode !== "effect" ) {
11028
		options.origin = origin || ["middle","center"];
11029
		options.restore = true;
11030
	}
11031
11032
	options.from = o.from || ( mode === "show" ? {
11033
		height: 0,
11034
		width: 0,
11035
		outerHeight: 0,
11036
		outerWidth: 0
11037
	} : original );
11038
	options.to = {
11039
		height: original.height * factor.y,
11040
		width: original.width * factor.x,
11041
		outerHeight: original.outerHeight * factor.y,
11042
		outerWidth: original.outerWidth * factor.x
11043
	};
11044
11045
	// Fade option to support puff
11046
	if ( options.fade ) {
11047
		if ( mode === "show" ) {
11048
			options.from.opacity = 0;
11049
			options.to.opacity = 1;
11050
		}
11051
		if ( mode === "hide" ) {
11052
			options.from.opacity = 1;
11053
			options.to.opacity = 0;
11054
		}
11055
	}
11056
11057
	// Animate
11058
	el.effect( options );
11059
11060
};
11061
11062
$.effects.effect.size = function( o, done ) {
11063
11064
	// Create element
11065
	var original, baseline, factor,
11066
		el = $( this ),
11067
		props0 = [ "position", "top", "bottom", "left", "right", "width", "height", "overflow", "opacity" ],
11068
11069
		// Always restore
11070
		props1 = [ "position", "top", "bottom", "left", "right", "overflow", "opacity" ],
11071
11072
		// Copy for children
11073
		props2 = [ "width", "height", "overflow" ],
11074
		cProps = [ "fontSize" ],
11075
		vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ],
11076
		hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ],
11077
11078
		// Set options
11079
		mode = $.effects.setMode( el, o.mode || "effect" ),
11080
		restore = o.restore || mode !== "effect",
11081
		scale = o.scale || "both",
11082
		origin = o.origin || [ "middle", "center" ],
11083
		position = el.css( "position" ),
11084
		props = restore ? props0 : props1,
11085
		zero = {
11086
			height: 0,
11087
			width: 0,
11088
			outerHeight: 0,
11089
			outerWidth: 0
11090
		};
11091
11092
	if ( mode === "show" ) {
11093
		el.show();
11094
	}
11095
	original = {
11096
		height: el.height(),
11097
		width: el.width(),
11098
		outerHeight: el.outerHeight(),
11099
		outerWidth: el.outerWidth()
11100
	};
11101
11102
	if ( o.mode === "toggle" && mode === "show" ) {
11103
		el.from = o.to || zero;
11104
		el.to = o.from || original;
11105
	} else {
11106
		el.from = o.from || ( mode === "show" ? zero : original );
11107
		el.to = o.to || ( mode === "hide" ? zero : original );
11108
	}
11109
11110
	// Set scaling factor
11111
	factor = {
11112
		from: {
11113
			y: el.from.height / original.height,
11114
			x: el.from.width / original.width
11115
		},
11116
		to: {
11117
			y: el.to.height / original.height,
11118
			x: el.to.width / original.width
11119
		}
11120
	};
11121
11122
	// Scale the css box
11123
	if ( scale === "box" || scale === "both" ) {
11124
11125
		// Vertical props scaling
11126
		if ( factor.from.y !== factor.to.y ) {
11127
			props = props.concat( vProps );
11128
			el.from = $.effects.setTransition( el, vProps, factor.from.y, el.from );
11129
			el.to = $.effects.setTransition( el, vProps, factor.to.y, el.to );
11130
		}
11131
11132
		// Horizontal props scaling
11133
		if ( factor.from.x !== factor.to.x ) {
11134
			props = props.concat( hProps );
11135
			el.from = $.effects.setTransition( el, hProps, factor.from.x, el.from );
11136
			el.to = $.effects.setTransition( el, hProps, factor.to.x, el.to );
11137
		}
11138
	}
11139
11140
	// Scale the content
11141
	if ( scale === "content" || scale === "both" ) {
11142
11143
		// Vertical props scaling
11144
		if ( factor.from.y !== factor.to.y ) {
11145
			props = props.concat( cProps ).concat( props2 );
11146
			el.from = $.effects.setTransition( el, cProps, factor.from.y, el.from );
11147
			el.to = $.effects.setTransition( el, cProps, factor.to.y, el.to );
11148
		}
11149
	}
11150
11151
	$.effects.save( el, props );
11152
	el.show();
11153
	$.effects.createWrapper( el );
11154
	el.css( "overflow", "hidden" ).css( el.from );
11155
11156
	// Adjust
11157
	if (origin) { // Calculate baseline shifts
11158
		baseline = $.effects.getBaseline( origin, original );
11159
		el.from.top = ( original.outerHeight - el.outerHeight() ) * baseline.y;
11160
		el.from.left = ( original.outerWidth - el.outerWidth() ) * baseline.x;
11161
		el.to.top = ( original.outerHeight - el.to.outerHeight ) * baseline.y;
11162
		el.to.left = ( original.outerWidth - el.to.outerWidth ) * baseline.x;
11163
	}
11164
	el.css( el.from ); // set top & left
11165
11166
	// Animate
11167
	if ( scale === "content" || scale === "both" ) { // Scale the children
11168
11169
		// Add margins/font-size
11170
		vProps = vProps.concat([ "marginTop", "marginBottom" ]).concat(cProps);
11171
		hProps = hProps.concat([ "marginLeft", "marginRight" ]);
11172
		props2 = props0.concat(vProps).concat(hProps);
11173
11174
		el.find( "*[width]" ).each( function(){
11175
			var child = $( this ),
11176
				c_original = {
11177
					height: child.height(),
11178
					width: child.width(),
11179
					outerHeight: child.outerHeight(),
11180
					outerWidth: child.outerWidth()
11181
				};
11182
			if (restore) {
11183
				$.effects.save(child, props2);
11184
			}
11185
11186
			child.from = {
11187
				height: c_original.height * factor.from.y,
11188
				width: c_original.width * factor.from.x,
11189
				outerHeight: c_original.outerHeight * factor.from.y,
11190
				outerWidth: c_original.outerWidth * factor.from.x
11191
			};
11192
			child.to = {
11193
				height: c_original.height * factor.to.y,
11194
				width: c_original.width * factor.to.x,
11195
				outerHeight: c_original.height * factor.to.y,
11196
				outerWidth: c_original.width * factor.to.x
11197
			};
11198
11199
			// Vertical props scaling
11200
			if ( factor.from.y !== factor.to.y ) {
11201
				child.from = $.effects.setTransition( child, vProps, factor.from.y, child.from );
11202
				child.to = $.effects.setTransition( child, vProps, factor.to.y, child.to );
11203
			}
11204
11205
			// Horizontal props scaling
11206
			if ( factor.from.x !== factor.to.x ) {
11207
				child.from = $.effects.setTransition( child, hProps, factor.from.x, child.from );
11208
				child.to = $.effects.setTransition( child, hProps, factor.to.x, child.to );
11209
			}
11210
11211
			// Animate children
11212
			child.css( child.from );
11213
			child.animate( child.to, o.duration, o.easing, function() {
11214
11215
				// Restore children
11216
				if ( restore ) {
11217
					$.effects.restore( child, props2 );
11218
				}
11219
			});
11220
		});
11221
	}
11222
11223
	// Animate
11224
	el.animate( el.to, {
11225
		queue: false,
11226
		duration: o.duration,
11227
		easing: o.easing,
11228
		complete: function() {
11229
			if ( el.to.opacity === 0 ) {
11230
				el.css( "opacity", el.from.opacity );
11231
			}
11232
			if( mode === "hide" ) {
11233
				el.hide();
11234
			}
11235
			$.effects.restore( el, props );
11236
			if ( !restore ) {
11237
11238
				// we need to calculate our new positioning based on the scaling
11239
				if ( position === "static" ) {
11240
					el.css({
11241
						position: "relative",
11242
						top: el.to.top,
11243
						left: el.to.left
11244
					});
11245
				} else {
11246
					$.each([ "top", "left" ], function( idx, pos ) {
11247
						el.css( pos, function( _, str ) {
11248
							var val = parseInt( str, 10 ),
11249
								toRef = idx ? el.to.left : el.to.top;
11250
11251
							// if original was "auto", recalculate the new value from wrapper
11252
							if ( str === "auto" ) {
11253
								return toRef + "px";
11254
							}
11255
11256
							return val + toRef + "px";
11257
						});
11258
					});
11259
				}
11260
			}
11261
11262
			$.effects.removeWrapper( el );
11263
			done();
11264
		}
11265
	});
11266
11267
};
11268
11269
})(jQuery);
11270
11271
(function( $, undefined ) {
11272
11273
$.effects.effect.shake = function( o, done ) {
11274
11275
	var el = $( this ),
11276
		props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
11277
		mode = $.effects.setMode( el, o.mode || "effect" ),
11278
		direction = o.direction || "left",
11279
		distance = o.distance || 20,
11280
		times = o.times || 3,
11281
		anims = times * 2 + 1,
11282
		speed = Math.round(o.duration/anims),
11283
		ref = (direction === "up" || direction === "down") ? "top" : "left",
11284
		positiveMotion = (direction === "up" || direction === "left"),
11285
		animation = {},
11286
		animation1 = {},
11287
		animation2 = {},
11288
		i,
11289
11290
		// we will need to re-assemble the queue to stack our animations in place
11291
		queue = el.queue(),
11292
		queuelen = queue.length;
11293
11294
	$.effects.save( el, props );
11295
	el.show();
11296
	$.effects.createWrapper( el );
11297
11298
	// Animation
11299
	animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance;
11300
	animation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2;
11301
	animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2;
11302
11303
	// Animate
11304
	el.animate( animation, speed, o.easing );
11305
11306
	// Shakes
11307
	for ( i = 1; i < times; i++ ) {
11308
		el.animate( animation1, speed, o.easing ).animate( animation2, speed, o.easing );
11309
	}
11310
	el
11311
		.animate( animation1, speed, o.easing )
11312
		.animate( animation, speed / 2, o.easing )
11313
		.queue(function() {
11314
			if ( mode === "hide" ) {
11315
				el.hide();
11316
			}
11317
			$.effects.restore( el, props );
11318
			$.effects.removeWrapper( el );
11319
			done();
11320
		});
11321
11322
	// inject all the animations we just queued to be first in line (after "inprogress")
11323
	if ( queuelen > 1) {
11324
		queue.splice.apply( queue,
11325
			[ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
11326
	}
11327
	el.dequeue();
11328
11329
};
11330
11331
})(jQuery);
11332
11333
(function( $, undefined ) {
11334
11335
$.effects.effect.slide = function( o, done ) {
11336
11337
	// Create element
11338
	var el = $( this ),
11339
		props = [ "position", "top", "bottom", "left", "right", "width", "height" ],
11340
		mode = $.effects.setMode( el, o.mode || "show" ),
11341
		show = mode === "show",
11342
		direction = o.direction || "left",
11343
		ref = (direction === "up" || direction === "down") ? "top" : "left",
11344
		positiveMotion = (direction === "up" || direction === "left"),
11345
		distance,
11346
		animation = {};
11347
11348
	// Adjust
11349
	$.effects.save( el, props );
11350
	el.show();
11351
	distance = o.distance || el[ ref === "top" ? "outerHeight" : "outerWidth" ]( true );
11352
11353
	$.effects.createWrapper( el ).css({
11354
		overflow: "hidden"
11355
	});
11356
11357
	if ( show ) {
11358
		el.css( ref, positiveMotion ? (isNaN(distance) ? "-" + distance : -distance) : distance );
11359
	}
11360
11361
	// Animation
11362
	animation[ ref ] = ( show ?
11363
		( positiveMotion ? "+=" : "-=") :
11364
		( positiveMotion ? "-=" : "+=")) +
11365
		distance;
11366
11367
	// Animate
11368
	el.animate( animation, {
11369
		queue: false,
11370
		duration: o.duration,
11371
		easing: o.easing,
11372
		complete: function() {
11373
			if ( mode === "hide" ) {
11374
				el.hide();
11375
			}
11376
			$.effects.restore( el, props );
11377
			$.effects.removeWrapper( el );
11378
			done();
11379
		}
11380
	});
11381
};
11382
11383
})(jQuery);
11384
11385
(function( $, undefined ) {
11386
11387
$.effects.effect.transfer = function( o, done ) {
11388
	var elem = $( this ),
11389
		target = $( o.to ),
11390
		targetFixed = target.css( "position" ) === "fixed",
11391
		body = $("body"),
11392
		fixTop = targetFixed ? body.scrollTop() : 0,
11393
		fixLeft = targetFixed ? body.scrollLeft() : 0,
11394
		endPosition = target.offset(),
11395
		animation = {
11396
			top: endPosition.top - fixTop ,
11397
			left: endPosition.left - fixLeft ,
11398
			height: target.innerHeight(),
11399
			width: target.innerWidth()
11400
		},
11401
		startPosition = elem.offset(),
11402
		transfer = $( "<div class='ui-effects-transfer'></div>" )
11403
			.appendTo( document.body )
11404
			.addClass( o.className )
11405
			.css({
11406
				top: startPosition.top - fixTop ,
11407
				left: startPosition.left - fixLeft ,
11408
				height: elem.innerHeight(),
11409
				width: elem.innerWidth(),
11410
				position: targetFixed ? "fixed" : "absolute"
11411
			})
11412
			.animate( animation, o.duration, o.easing, function() {
11413
				transfer.remove();
11414
				done();
11415
			});
11416
};
11417
11418
})(jQuery);
11419
11420
(function( $, undefined ) {
11421
11422
$.widget( "ui.menu", {
11423
	version: "1.10.3",
11424
	defaultElement: "<ul>",
11425
	delay: 300,
11426
	options: {
11427
		icons: {
11428
			submenu: "ui-icon-carat-1-e"
11429
		},
11430
		menus: "ul",
11431
		position: {
11432
			my: "left top",
11433
			at: "right top"
11434
		},
11435
		role: "menu",
11436
11437
		// callbacks
11438
		blur: null,
11439
		focus: null,
11440
		select: null
11441
	},
11442
11443
	_create: function() {
11444
		this.activeMenu = this.element;
11445
		// flag used to prevent firing of the click handler
11446
		// as the event bubbles up through nested menus
11447
		this.mouseHandled = false;
11448
		this.element
11449
			.uniqueId()
11450
			.addClass( "ui-menu ui-widget ui-widget-content ui-corner-all" )
11451
			.toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length )
11452
			.attr({
11453
				role: this.options.role,
11454
				tabIndex: 0
11455
			})
11456
			// need to catch all clicks on disabled menu
11457
			// not possible through _on
11458
			.bind( "click" + this.eventNamespace, $.proxy(function( event ) {
11459
				if ( this.options.disabled ) {
11460
					event.preventDefault();
11461
				}
11462
			}, this ));
11463
11464
		if ( this.options.disabled ) {
11465
			this.element
11466
				.addClass( "ui-state-disabled" )
11467
				.attr( "aria-disabled", "true" );
11468
		}
11469
11470
		this._on({
11471
			// Prevent focus from sticking to links inside menu after clicking
11472
			// them (focus should always stay on UL during navigation).
11473
			"mousedown .ui-menu-item > a": function( event ) {
11474
				event.preventDefault();
11475
			},
11476
			"click .ui-state-disabled > a": function( event ) {
11477
				event.preventDefault();
11478
			},
11479
			"click .ui-menu-item:has(a)": function( event ) {
11480
				var target = $( event.target ).closest( ".ui-menu-item" );
11481
				if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) {
11482
					this.mouseHandled = true;
11483
11484
					this.select( event );
11485
					// Open submenu on click
11486
					if ( target.has( ".ui-menu" ).length ) {
11487
						this.expand( event );
11488
					} else if ( !this.element.is( ":focus" ) ) {
11489
						// Redirect focus to the menu
11490
						this.element.trigger( "focus", [ true ] );
11491
11492
						// If the active item is on the top level, let it stay active.
11493
						// Otherwise, blur the active item since it is no longer visible.
11494
						if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) {
11495
							clearTimeout( this.timer );
11496
						}
11497
					}
11498
				}
11499
			},
11500
			"mouseenter .ui-menu-item": function( event ) {
11501
				var target = $( event.currentTarget );
11502
				// Remove ui-state-active class from siblings of the newly focused menu item
11503
				// to avoid a jump caused by adjacent elements both having a class with a border
11504
				target.siblings().children( ".ui-state-active" ).removeClass( "ui-state-active" );
11505
				this.focus( event, target );
11506
			},
11507
			mouseleave: "collapseAll",
11508
			"mouseleave .ui-menu": "collapseAll",
11509
			focus: function( event, keepActiveItem ) {
11510
				// If there's already an active item, keep it active
11511
				// If not, activate the first item
11512
				var item = this.active || this.element.children( ".ui-menu-item" ).eq( 0 );
11513
11514
				if ( !keepActiveItem ) {
11515
					this.focus( event, item );
11516
				}
11517
			},
11518
			blur: function( event ) {
11519
				this._delay(function() {
11520
					if ( !$.contains( this.element[0], this.document[0].activeElement ) ) {
11521
						this.collapseAll( event );
11522
					}
11523
				});
11524
			},
11525
			keydown: "_keydown"
11526
		});
11527
11528
		this.refresh();
11529
11530
		// Clicks outside of a menu collapse any open menus
11531
		this._on( this.document, {
11532
			click: function( event ) {
11533
				if ( !$( event.target ).closest( ".ui-menu" ).length ) {
11534
					this.collapseAll( event );
11535
				}
11536
11537
				// Reset the mouseHandled flag
11538
				this.mouseHandled = false;
11539
			}
11540
		});
11541
	},
11542
11543
	_destroy: function() {
11544
		// Destroy (sub)menus
11545
		this.element
11546
			.removeAttr( "aria-activedescendant" )
11547
			.find( ".ui-menu" ).addBack()
11548
				.removeClass( "ui-menu ui-widget ui-widget-content ui-corner-all ui-menu-icons" )
11549
				.removeAttr( "role" )
11550
				.removeAttr( "tabIndex" )
11551
				.removeAttr( "aria-labelledby" )
11552
				.removeAttr( "aria-expanded" )
11553
				.removeAttr( "aria-hidden" )
11554
				.removeAttr( "aria-disabled" )
11555
				.removeUniqueId()
11556
				.show();
11557
11558
		// Destroy menu items
11559
		this.element.find( ".ui-menu-item" )
11560
			.removeClass( "ui-menu-item" )
11561
			.removeAttr( "role" )
11562
			.removeAttr( "aria-disabled" )
11563
			.children( "a" )
11564
				.removeUniqueId()
11565
				.removeClass( "ui-corner-all ui-state-hover" )
11566
				.removeAttr( "tabIndex" )
11567
				.removeAttr( "role" )
11568
				.removeAttr( "aria-haspopup" )
11569
				.children().each( function() {
11570
					var elem = $( this );
11571
					if ( elem.data( "ui-menu-submenu-carat" ) ) {
11572
						elem.remove();
11573
					}
11574
				});
11575
11576
		// Destroy menu dividers
11577
		this.element.find( ".ui-menu-divider" ).removeClass( "ui-menu-divider ui-widget-content" );
11578
	},
11579
11580
	_keydown: function( event ) {
11581
		/*jshint maxcomplexity:20*/
11582
		var match, prev, character, skip, regex,
11583
			preventDefault = true;
11584
11585
		function escape( value ) {
11586
			return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" );
11587
		}
11588
11589
		switch ( event.keyCode ) {
11590
		case $.ui.keyCode.PAGE_UP:
11591
			this.previousPage( event );
11592
			break;
11593
		case $.ui.keyCode.PAGE_DOWN:
11594
			this.nextPage( event );
11595
			break;
11596
		case $.ui.keyCode.HOME:
11597
			this._move( "first", "first", event );
11598
			break;
11599
		case $.ui.keyCode.END:
11600
			this._move( "last", "last", event );
11601
			break;
11602
		case $.ui.keyCode.UP:
11603
			this.previous( event );
11604
			break;
11605
		case $.ui.keyCode.DOWN:
11606
			this.next( event );
11607
			break;
11608
		case $.ui.keyCode.LEFT:
11609
			this.collapse( event );
11610
			break;
11611
		case $.ui.keyCode.RIGHT:
11612
			if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
11613
				this.expand( event );
11614
			}
11615
			break;
11616
		case $.ui.keyCode.ENTER:
11617
		case $.ui.keyCode.SPACE:
11618
			this._activate( event );
11619
			break;
11620
		case $.ui.keyCode.ESCAPE:
11621
			this.collapse( event );
11622
			break;
11623
		default:
11624
			preventDefault = false;
11625
			prev = this.previousFilter || "";
11626
			character = String.fromCharCode( event.keyCode );
11627
			skip = false;
11628
11629
			clearTimeout( this.filterTimer );
11630
11631
			if ( character === prev ) {
11632
				skip = true;
11633
			} else {
11634
				character = prev + character;
11635
			}
11636
11637
			regex = new RegExp( "^" + escape( character ), "i" );
11638
			match = this.activeMenu.children( ".ui-menu-item" ).filter(function() {
11639
				return regex.test( $( this ).children( "a" ).text() );
11640
			});
11641
			match = skip && match.index( this.active.next() ) !== -1 ?
11642
				this.active.nextAll( ".ui-menu-item" ) :
11643
				match;
11644
11645
			// If no matches on the current filter, reset to the last character pressed
11646
			// to move down the menu to the first item that starts with that character
11647
			if ( !match.length ) {
11648
				character = String.fromCharCode( event.keyCode );
11649
				regex = new RegExp( "^" + escape( character ), "i" );
11650
				match = this.activeMenu.children( ".ui-menu-item" ).filter(function() {
11651
					return regex.test( $( this ).children( "a" ).text() );
11652
				});
11653
			}
11654
11655
			if ( match.length ) {
11656
				this.focus( event, match );
11657
				if ( match.length > 1 ) {
11658
					this.previousFilter = character;
11659
					this.filterTimer = this._delay(function() {
11660
						delete this.previousFilter;
11661
					}, 1000 );
11662
				} else {
11663
					delete this.previousFilter;
11664
				}
11665
			} else {
11666
				delete this.previousFilter;
11667
			}
11668
		}
11669
11670
		if ( preventDefault ) {
11671
			event.preventDefault();
11672
		}
11673
	},
11674
11675
	_activate: function( event ) {
11676
		if ( !this.active.is( ".ui-state-disabled" ) ) {
11677
			if ( this.active.children( "a[aria-haspopup='true']" ).length ) {
11678
				this.expand( event );
11679
			} else {
11680
				this.select( event );
11681
			}
11682
		}
11683
	},
11684
11685
	refresh: function() {
11686
		var menus,
11687
			icon = this.options.icons.submenu,
11688
			submenus = this.element.find( this.options.menus );
11689
11690
		// Initialize nested menus
11691
		submenus.filter( ":not(.ui-menu)" )
11692
			.addClass( "ui-menu ui-widget ui-widget-content ui-corner-all" )
11693
			.hide()
11694
			.attr({
11695
				role: this.options.role,
11696
				"aria-hidden": "true",
11697
				"aria-expanded": "false"
11698
			})
11699
			.each(function() {
11700
				var menu = $( this ),
11701
					item = menu.prev( "a" ),
11702
					submenuCarat = $( "<span>" )
11703
						.addClass( "ui-menu-icon ui-icon " + icon )
11704
						.data( "ui-menu-submenu-carat", true );
11705
11706
				item
11707
					.attr( "aria-haspopup", "true" )
11708
					.prepend( submenuCarat );
11709
				menu.attr( "aria-labelledby", item.attr( "id" ) );
11710
			});
11711
11712
		menus = submenus.add( this.element );
11713
11714
		// Don't refresh list items that are already adapted
11715
		menus.children( ":not(.ui-menu-item):has(a)" )
11716
			.addClass( "ui-menu-item" )
11717
			.attr( "role", "presentation" )
11718
			.children( "a" )
11719
				.uniqueId()
11720
				.addClass( "ui-corner-all" )
11721
				.attr({
11722
					tabIndex: -1,
11723
					role: this._itemRole()
11724
				});
11725
11726
		// Initialize unlinked menu-items containing spaces and/or dashes only as dividers
11727
		menus.children( ":not(.ui-menu-item)" ).each(function() {
11728
			var item = $( this );
11729
			// hyphen, em dash, en dash
11730
			if ( !/[^\-\u2014\u2013\s]/.test( item.text() ) ) {
11731
				item.addClass( "ui-widget-content ui-menu-divider" );
11732
			}
11733
		});
11734
11735
		// Add aria-disabled attribute to any disabled menu item
11736
		menus.children( ".ui-state-disabled" ).attr( "aria-disabled", "true" );
11737
11738
		// If the active item has been removed, blur the menu
11739
		if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
11740
			this.blur();
11741
		}
11742
	},
11743
11744
	_itemRole: function() {
11745
		return {
11746
			menu: "menuitem",
11747
			listbox: "option"
11748
		}[ this.options.role ];
11749
	},
11750
11751
	_setOption: function( key, value ) {
11752
		if ( key === "icons" ) {
11753
			this.element.find( ".ui-menu-icon" )
11754
				.removeClass( this.options.icons.submenu )
11755
				.addClass( value.submenu );
11756
		}
11757
		this._super( key, value );
11758
	},
11759
11760
	focus: function( event, item ) {
11761
		var nested, focused;
11762
		this.blur( event, event && event.type === "focus" );
11763
11764
		this._scrollIntoView( item );
11765
11766
		this.active = item.first();
11767
		focused = this.active.children( "a" ).addClass( "ui-state-focus" );
11768
		// Only update aria-activedescendant if there's a role
11769
		// otherwise we assume focus is managed elsewhere
11770
		if ( this.options.role ) {
11771
			this.element.attr( "aria-activedescendant", focused.attr( "id" ) );
11772
		}
11773
11774
		// Highlight active parent menu item, if any
11775
		this.active
11776
			.parent()
11777
			.closest( ".ui-menu-item" )
11778
			.children( "a:first" )
11779
			.addClass( "ui-state-active" );
11780
11781
		if ( event && event.type === "keydown" ) {
11782
			this._close();
11783
		} else {
11784
			this.timer = this._delay(function() {
11785
				this._close();
11786
			}, this.delay );
11787
		}
11788
11789
		nested = item.children( ".ui-menu" );
11790
		if ( nested.length && ( /^mouse/.test( event.type ) ) ) {
11791
			this._startOpening(nested);
11792
		}
11793
		this.activeMenu = item.parent();
11794
11795
		this._trigger( "focus", event, { item: item } );
11796
	},
11797
11798
	_scrollIntoView: function( item ) {
11799
		var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight;
11800
		if ( this._hasScroll() ) {
11801
			borderTop = parseFloat( $.css( this.activeMenu[0], "borderTopWidth" ) ) || 0;
11802
			paddingTop = parseFloat( $.css( this.activeMenu[0], "paddingTop" ) ) || 0;
11803
			offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop;
11804
			scroll = this.activeMenu.scrollTop();
11805
			elementHeight = this.activeMenu.height();
11806
			itemHeight = item.height();
11807
11808
			if ( offset < 0 ) {
11809
				this.activeMenu.scrollTop( scroll + offset );
11810
			} else if ( offset + itemHeight > elementHeight ) {
11811
				this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight );
11812
			}
11813
		}
11814
	},
11815
11816
	blur: function( event, fromFocus ) {
11817
		if ( !fromFocus ) {
11818
			clearTimeout( this.timer );
11819
		}
11820
11821
		if ( !this.active ) {
11822
			return;
11823
		}
11824
11825
		this.active.children( "a" ).removeClass( "ui-state-focus" );
11826
		this.active = null;
11827
11828
		this._trigger( "blur", event, { item: this.active } );
11829
	},
11830
11831
	_startOpening: function( submenu ) {
11832
		clearTimeout( this.timer );
11833
11834
		// Don't open if already open fixes a Firefox bug that caused a .5 pixel
11835
		// shift in the submenu position when mousing over the carat icon
11836
		if ( submenu.attr( "aria-hidden" ) !== "true" ) {
11837
			return;
11838
		}
11839
11840
		this.timer = this._delay(function() {
11841
			this._close();
11842
			this._open( submenu );
11843
		}, this.delay );
11844
	},
11845
11846
	_open: function( submenu ) {
11847
		var position = $.extend({
11848
			of: this.active
11849
		}, this.options.position );
11850
11851
		clearTimeout( this.timer );
11852
		this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) )
11853
			.hide()
11854
			.attr( "aria-hidden", "true" );
11855
11856
		submenu
11857
			.show()
11858
			.removeAttr( "aria-hidden" )
11859
			.attr( "aria-expanded", "true" )
11860
			.position( position );
11861
	},
11862
11863
	collapseAll: function( event, all ) {
11864
		clearTimeout( this.timer );
11865
		this.timer = this._delay(function() {
11866
			// If we were passed an event, look for the submenu that contains the event
11867
			var currentMenu = all ? this.element :
11868
				$( event && event.target ).closest( this.element.find( ".ui-menu" ) );
11869
11870
			// If we found no valid submenu ancestor, use the main menu to close all sub menus anyway
11871
			if ( !currentMenu.length ) {
11872
				currentMenu = this.element;
11873
			}
11874
11875
			this._close( currentMenu );
11876
11877
			this.blur( event );
11878
			this.activeMenu = currentMenu;
11879
		}, this.delay );
11880
	},
11881
11882
	// With no arguments, closes the currently active menu - if nothing is active
11883
	// it closes all menus.  If passed an argument, it will search for menus BELOW
11884
	_close: function( startMenu ) {
11885
		if ( !startMenu ) {
11886
			startMenu = this.active ? this.active.parent() : this.element;
11887
		}
11888
11889
		startMenu
11890
			.find( ".ui-menu" )
11891
				.hide()
11892
				.attr( "aria-hidden", "true" )
11893
				.attr( "aria-expanded", "false" )
11894
			.end()
11895
			.find( "a.ui-state-active" )
11896
				.removeClass( "ui-state-active" );
11897
	},
11898
11899
	collapse: function( event ) {
11900
		var newItem = this.active &&
11901
			this.active.parent().closest( ".ui-menu-item", this.element );
11902
		if ( newItem && newItem.length ) {
11903
			this._close();
11904
			this.focus( event, newItem );
11905
		}
11906
	},
11907
11908
	expand: function( event ) {
11909
		var newItem = this.active &&
11910
			this.active
11911
				.children( ".ui-menu " )
11912
				.children( ".ui-menu-item" )
11913
				.first();
11914
11915
		if ( newItem && newItem.length ) {
11916
			this._open( newItem.parent() );
11917
11918
			// Delay so Firefox will not hide activedescendant change in expanding submenu from AT
11919
			this._delay(function() {
11920
				this.focus( event, newItem );
11921
			});
11922
		}
11923
	},
11924
11925
	next: function( event ) {
11926
		this._move( "next", "first", event );
11927
	},
11928
11929
	previous: function( event ) {
11930
		this._move( "prev", "last", event );
11931
	},
11932
11933
	isFirstItem: function() {
11934
		return this.active && !this.active.prevAll( ".ui-menu-item" ).length;
11935
	},
11936
11937
	isLastItem: function() {
11938
		return this.active && !this.active.nextAll( ".ui-menu-item" ).length;
11939
	},
11940
11941
	_move: function( direction, filter, event ) {
11942
		var next;
11943
		if ( this.active ) {
11944
			if ( direction === "first" || direction === "last" ) {
11945
				next = this.active
11946
					[ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" )
11947
					.eq( -1 );
11948
			} else {
11949
				next = this.active
11950
					[ direction + "All" ]( ".ui-menu-item" )
11951
					.eq( 0 );
11952
			}
11953
		}
11954
		if ( !next || !next.length || !this.active ) {
11955
			next = this.activeMenu.children( ".ui-menu-item" )[ filter ]();
11956
		}
11957
11958
		this.focus( event, next );
11959
	},
11960
11961
	nextPage: function( event ) {
11962
		var item, base, height;
11963
11964
		if ( !this.active ) {
11965
			this.next( event );
11966
			return;
11967
		}
11968
		if ( this.isLastItem() ) {
11969
			return;
11970
		}
11971
		if ( this._hasScroll() ) {
11972
			base = this.active.offset().top;
11973
			height = this.element.height();
11974
			this.active.nextAll( ".ui-menu-item" ).each(function() {
11975
				item = $( this );
11976
				return item.offset().top - base - height < 0;
11977
			});
11978
11979
			this.focus( event, item );
11980
		} else {
11981
			this.focus( event, this.activeMenu.children( ".ui-menu-item" )
11982
				[ !this.active ? "first" : "last" ]() );
11983
		}
11984
	},
11985
11986
	previousPage: function( event ) {
11987
		var item, base, height;
11988
		if ( !this.active ) {
11989
			this.next( event );
11990
			return;
11991
		}
11992
		if ( this.isFirstItem() ) {
11993
			return;
11994
		}
11995
		if ( this._hasScroll() ) {
11996
			base = this.active.offset().top;
11997
			height = this.element.height();
11998
			this.active.prevAll( ".ui-menu-item" ).each(function() {
11999
				item = $( this );
12000
				return item.offset().top - base + height > 0;
12001
			});
12002
12003
			this.focus( event, item );
12004
		} else {
12005
			this.focus( event, this.activeMenu.children( ".ui-menu-item" ).first() );
12006
		}
12007
	},
12008
12009
	_hasScroll: function() {
12010
		return this.element.outerHeight() < this.element.prop( "scrollHeight" );
12011
	},
12012
12013
	select: function( event ) {
12014
		// TODO: It should never be possible to not have an active item at this
12015
		// point, but the tests don't trigger mouseenter before click.
12016
		this.active = this.active || $( event.target ).closest( ".ui-menu-item" );
12017
		var ui = { item: this.active };
12018
		if ( !this.active.has( ".ui-menu" ).length ) {
12019
			this.collapseAll( event, true );
12020
		}
12021
		this._trigger( "select", event, ui );
12022
	}
12023
});
12024
12025
}( jQuery ));
12026
12027
(function( $, undefined ) {
12028
12029
$.ui = $.ui || {};
12030
12031
var cachedScrollbarWidth,
12032
	max = Math.max,
12033
	abs = Math.abs,
12034
	round = Math.round,
12035
	rhorizontal = /left|center|right/,
12036
	rvertical = /top|center|bottom/,
12037
	roffset = /[\+\-]\d+(\.[\d]+)?%?/,
12038
	rposition = /^\w+/,
12039
	rpercent = /%$/,
12040
	_position = $.fn.position;
12041
12042
function getOffsets( offsets, width, height ) {
12043
	return [
12044
		parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),
12045
		parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )
12046
	];
12047
}
12048
12049
function parseCss( element, property ) {
12050
	return parseInt( $.css( element, property ), 10 ) || 0;
12051
}
12052
12053
function getDimensions( elem ) {
12054
	var raw = elem[0];
12055
	if ( raw.nodeType === 9 ) {
12056
		return {
12057
			width: elem.width(),
12058
			height: elem.height(),
12059
			offset: { top: 0, left: 0 }
12060
		};
12061
	}
12062
	if ( $.isWindow( raw ) ) {
12063
		return {
12064
			width: elem.width(),
12065
			height: elem.height(),
12066
			offset: { top: elem.scrollTop(), left: elem.scrollLeft() }
12067
		};
12068
	}
12069
	if ( raw.preventDefault ) {
12070
		return {
12071
			width: 0,
12072
			height: 0,
12073
			offset: { top: raw.pageY, left: raw.pageX }
12074
		};
12075
	}
12076
	return {
12077
		width: elem.outerWidth(),
12078
		height: elem.outerHeight(),
12079
		offset: elem.offset()
12080
	};
12081
}
12082
12083
$.position = {
12084
	scrollbarWidth: function() {
12085
		if ( cachedScrollbarWidth !== undefined ) {
12086
			return cachedScrollbarWidth;
12087
		}
12088
		var w1, w2,
12089
			div = $( "<div style='display:block;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>" ),
12090
			innerDiv = div.children()[0];
12091
12092
		$( "body" ).append( div );
12093
		w1 = innerDiv.offsetWidth;
12094
		div.css( "overflow", "scroll" );
12095
12096
		w2 = innerDiv.offsetWidth;
12097
12098
		if ( w1 === w2 ) {
12099
			w2 = div[0].clientWidth;
12100
		}
12101
12102
		div.remove();
12103
12104
		return (cachedScrollbarWidth = w1 - w2);
12105
	},
12106
	getScrollInfo: function( within ) {
12107
		var overflowX = within.isWindow ? "" : within.element.css( "overflow-x" ),
12108
			overflowY = within.isWindow ? "" : within.element.css( "overflow-y" ),
12109
			hasOverflowX = overflowX === "scroll" ||
12110
				( overflowX === "auto" && within.width < within.element[0].scrollWidth ),
12111
			hasOverflowY = overflowY === "scroll" ||
12112
				( overflowY === "auto" && within.height < within.element[0].scrollHeight );
12113
		return {
12114
			width: hasOverflowY ? $.position.scrollbarWidth() : 0,
12115
			height: hasOverflowX ? $.position.scrollbarWidth() : 0
12116
		};
12117
	},
12118
	getWithinInfo: function( element ) {
12119
		var withinElement = $( element || window ),
12120
			isWindow = $.isWindow( withinElement[0] );
12121
		return {
12122
			element: withinElement,
12123
			isWindow: isWindow,
12124
			offset: withinElement.offset() || { left: 0, top: 0 },
12125
			scrollLeft: withinElement.scrollLeft(),
12126
			scrollTop: withinElement.scrollTop(),
12127
			width: isWindow ? withinElement.width() : withinElement.outerWidth(),
12128
			height: isWindow ? withinElement.height() : withinElement.outerHeight()
12129
		};
12130
	}
12131
};
12132
12133
$.fn.position = function( options ) {
12134
	if ( !options || !options.of ) {
12135
		return _position.apply( this, arguments );
12136
	}
12137
12138
	// make a copy, we don't want to modify arguments
12139
	options = $.extend( {}, options );
12140
12141
	var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,
12142
		target = $( options.of ),
12143
		within = $.position.getWithinInfo( options.within ),
12144
		scrollInfo = $.position.getScrollInfo( within ),
12145
		collision = ( options.collision || "flip" ).split( " " ),
12146
		offsets = {};
12147
12148
	dimensions = getDimensions( target );
12149
	if ( target[0].preventDefault ) {
12150
		// force left top to allow flipping
12151
		options.at = "left top";
12152
	}
12153
	targetWidth = dimensions.width;
12154
	targetHeight = dimensions.height;
12155
	targetOffset = dimensions.offset;
12156
	// clone to reuse original targetOffset later
12157
	basePosition = $.extend( {}, targetOffset );
12158
12159
	// force my and at to have valid horizontal and vertical positions
12160
	// if a value is missing or invalid, it will be converted to center
12161
	$.each( [ "my", "at" ], function() {
12162
		var pos = ( options[ this ] || "" ).split( " " ),
12163
			horizontalOffset,
12164
			verticalOffset;
12165
12166
		if ( pos.length === 1) {
12167
			pos = rhorizontal.test( pos[ 0 ] ) ?
12168
				pos.concat( [ "center" ] ) :
12169
				rvertical.test( pos[ 0 ] ) ?
12170
					[ "center" ].concat( pos ) :
12171
					[ "center", "center" ];
12172
		}
12173
		pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center";
12174
		pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";
12175
12176
		// calculate offsets
12177
		horizontalOffset = roffset.exec( pos[ 0 ] );
12178
		verticalOffset = roffset.exec( pos[ 1 ] );
12179
		offsets[ this ] = [
12180
			horizontalOffset ? horizontalOffset[ 0 ] : 0,
12181
			verticalOffset ? verticalOffset[ 0 ] : 0
12182
		];
12183
12184
		// reduce to just the positions without the offsets
12185
		options[ this ] = [
12186
			rposition.exec( pos[ 0 ] )[ 0 ],
12187
			rposition.exec( pos[ 1 ] )[ 0 ]
12188
		];
12189
	});
12190
12191
	// normalize collision option
12192
	if ( collision.length === 1 ) {
12193
		collision[ 1 ] = collision[ 0 ];
12194
	}
12195
12196
	if ( options.at[ 0 ] === "right" ) {
12197
		basePosition.left += targetWidth;
12198
	} else if ( options.at[ 0 ] === "center" ) {
12199
		basePosition.left += targetWidth / 2;
12200
	}
12201
12202
	if ( options.at[ 1 ] === "bottom" ) {
12203
		basePosition.top += targetHeight;
12204
	} else if ( options.at[ 1 ] === "center" ) {
12205
		basePosition.top += targetHeight / 2;
12206
	}
12207
12208
	atOffset = getOffsets( offsets.at, targetWidth, targetHeight );
12209
	basePosition.left += atOffset[ 0 ];
12210
	basePosition.top += atOffset[ 1 ];
12211
12212
	return this.each(function() {
12213
		var collisionPosition, using,
12214
			elem = $( this ),
12215
			elemWidth = elem.outerWidth(),
12216
			elemHeight = elem.outerHeight(),
12217
			marginLeft = parseCss( this, "marginLeft" ),
12218
			marginTop = parseCss( this, "marginTop" ),
12219
			collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) + scrollInfo.width,
12220
			collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) + scrollInfo.height,
12221
			position = $.extend( {}, basePosition ),
12222
			myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );
12223
12224
		if ( options.my[ 0 ] === "right" ) {
12225
			position.left -= elemWidth;
12226
		} else if ( options.my[ 0 ] === "center" ) {
12227
			position.left -= elemWidth / 2;
12228
		}
12229
12230
		if ( options.my[ 1 ] === "bottom" ) {
12231
			position.top -= elemHeight;
12232
		} else if ( options.my[ 1 ] === "center" ) {
12233
			position.top -= elemHeight / 2;
12234
		}
12235
12236
		position.left += myOffset[ 0 ];
12237
		position.top += myOffset[ 1 ];
12238
12239
		// if the browser doesn't support fractions, then round for consistent results
12240
		if ( !$.support.offsetFractions ) {
12241
			position.left = round( position.left );
12242
			position.top = round( position.top );
12243
		}
12244
12245
		collisionPosition = {
12246
			marginLeft: marginLeft,
12247
			marginTop: marginTop
12248
		};
12249
12250
		$.each( [ "left", "top" ], function( i, dir ) {
12251
			if ( $.ui.position[ collision[ i ] ] ) {
12252
				$.ui.position[ collision[ i ] ][ dir ]( position, {
12253
					targetWidth: targetWidth,
12254
					targetHeight: targetHeight,
12255
					elemWidth: elemWidth,
12256
					elemHeight: elemHeight,
12257
					collisionPosition: collisionPosition,
12258
					collisionWidth: collisionWidth,
12259
					collisionHeight: collisionHeight,
12260
					offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],
12261
					my: options.my,
12262
					at: options.at,
12263
					within: within,
12264
					elem : elem
12265
				});
12266
			}
12267
		});
12268
12269
		if ( options.using ) {
12270
			// adds feedback as second argument to using callback, if present
12271
			using = function( props ) {
12272
				var left = targetOffset.left - position.left,
12273
					right = left + targetWidth - elemWidth,
12274
					top = targetOffset.top - position.top,
12275
					bottom = top + targetHeight - elemHeight,
12276
					feedback = {
12277
						target: {
12278
							element: target,
12279
							left: targetOffset.left,
12280
							top: targetOffset.top,
12281
							width: targetWidth,
12282
							height: targetHeight
12283
						},
12284
						element: {
12285
							element: elem,
12286
							left: position.left,
12287
							top: position.top,
12288
							width: elemWidth,
12289
							height: elemHeight
12290
						},
12291
						horizontal: right < 0 ? "left" : left > 0 ? "right" : "center",
12292
						vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle"
12293
					};
12294
				if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {
12295
					feedback.horizontal = "center";
12296
				}
12297
				if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {
12298
					feedback.vertical = "middle";
12299
				}
12300
				if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {
12301
					feedback.important = "horizontal";
12302
				} else {
12303
					feedback.important = "vertical";
12304
				}
12305
				options.using.call( this, props, feedback );
12306
			};
12307
		}
12308
12309
		elem.offset( $.extend( position, { using: using } ) );
12310
	});
12311
};
12312
12313
$.ui.position = {
12314
	fit: {
12315
		left: function( position, data ) {
12316
			var within = data.within,
12317
				withinOffset = within.isWindow ? within.scrollLeft : within.offset.left,
12318
				outerWidth = within.width,
12319
				collisionPosLeft = position.left - data.collisionPosition.marginLeft,
12320
				overLeft = withinOffset - collisionPosLeft,
12321
				overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
12322
				newOverRight;
12323
12324
			// element is wider than within
12325
			if ( data.collisionWidth > outerWidth ) {
12326
				// element is initially over the left side of within
12327
				if ( overLeft > 0 && overRight <= 0 ) {
12328
					newOverRight = position.left + overLeft + data.collisionWidth - outerWidth - withinOffset;
12329
					position.left += overLeft - newOverRight;
12330
				// element is initially over right side of within
12331
				} else if ( overRight > 0 && overLeft <= 0 ) {
12332
					position.left = withinOffset;
12333
				// element is initially over both left and right sides of within
12334
				} else {
12335
					if ( overLeft > overRight ) {
12336
						position.left = withinOffset + outerWidth - data.collisionWidth;
12337
					} else {
12338
						position.left = withinOffset;
12339
					}
12340
				}
12341
			// too far left -> align with left edge
12342
			} else if ( overLeft > 0 ) {
12343
				position.left += overLeft;
12344
			// too far right -> align with right edge
12345
			} else if ( overRight > 0 ) {
12346
				position.left -= overRight;
12347
			// adjust based on position and margin
12348
			} else {
12349
				position.left = max( position.left - collisionPosLeft, position.left );
12350
			}
12351
		},
12352
		top: function( position, data ) {
12353
			var within = data.within,
12354
				withinOffset = within.isWindow ? within.scrollTop : within.offset.top,
12355
				outerHeight = data.within.height,
12356
				collisionPosTop = position.top - data.collisionPosition.marginTop,
12357
				overTop = withinOffset - collisionPosTop,
12358
				overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
12359
				newOverBottom;
12360
12361
			// element is taller than within
12362
			if ( data.collisionHeight > outerHeight ) {
12363
				// element is initially over the top of within
12364
				if ( overTop > 0 && overBottom <= 0 ) {
12365
					newOverBottom = position.top + overTop + data.collisionHeight - outerHeight - withinOffset;
12366
					position.top += overTop - newOverBottom;
12367
				// element is initially over bottom of within
12368
				} else if ( overBottom > 0 && overTop <= 0 ) {
12369
					position.top = withinOffset;
12370
				// element is initially over both top and bottom of within
12371
				} else {
12372
					if ( overTop > overBottom ) {
12373
						position.top = withinOffset + outerHeight - data.collisionHeight;
12374
					} else {
12375
						position.top = withinOffset;
12376
					}
12377
				}
12378
			// too far up -> align with top
12379
			} else if ( overTop > 0 ) {
12380
				position.top += overTop;
12381
			// too far down -> align with bottom edge
12382
			} else if ( overBottom > 0 ) {
12383
				position.top -= overBottom;
12384
			// adjust based on position and margin
12385
			} else {
12386
				position.top = max( position.top - collisionPosTop, position.top );
12387
			}
12388
		}
12389
	},
12390
	flip: {
12391
		left: function( position, data ) {
12392
			var within = data.within,
12393
				withinOffset = within.offset.left + within.scrollLeft,
12394
				outerWidth = within.width,
12395
				offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,
12396
				collisionPosLeft = position.left - data.collisionPosition.marginLeft,
12397
				overLeft = collisionPosLeft - offsetLeft,
12398
				overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,
12399
				myOffset = data.my[ 0 ] === "left" ?
12400
					-data.elemWidth :
12401
					data.my[ 0 ] === "right" ?
12402
						data.elemWidth :
12403
						0,
12404
				atOffset = data.at[ 0 ] === "left" ?
12405
					data.targetWidth :
12406
					data.at[ 0 ] === "right" ?
12407
						-data.targetWidth :
12408
						0,
12409
				offset = -2 * data.offset[ 0 ],
12410
				newOverRight,
12411
				newOverLeft;
12412
12413
			if ( overLeft < 0 ) {
12414
				newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - outerWidth - withinOffset;
12415
				if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {
12416
					position.left += myOffset + atOffset + offset;
12417
				}
12418
			}
12419
			else if ( overRight > 0 ) {
12420
				newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + atOffset + offset - offsetLeft;
12421
				if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {
12422
					position.left += myOffset + atOffset + offset;
12423
				}
12424
			}
12425
		},
12426
		top: function( position, data ) {
12427
			var within = data.within,
12428
				withinOffset = within.offset.top + within.scrollTop,
12429
				outerHeight = within.height,
12430
				offsetTop = within.isWindow ? within.scrollTop : within.offset.top,
12431
				collisionPosTop = position.top - data.collisionPosition.marginTop,
12432
				overTop = collisionPosTop - offsetTop,
12433
				overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,
12434
				top = data.my[ 1 ] === "top",
12435
				myOffset = top ?
12436
					-data.elemHeight :
12437
					data.my[ 1 ] === "bottom" ?
12438
						data.elemHeight :
12439
						0,
12440
				atOffset = data.at[ 1 ] === "top" ?
12441
					data.targetHeight :
12442
					data.at[ 1 ] === "bottom" ?
12443
						-data.targetHeight :
12444
						0,
12445
				offset = -2 * data.offset[ 1 ],
12446
				newOverTop,
12447
				newOverBottom;
12448
			if ( overTop < 0 ) {
12449
				newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - outerHeight - withinOffset;
12450
				if ( ( position.top + myOffset + atOffset + offset) > overTop && ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) ) {
12451
					position.top += myOffset + atOffset + offset;
12452
				}
12453
			}
12454
			else if ( overBottom > 0 ) {
12455
				newOverTop = position.top -  data.collisionPosition.marginTop + myOffset + atOffset + offset - offsetTop;
12456
				if ( ( position.top + myOffset + atOffset + offset) > overBottom && ( newOverTop > 0 || abs( newOverTop ) < overBottom ) ) {
12457
					position.top += myOffset + atOffset + offset;
12458
				}
12459
			}
12460
		}
12461
	},
12462
	flipfit: {
12463
		left: function() {
12464
			$.ui.position.flip.left.apply( this, arguments );
12465
			$.ui.position.fit.left.apply( this, arguments );
12466
		},
12467
		top: function() {
12468
			$.ui.position.flip.top.apply( this, arguments );
12469
			$.ui.position.fit.top.apply( this, arguments );
12470
		}
12471
	}
12472
};
12473
12474
// fraction support test
12475
(function () {
12476
	var testElement, testElementParent, testElementStyle, offsetLeft, i,
12477
		body = document.getElementsByTagName( "body" )[ 0 ],
12478
		div = document.createElement( "div" );
12479
12480
	//Create a "fake body" for testing based on method used in jQuery.support
12481
	testElement = document.createElement( body ? "div" : "body" );
12482
	testElementStyle = {
12483
		visibility: "hidden",
12484
		width: 0,
12485
		height: 0,
12486
		border: 0,
12487
		margin: 0,
12488
		background: "none"
12489
	};
12490
	if ( body ) {
12491
		$.extend( testElementStyle, {
12492
			position: "absolute",
12493
			left: "-1000px",
12494
			top: "-1000px"
12495
		});
12496
	}
12497
	for ( i in testElementStyle ) {
12498
		testElement.style[ i ] = testElementStyle[ i ];
12499
	}
12500
	testElement.appendChild( div );
12501
	testElementParent = body || document.documentElement;
12502
	testElementParent.insertBefore( testElement, testElementParent.firstChild );
12503
12504
	div.style.cssText = "position: absolute; left: 10.7432222px;";
12505
12506
	offsetLeft = $( div ).offset().left;
12507
	$.support.offsetFractions = offsetLeft > 10 && offsetLeft < 11;
12508
12509
	testElement.innerHTML = "";
12510
	testElementParent.removeChild( testElement );
12511
})();
12512
12513
}( jQuery ) );
12514
12515
(function( $, undefined ) {
12516
12517
$.widget( "ui.progressbar", {
12518
	version: "1.10.3",
12519
	options: {
12520
		max: 100,
12521
		value: 0,
12522
12523
		change: null,
12524
		complete: null
12525
	},
12526
12527
	min: 0,
12528
12529
	_create: function() {
12530
		// Constrain initial value
12531
		this.oldValue = this.options.value = this._constrainedValue();
12532
12533
		this.element
12534
			.addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
12535
			.attr({
12536
				// Only set static values, aria-valuenow and aria-valuemax are
12537
				// set inside _refreshValue()
12538
				role: "progressbar",
12539
				"aria-valuemin": this.min
12540
			});
12541
12542
		this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" )
12543
			.appendTo( this.element );
12544
12545
		this._refreshValue();
12546
	},
12547
12548
	_destroy: function() {
12549
		this.element
12550
			.removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
12551
			.removeAttr( "role" )
12552
			.removeAttr( "aria-valuemin" )
12553
			.removeAttr( "aria-valuemax" )
12554
			.removeAttr( "aria-valuenow" );
12555
12556
		this.valueDiv.remove();
12557
	},
12558
12559
	value: function( newValue ) {
12560
		if ( newValue === undefined ) {
12561
			return this.options.value;
12562
		}
12563
12564
		this.options.value = this._constrainedValue( newValue );
12565
		this._refreshValue();
12566
	},
12567
12568
	_constrainedValue: function( newValue ) {
12569
		if ( newValue === undefined ) {
12570
			newValue = this.options.value;
12571
		}
12572
12573
		this.indeterminate = newValue === false;
12574
12575
		// sanitize value
12576
		if ( typeof newValue !== "number" ) {
12577
			newValue = 0;
12578
		}
12579
12580
		return this.indeterminate ? false :
12581
			Math.min( this.options.max, Math.max( this.min, newValue ) );
12582
	},
12583
12584
	_setOptions: function( options ) {
12585
		// Ensure "value" option is set after other values (like max)
12586
		var value = options.value;
12587
		delete options.value;
12588
12589
		this._super( options );
12590
12591
		this.options.value = this._constrainedValue( value );
12592
		this._refreshValue();
12593
	},
12594
12595
	_setOption: function( key, value ) {
12596
		if ( key === "max" ) {
12597
			// Don't allow a max less than min
12598
			value = Math.max( this.min, value );
12599
		}
12600
12601
		this._super( key, value );
12602
	},
12603
12604
	_percentage: function() {
12605
		return this.indeterminate ? 100 : 100 * ( this.options.value - this.min ) / ( this.options.max - this.min );
12606
	},
12607
12608
	_refreshValue: function() {
12609
		var value = this.options.value,
12610
			percentage = this._percentage();
12611
12612
		this.valueDiv
12613
			.toggle( this.indeterminate || value > this.min )
12614
			.toggleClass( "ui-corner-right", value === this.options.max )
12615
			.width( percentage.toFixed(0) + "%" );
12616
12617
		this.element.toggleClass( "ui-progressbar-indeterminate", this.indeterminate );
12618
12619
		if ( this.indeterminate ) {
12620
			this.element.removeAttr( "aria-valuenow" );
12621
			if ( !this.overlayDiv ) {
12622
				this.overlayDiv = $( "<div class='ui-progressbar-overlay'></div>" ).appendTo( this.valueDiv );
12623
			}
12624
		} else {
12625
			this.element.attr({
12626
				"aria-valuemax": this.options.max,
12627
				"aria-valuenow": value
12628
			});
12629
			if ( this.overlayDiv ) {
12630
				this.overlayDiv.remove();
12631
				this.overlayDiv = null;
12632
			}
12633
		}
12634
12635
		if ( this.oldValue !== value ) {
12636
			this.oldValue = value;
12637
			this._trigger( "change" );
12638
		}
12639
		if ( value === this.options.max ) {
12640
			this._trigger( "complete" );
12641
		}
12642
	}
12643
});
12644
12645
})( jQuery );
12646
12647
(function( $, undefined ) {
12648
12649
// number of pages in a slider
12650
// (how many times can you page up/down to go through the whole range)
12651
var numPages = 5;
12652
12653
$.widget( "ui.slider", $.ui.mouse, {
12654
	version: "1.10.3",
12655
	widgetEventPrefix: "slide",
12656
12657
	options: {
12658
		animate: false,
12659
		distance: 0,
12660
		max: 100,
12661
		min: 0,
12662
		orientation: "horizontal",
12663
		range: false,
12664
		step: 1,
12665
		value: 0,
12666
		values: null,
12667
12668
		// callbacks
12669
		change: null,
12670
		slide: null,
12671
		start: null,
12672
		stop: null
12673
	},
12674
12675
	_create: function() {
12676
		this._keySliding = false;
12677
		this._mouseSliding = false;
12678
		this._animateOff = true;
12679
		this._handleIndex = null;
12680
		this._detectOrientation();
12681
		this._mouseInit();
12682
12683
		this.element
12684
			.addClass( "ui-slider" +
12685
				" ui-slider-" + this.orientation +
12686
				" ui-widget" +
12687
				" ui-widget-content" +
12688
				" ui-corner-all");
12689
12690
		this._refresh();
12691
		this._setOption( "disabled", this.options.disabled );
12692
12693
		this._animateOff = false;
12694
	},
12695
12696
	_refresh: function() {
12697
		this._createRange();
12698
		this._createHandles();
12699
		this._setupEvents();
12700
		this._refreshValue();
12701
	},
12702
12703
	_createHandles: function() {
12704
		var i, handleCount,
12705
			options = this.options,
12706
			existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ),
12707
			handle = "<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>",
12708
			handles = [];
12709
12710
		handleCount = ( options.values && options.values.length ) || 1;
12711
12712
		if ( existingHandles.length > handleCount ) {
12713
			existingHandles.slice( handleCount ).remove();
12714
			existingHandles = existingHandles.slice( 0, handleCount );
12715
		}
12716
12717
		for ( i = existingHandles.length; i < handleCount; i++ ) {
12718
			handles.push( handle );
12719
		}
12720
12721
		this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) );
12722
12723
		this.handle = this.handles.eq( 0 );
12724
12725
		this.handles.each(function( i ) {
12726
			$( this ).data( "ui-slider-handle-index", i );
12727
		});
12728
	},
12729
12730
	_createRange: function() {
12731
		var options = this.options,
12732
			classes = "";
12733
12734
		if ( options.range ) {
12735
			if ( options.range === true ) {
12736
				if ( !options.values ) {
12737
					options.values = [ this._valueMin(), this._valueMin() ];
12738
				} else if ( options.values.length && options.values.length !== 2 ) {
12739
					options.values = [ options.values[0], options.values[0] ];
12740
				} else if ( $.isArray( options.values ) ) {
12741
					options.values = options.values.slice(0);
12742
				}
12743
			}
12744
12745
			if ( !this.range || !this.range.length ) {
12746
				this.range = $( "<div></div>" )
12747
					.appendTo( this.element );
12748
12749
				classes = "ui-slider-range" +
12750
				// note: this isn't the most fittingly semantic framework class for this element,
12751
				// but worked best visually with a variety of themes
12752
				" ui-widget-header ui-corner-all";
12753
			} else {
12754
				this.range.removeClass( "ui-slider-range-min ui-slider-range-max" )
12755
					// Handle range switching from true to min/max
12756
					.css({
12757
						"left": "",
12758
						"bottom": ""
12759
					});
12760
			}
12761
12762
			this.range.addClass( classes +
12763
				( ( options.range === "min" || options.range === "max" ) ? " ui-slider-range-" + options.range : "" ) );
12764
		} else {
12765
			this.range = $([]);
12766
		}
12767
	},
12768
12769
	_setupEvents: function() {
12770
		var elements = this.handles.add( this.range ).filter( "a" );
12771
		this._off( elements );
12772
		this._on( elements, this._handleEvents );
12773
		this._hoverable( elements );
12774
		this._focusable( elements );
12775
	},
12776
12777
	_destroy: function() {
12778
		this.handles.remove();
12779
		this.range.remove();
12780
12781
		this.element
12782
			.removeClass( "ui-slider" +
12783
				" ui-slider-horizontal" +
12784
				" ui-slider-vertical" +
12785
				" ui-widget" +
12786
				" ui-widget-content" +
12787
				" ui-corner-all" );
12788
12789
		this._mouseDestroy();
12790
	},
12791
12792
	_mouseCapture: function( event ) {
12793
		var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle,
12794
			that = this,
12795
			o = this.options;
12796
12797
		if ( o.disabled ) {
12798
			return false;
12799
		}
12800
12801
		this.elementSize = {
12802
			width: this.element.outerWidth(),
12803
			height: this.element.outerHeight()
12804
		};
12805
		this.elementOffset = this.element.offset();
12806
12807
		position = { x: event.pageX, y: event.pageY };
12808
		normValue = this._normValueFromMouse( position );
12809
		distance = this._valueMax() - this._valueMin() + 1;
12810
		this.handles.each(function( i ) {
12811
			var thisDistance = Math.abs( normValue - that.values(i) );
12812
			if (( distance > thisDistance ) ||
12813
				( distance === thisDistance &&
12814
					(i === that._lastChangedValue || that.values(i) === o.min ))) {
12815
				distance = thisDistance;
12816
				closestHandle = $( this );
12817
				index = i;
12818
			}
12819
		});
12820
12821
		allowed = this._start( event, index );
12822
		if ( allowed === false ) {
12823
			return false;
12824
		}
12825
		this._mouseSliding = true;
12826
12827
		this._handleIndex = index;
12828
12829
		closestHandle
12830
			.addClass( "ui-state-active" )
12831
			.focus();
12832
12833
		offset = closestHandle.offset();
12834
		mouseOverHandle = !$( event.target ).parents().addBack().is( ".ui-slider-handle" );
12835
		this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
12836
			left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
12837
			top: event.pageY - offset.top -
12838
				( closestHandle.height() / 2 ) -
12839
				( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
12840
				( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
12841
				( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
12842
		};
12843
12844
		if ( !this.handles.hasClass( "ui-state-hover" ) ) {
12845
			this._slide( event, index, normValue );
12846
		}
12847
		this._animateOff = true;
12848
		return true;
12849
	},
12850
12851
	_mouseStart: function() {
12852
		return true;
12853
	},
12854
12855
	_mouseDrag: function( event ) {
12856
		var position = { x: event.pageX, y: event.pageY },
12857
			normValue = this._normValueFromMouse( position );
12858
12859
		this._slide( event, this._handleIndex, normValue );
12860
12861
		return false;
12862
	},
12863
12864
	_mouseStop: function( event ) {
12865
		this.handles.removeClass( "ui-state-active" );
12866
		this._mouseSliding = false;
12867
12868
		this._stop( event, this._handleIndex );
12869
		this._change( event, this._handleIndex );
12870
12871
		this._handleIndex = null;
12872
		this._clickOffset = null;
12873
		this._animateOff = false;
12874
12875
		return false;
12876
	},
12877
12878
	_detectOrientation: function() {
12879
		this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
12880
	},
12881
12882
	_normValueFromMouse: function( position ) {
12883
		var pixelTotal,
12884
			pixelMouse,
12885
			percentMouse,
12886
			valueTotal,
12887
			valueMouse;
12888
12889
		if ( this.orientation === "horizontal" ) {
12890
			pixelTotal = this.elementSize.width;
12891
			pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
12892
		} else {
12893
			pixelTotal = this.elementSize.height;
12894
			pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
12895
		}
12896
12897
		percentMouse = ( pixelMouse / pixelTotal );
12898
		if ( percentMouse > 1 ) {
12899
			percentMouse = 1;
12900
		}
12901
		if ( percentMouse < 0 ) {
12902
			percentMouse = 0;
12903
		}
12904
		if ( this.orientation === "vertical" ) {
12905
			percentMouse = 1 - percentMouse;
12906
		}
12907
12908
		valueTotal = this._valueMax() - this._valueMin();
12909
		valueMouse = this._valueMin() + percentMouse * valueTotal;
12910
12911
		return this._trimAlignValue( valueMouse );
12912
	},
12913
12914
	_start: function( event, index ) {
12915
		var uiHash = {
12916
			handle: this.handles[ index ],
12917
			value: this.value()
12918
		};
12919
		if ( this.options.values && this.options.values.length ) {
12920
			uiHash.value = this.values( index );
12921
			uiHash.values = this.values();
12922
		}
12923
		return this._trigger( "start", event, uiHash );
12924
	},
12925
12926
	_slide: function( event, index, newVal ) {
12927
		var otherVal,
12928
			newValues,
12929
			allowed;
12930
12931
		if ( this.options.values && this.options.values.length ) {
12932
			otherVal = this.values( index ? 0 : 1 );
12933
12934
			if ( ( this.options.values.length === 2 && this.options.range === true ) &&
12935
					( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
12936
				) {
12937
				newVal = otherVal;
12938
			}
12939
12940
			if ( newVal !== this.values( index ) ) {
12941
				newValues = this.values();
12942
				newValues[ index ] = newVal;
12943
				// A slide can be canceled by returning false from the slide callback
12944
				allowed = this._trigger( "slide", event, {
12945
					handle: this.handles[ index ],
12946
					value: newVal,
12947
					values: newValues
12948
				} );
12949
				otherVal = this.values( index ? 0 : 1 );
12950
				if ( allowed !== false ) {
12951
					this.values( index, newVal, true );
12952
				}
12953
			}
12954
		} else {
12955
			if ( newVal !== this.value() ) {
12956
				// A slide can be canceled by returning false from the slide callback
12957
				allowed = this._trigger( "slide", event, {
12958
					handle: this.handles[ index ],
12959
					value: newVal
12960
				} );
12961
				if ( allowed !== false ) {
12962
					this.value( newVal );
12963
				}
12964
			}
12965
		}
12966
	},
12967
12968
	_stop: function( event, index ) {
12969
		var uiHash = {
12970
			handle: this.handles[ index ],
12971
			value: this.value()
12972
		};
12973
		if ( this.options.values && this.options.values.length ) {
12974
			uiHash.value = this.values( index );
12975
			uiHash.values = this.values();
12976
		}
12977
12978
		this._trigger( "stop", event, uiHash );
12979
	},
12980
12981
	_change: function( event, index ) {
12982
		if ( !this._keySliding && !this._mouseSliding ) {
12983
			var uiHash = {
12984
				handle: this.handles[ index ],
12985
				value: this.value()
12986
			};
12987
			if ( this.options.values && this.options.values.length ) {
12988
				uiHash.value = this.values( index );
12989
				uiHash.values = this.values();
12990
			}
12991
12992
			//store the last changed value index for reference when handles overlap
12993
			this._lastChangedValue = index;
12994
12995
			this._trigger( "change", event, uiHash );
12996
		}
12997
	},
12998
12999
	value: function( newValue ) {
13000
		if ( arguments.length ) {
13001
			this.options.value = this._trimAlignValue( newValue );
13002
			this._refreshValue();
13003
			this._change( null, 0 );
13004
			return;
13005
		}
13006
13007
		return this._value();
13008
	},
13009
13010
	values: function( index, newValue ) {
13011
		var vals,
13012
			newValues,
13013
			i;
13014
13015
		if ( arguments.length > 1 ) {
13016
			this.options.values[ index ] = this._trimAlignValue( newValue );
13017
			this._refreshValue();
13018
			this._change( null, index );
13019
			return;
13020
		}
13021
13022
		if ( arguments.length ) {
13023
			if ( $.isArray( arguments[ 0 ] ) ) {
13024
				vals = this.options.values;
13025
				newValues = arguments[ 0 ];
13026
				for ( i = 0; i < vals.length; i += 1 ) {
13027
					vals[ i ] = this._trimAlignValue( newValues[ i ] );
13028
					this._change( null, i );
13029
				}
13030
				this._refreshValue();
13031
			} else {
13032
				if ( this.options.values && this.options.values.length ) {
13033
					return this._values( index );
13034
				} else {
13035
					return this.value();
13036
				}
13037
			}
13038
		} else {
13039
			return this._values();
13040
		}
13041
	},
13042
13043
	_setOption: function( key, value ) {
13044
		var i,
13045
			valsLength = 0;
13046
13047
		if ( key === "range" && this.options.range === true ) {
13048
			if ( value === "min" ) {
13049
				this.options.value = this._values( 0 );
13050
				this.options.values = null;
13051
			} else if ( value === "max" ) {
13052
				this.options.value = this._values( this.options.values.length-1 );
13053
				this.options.values = null;
13054
			}
13055
		}
13056
13057
		if ( $.isArray( this.options.values ) ) {
13058
			valsLength = this.options.values.length;
13059
		}
13060
13061
		$.Widget.prototype._setOption.apply( this, arguments );
13062
13063
		switch ( key ) {
13064
			case "orientation":
13065
				this._detectOrientation();
13066
				this.element
13067
					.removeClass( "ui-slider-horizontal ui-slider-vertical" )
13068
					.addClass( "ui-slider-" + this.orientation );
13069
				this._refreshValue();
13070
				break;
13071
			case "value":
13072
				this._animateOff = true;
13073
				this._refreshValue();
13074
				this._change( null, 0 );
13075
				this._animateOff = false;
13076
				break;
13077
			case "values":
13078
				this._animateOff = true;
13079
				this._refreshValue();
13080
				for ( i = 0; i < valsLength; i += 1 ) {
13081
					this._change( null, i );
13082
				}
13083
				this._animateOff = false;
13084
				break;
13085
			case "min":
13086
			case "max":
13087
				this._animateOff = true;
13088
				this._refreshValue();
13089
				this._animateOff = false;
13090
				break;
13091
			case "range":
13092
				this._animateOff = true;
13093
				this._refresh();
13094
				this._animateOff = false;
13095
				break;
13096
		}
13097
	},
13098
13099
	//internal value getter
13100
	// _value() returns value trimmed by min and max, aligned by step
13101
	_value: function() {
13102
		var val = this.options.value;
13103
		val = this._trimAlignValue( val );
13104
13105
		return val;
13106
	},
13107
13108
	//internal values getter
13109
	// _values() returns array of values trimmed by min and max, aligned by step
13110
	// _values( index ) returns single value trimmed by min and max, aligned by step
13111
	_values: function( index ) {
13112
		var val,
13113
			vals,
13114
			i;
13115
13116
		if ( arguments.length ) {
13117
			val = this.options.values[ index ];
13118
			val = this._trimAlignValue( val );
13119
13120
			return val;
13121
		} else if ( this.options.values && this.options.values.length ) {
13122
			// .slice() creates a copy of the array
13123
			// this copy gets trimmed by min and max and then returned
13124
			vals = this.options.values.slice();
13125
			for ( i = 0; i < vals.length; i+= 1) {
13126
				vals[ i ] = this._trimAlignValue( vals[ i ] );
13127
			}
13128
13129
			return vals;
13130
		} else {
13131
			return [];
13132
		}
13133
	},
13134
13135
	// returns the step-aligned value that val is closest to, between (inclusive) min and max
13136
	_trimAlignValue: function( val ) {
13137
		if ( val <= this._valueMin() ) {
13138
			return this._valueMin();
13139
		}
13140
		if ( val >= this._valueMax() ) {
13141
			return this._valueMax();
13142
		}
13143
		var step = ( this.options.step > 0 ) ? this.options.step : 1,
13144
			valModStep = (val - this._valueMin()) % step,
13145
			alignValue = val - valModStep;
13146
13147
		if ( Math.abs(valModStep) * 2 >= step ) {
13148
			alignValue += ( valModStep > 0 ) ? step : ( -step );
13149
		}
13150
13151
		// Since JavaScript has problems with large floats, round
13152
		// the final value to 5 digits after the decimal point (see #4124)
13153
		return parseFloat( alignValue.toFixed(5) );
13154
	},
13155
13156
	_valueMin: function() {
13157
		return this.options.min;
13158
	},
13159
13160
	_valueMax: function() {
13161
		return this.options.max;
13162
	},
13163
13164
	_refreshValue: function() {
13165
		var lastValPercent, valPercent, value, valueMin, valueMax,
13166
			oRange = this.options.range,
13167
			o = this.options,
13168
			that = this,
13169
			animate = ( !this._animateOff ) ? o.animate : false,
13170
			_set = {};
13171
13172
		if ( this.options.values && this.options.values.length ) {
13173
			this.handles.each(function( i ) {
13174
				valPercent = ( that.values(i) - that._valueMin() ) / ( that._valueMax() - that._valueMin() ) * 100;
13175
				_set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
13176
				$( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
13177
				if ( that.options.range === true ) {
13178
					if ( that.orientation === "horizontal" ) {
13179
						if ( i === 0 ) {
13180
							that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
13181
						}
13182
						if ( i === 1 ) {
13183
							that.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
13184
						}
13185
					} else {
13186
						if ( i === 0 ) {
13187
							that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
13188
						}
13189
						if ( i === 1 ) {
13190
							that.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
13191
						}
13192
					}
13193
				}
13194
				lastValPercent = valPercent;
13195
			});
13196
		} else {
13197
			value = this.value();
13198
			valueMin = this._valueMin();
13199
			valueMax = this._valueMax();
13200
			valPercent = ( valueMax !== valueMin ) ?
13201
					( value - valueMin ) / ( valueMax - valueMin ) * 100 :
13202
					0;
13203
			_set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
13204
			this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
13205
13206
			if ( oRange === "min" && this.orientation === "horizontal" ) {
13207
				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );
13208
			}
13209
			if ( oRange === "max" && this.orientation === "horizontal" ) {
13210
				this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
13211
			}
13212
			if ( oRange === "min" && this.orientation === "vertical" ) {
13213
				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );
13214
			}
13215
			if ( oRange === "max" && this.orientation === "vertical" ) {
13216
				this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
13217
			}
13218
		}
13219
	},
13220
13221
	_handleEvents: {
13222
		keydown: function( event ) {
13223
			/*jshint maxcomplexity:25*/
13224
			var allowed, curVal, newVal, step,
13225
				index = $( event.target ).data( "ui-slider-handle-index" );
13226
13227
			switch ( event.keyCode ) {
13228
				case $.ui.keyCode.HOME:
13229
				case $.ui.keyCode.END:
13230
				case $.ui.keyCode.PAGE_UP:
13231
				case $.ui.keyCode.PAGE_DOWN:
13232
				case $.ui.keyCode.UP:
13233
				case $.ui.keyCode.RIGHT:
13234
				case $.ui.keyCode.DOWN:
13235
				case $.ui.keyCode.LEFT:
13236
					event.preventDefault();
13237
					if ( !this._keySliding ) {
13238
						this._keySliding = true;
13239
						$( event.target ).addClass( "ui-state-active" );
13240
						allowed = this._start( event, index );
13241
						if ( allowed === false ) {
13242
							return;
13243
						}
13244
					}
13245
					break;
13246
			}
13247
13248
			step = this.options.step;
13249
			if ( this.options.values && this.options.values.length ) {
13250
				curVal = newVal = this.values( index );
13251
			} else {
13252
				curVal = newVal = this.value();
13253
			}
13254
13255
			switch ( event.keyCode ) {
13256
				case $.ui.keyCode.HOME:
13257
					newVal = this._valueMin();
13258
					break;
13259
				case $.ui.keyCode.END:
13260
					newVal = this._valueMax();
13261
					break;
13262
				case $.ui.keyCode.PAGE_UP:
13263
					newVal = this._trimAlignValue( curVal + ( (this._valueMax() - this._valueMin()) / numPages ) );
13264
					break;
13265
				case $.ui.keyCode.PAGE_DOWN:
13266
					newVal = this._trimAlignValue( curVal - ( (this._valueMax() - this._valueMin()) / numPages ) );
13267
					break;
13268
				case $.ui.keyCode.UP:
13269
				case $.ui.keyCode.RIGHT:
13270
					if ( curVal === this._valueMax() ) {
13271
						return;
13272
					}
13273
					newVal = this._trimAlignValue( curVal + step );
13274
					break;
13275
				case $.ui.keyCode.DOWN:
13276
				case $.ui.keyCode.LEFT:
13277
					if ( curVal === this._valueMin() ) {
13278
						return;
13279
					}
13280
					newVal = this._trimAlignValue( curVal - step );
13281
					break;
13282
			}
13283
13284
			this._slide( event, index, newVal );
13285
		},
13286
		click: function( event ) {
13287
			event.preventDefault();
13288
		},
13289
		keyup: function( event ) {
13290
			var index = $( event.target ).data( "ui-slider-handle-index" );
13291
13292
			if ( this._keySliding ) {
13293
				this._keySliding = false;
13294
				this._stop( event, index );
13295
				this._change( event, index );
13296
				$( event.target ).removeClass( "ui-state-active" );
13297
			}
13298
		}
13299
	}
13300
13301
});
13302
13303
}(jQuery));
13304
13305
(function( $ ) {
13306
13307
function modifier( fn ) {
13308
	return function() {
13309
		var previous = this.element.val();
13310
		fn.apply( this, arguments );
13311
		this._refresh();
13312
		if ( previous !== this.element.val() ) {
13313
			this._trigger( "change" );
13314
		}
13315
	};
13316
}
13317
13318
$.widget( "ui.spinner", {
13319
	version: "1.10.3",
13320
	defaultElement: "<input>",
13321
	widgetEventPrefix: "spin",
13322
	options: {
13323
		culture: null,
13324
		icons: {
13325
			down: "ui-icon-triangle-1-s",
13326
			up: "ui-icon-triangle-1-n"
13327
		},
13328
		incremental: true,
13329
		max: null,
13330
		min: null,
13331
		numberFormat: null,
13332
		page: 10,
13333
		step: 1,
13334
13335
		change: null,
13336
		spin: null,
13337
		start: null,
13338
		stop: null
13339
	},
13340
13341
	_create: function() {
13342
		// handle string values that need to be parsed
13343
		this._setOption( "max", this.options.max );
13344
		this._setOption( "min", this.options.min );
13345
		this._setOption( "step", this.options.step );
13346
13347
		// format the value, but don't constrain
13348
		this._value( this.element.val(), true );
13349
13350
		this._draw();
13351
		this._on( this._events );
13352
		this._refresh();
13353
13354
		// turning off autocomplete prevents the browser from remembering the
13355
		// value when navigating through history, so we re-enable autocomplete
13356
		// if the page is unloaded before the widget is destroyed. #7790
13357
		this._on( this.window, {
13358
			beforeunload: function() {
13359
				this.element.removeAttr( "autocomplete" );
13360
			}
13361
		});
13362
	},
13363
13364
	_getCreateOptions: function() {
13365
		var options = {},
13366
			element = this.element;
13367
13368
		$.each( [ "min", "max", "step" ], function( i, option ) {
13369
			var value = element.attr( option );
13370
			if ( value !== undefined && value.length ) {
13371
				options[ option ] = value;
13372
			}
13373
		});
13374
13375
		return options;
13376
	},
13377
13378
	_events: {
13379
		keydown: function( event ) {
13380
			if ( this._start( event ) && this._keydown( event ) ) {
13381
				event.preventDefault();
13382
			}
13383
		},
13384
		keyup: "_stop",
13385
		focus: function() {
13386
			this.previous = this.element.val();
13387
		},
13388
		blur: function( event ) {
13389
			if ( this.cancelBlur ) {
13390
				delete this.cancelBlur;
13391
				return;
13392
			}
13393
13394
			this._stop();
13395
			this._refresh();
13396
			if ( this.previous !== this.element.val() ) {
13397
				this._trigger( "change", event );
13398
			}
13399
		},
13400
		mousewheel: function( event, delta ) {
13401
			if ( !delta ) {
13402
				return;
13403
			}
13404
			if ( !this.spinning && !this._start( event ) ) {
13405
				return false;
13406
			}
13407
13408
			this._spin( (delta > 0 ? 1 : -1) * this.options.step, event );
13409
			clearTimeout( this.mousewheelTimer );
13410
			this.mousewheelTimer = this._delay(function() {
13411
				if ( this.spinning ) {
13412
					this._stop( event );
13413
				}
13414
			}, 100 );
13415
			event.preventDefault();
13416
		},
13417
		"mousedown .ui-spinner-button": function( event ) {
13418
			var previous;
13419
13420
			// We never want the buttons to have focus; whenever the user is
13421
			// interacting with the spinner, the focus should be on the input.
13422
			// If the input is focused then this.previous is properly set from
13423
			// when the input first received focus. If the input is not focused
13424
			// then we need to set this.previous based on the value before spinning.
13425
			previous = this.element[0] === this.document[0].activeElement ?
13426
				this.previous : this.element.val();
13427
			function checkFocus() {
13428
				var isActive = this.element[0] === this.document[0].activeElement;
13429
				if ( !isActive ) {
13430
					this.element.focus();
13431
					this.previous = previous;
13432
					// support: IE
13433
					// IE sets focus asynchronously, so we need to check if focus
13434
					// moved off of the input because the user clicked on the button.
13435
					this._delay(function() {
13436
						this.previous = previous;
13437
					});
13438
				}
13439
			}
13440
13441
			// ensure focus is on (or stays on) the text field
13442
			event.preventDefault();
13443
			checkFocus.call( this );
13444
13445
			// support: IE
13446
			// IE doesn't prevent moving focus even with event.preventDefault()
13447
			// so we set a flag to know when we should ignore the blur event
13448
			// and check (again) if focus moved off of the input.
13449
			this.cancelBlur = true;
13450
			this._delay(function() {
13451
				delete this.cancelBlur;
13452
				checkFocus.call( this );
13453
			});
13454
13455
			if ( this._start( event ) === false ) {
13456
				return;
13457
			}
13458
13459
			this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event );
13460
		},
13461
		"mouseup .ui-spinner-button": "_stop",
13462
		"mouseenter .ui-spinner-button": function( event ) {
13463
			// button will add ui-state-active if mouse was down while mouseleave and kept down
13464
			if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) {
13465
				return;
13466
			}
13467
13468
			if ( this._start( event ) === false ) {
13469
				return false;
13470
			}
13471
			this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event );
13472
		},
13473
		// TODO: do we really want to consider this a stop?
13474
		// shouldn't we just stop the repeater and wait until mouseup before
13475
		// we trigger the stop event?
13476
		"mouseleave .ui-spinner-button": "_stop"
13477
	},
13478
13479
	_draw: function() {
13480
		var uiSpinner = this.uiSpinner = this.element
13481
			.addClass( "ui-spinner-input" )
13482
			.attr( "autocomplete", "off" )
13483
			.wrap( this._uiSpinnerHtml() )
13484
			.parent()
13485
				// add buttons
13486
				.append( this._buttonHtml() );
13487
13488
		this.element.attr( "role", "spinbutton" );
13489
13490
		// button bindings
13491
		this.buttons = uiSpinner.find( ".ui-spinner-button" )
13492
			.attr( "tabIndex", -1 )
13493
			.button()
13494
			.removeClass( "ui-corner-all" );
13495
13496
		// IE 6 doesn't understand height: 50% for the buttons
13497
		// unless the wrapper has an explicit height
13498
		if ( this.buttons.height() > Math.ceil( uiSpinner.height() * 0.5 ) &&
13499
				uiSpinner.height() > 0 ) {
13500
			uiSpinner.height( uiSpinner.height() );
13501
		}
13502
13503
		// disable spinner if element was already disabled
13504
		if ( this.options.disabled ) {
13505
			this.disable();
13506
		}
13507
	},
13508
13509
	_keydown: function( event ) {
13510
		var options = this.options,
13511
			keyCode = $.ui.keyCode;
13512
13513
		switch ( event.keyCode ) {
13514
		case keyCode.UP:
13515
			this._repeat( null, 1, event );
13516
			return true;
13517
		case keyCode.DOWN:
13518
			this._repeat( null, -1, event );
13519
			return true;
13520
		case keyCode.PAGE_UP:
13521
			this._repeat( null, options.page, event );
13522
			return true;
13523
		case keyCode.PAGE_DOWN:
13524
			this._repeat( null, -options.page, event );
13525
			return true;
13526
		}
13527
13528
		return false;
13529
	},
13530
13531
	_uiSpinnerHtml: function() {
13532
		return "<span class='ui-spinner ui-widget ui-widget-content ui-corner-all'></span>";
13533
	},
13534
13535
	_buttonHtml: function() {
13536
		return "" +
13537
			"<a class='ui-spinner-button ui-spinner-up ui-corner-tr'>" +
13538
				"<span class='ui-icon " + this.options.icons.up + "'>&#9650;</span>" +
13539
			"</a>" +
13540
			"<a class='ui-spinner-button ui-spinner-down ui-corner-br'>" +
13541
				"<span class='ui-icon " + this.options.icons.down + "'>&#9660;</span>" +
13542
			"</a>";
13543
	},
13544
13545
	_start: function( event ) {
13546
		if ( !this.spinning && this._trigger( "start", event ) === false ) {
13547
			return false;
13548
		}
13549
13550
		if ( !this.counter ) {
13551
			this.counter = 1;
13552
		}
13553
		this.spinning = true;
13554
		return true;
13555
	},
13556
13557
	_repeat: function( i, steps, event ) {
13558
		i = i || 500;
13559
13560
		clearTimeout( this.timer );
13561
		this.timer = this._delay(function() {
13562
			this._repeat( 40, steps, event );
13563
		}, i );
13564
13565
		this._spin( steps * this.options.step, event );
13566
	},
13567
13568
	_spin: function( step, event ) {
13569
		var value = this.value() || 0;
13570
13571
		if ( !this.counter ) {
13572
			this.counter = 1;
13573
		}
13574
13575
		value = this._adjustValue( value + step * this._increment( this.counter ) );
13576
13577
		if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false) {
13578
			this._value( value );
13579
			this.counter++;
13580
		}
13581
	},
13582
13583
	_increment: function( i ) {
13584
		var incremental = this.options.incremental;
13585
13586
		if ( incremental ) {
13587
			return $.isFunction( incremental ) ?
13588
				incremental( i ) :
13589
				Math.floor( i*i*i/50000 - i*i/500 + 17*i/200 + 1 );
13590
		}
13591
13592
		return 1;
13593
	},
13594
13595
	_precision: function() {
13596
		var precision = this._precisionOf( this.options.step );
13597
		if ( this.options.min !== null ) {
13598
			precision = Math.max( precision, this._precisionOf( this.options.min ) );
13599
		}
13600
		return precision;
13601
	},
13602
13603
	_precisionOf: function( num ) {
13604
		var str = num.toString(),
13605
			decimal = str.indexOf( "." );
13606
		return decimal === -1 ? 0 : str.length - decimal - 1;
13607
	},
13608
13609
	_adjustValue: function( value ) {
13610
		var base, aboveMin,
13611
			options = this.options;
13612
13613
		// make sure we're at a valid step
13614
		// - find out where we are relative to the base (min or 0)
13615
		base = options.min !== null ? options.min : 0;
13616
		aboveMin = value - base;
13617
		// - round to the nearest step
13618
		aboveMin = Math.round(aboveMin / options.step) * options.step;
13619
		// - rounding is based on 0, so adjust back to our base
13620
		value = base + aboveMin;
13621
13622
		// fix precision from bad JS floating point math
13623
		value = parseFloat( value.toFixed( this._precision() ) );
13624
13625
		// clamp the value
13626
		if ( options.max !== null && value > options.max) {
13627
			return options.max;
13628
		}
13629
		if ( options.min !== null && value < options.min ) {
13630
			return options.min;
13631
		}
13632
13633
		return value;
13634
	},
13635
13636
	_stop: function( event ) {
13637
		if ( !this.spinning ) {
13638
			return;
13639
		}
13640
13641
		clearTimeout( this.timer );
13642
		clearTimeout( this.mousewheelTimer );
13643
		this.counter = 0;
13644
		this.spinning = false;
13645
		this._trigger( "stop", event );
13646
	},
13647
13648
	_setOption: function( key, value ) {
13649
		if ( key === "culture" || key === "numberFormat" ) {
13650
			var prevValue = this._parse( this.element.val() );
13651
			this.options[ key ] = value;
13652
			this.element.val( this._format( prevValue ) );
13653
			return;
13654
		}
13655
13656
		if ( key === "max" || key === "min" || key === "step" ) {
13657
			if ( typeof value === "string" ) {
13658
				value = this._parse( value );
13659
			}
13660
		}
13661
		if ( key === "icons" ) {
13662
			this.buttons.first().find( ".ui-icon" )
13663
				.removeClass( this.options.icons.up )
13664
				.addClass( value.up );
13665
			this.buttons.last().find( ".ui-icon" )
13666
				.removeClass( this.options.icons.down )
13667
				.addClass( value.down );
13668
		}
13669
13670
		this._super( key, value );
13671
13672
		if ( key === "disabled" ) {
13673
			if ( value ) {
13674
				this.element.prop( "disabled", true );
13675
				this.buttons.button( "disable" );
13676
			} else {
13677
				this.element.prop( "disabled", false );
13678
				this.buttons.button( "enable" );
13679
			}
13680
		}
13681
	},
13682
13683
	_setOptions: modifier(function( options ) {
13684
		this._super( options );
13685
		this._value( this.element.val() );
13686
	}),
13687
13688
	_parse: function( val ) {
13689
		if ( typeof val === "string" && val !== "" ) {
13690
			val = window.Globalize && this.options.numberFormat ?
13691
				Globalize.parseFloat( val, 10, this.options.culture ) : +val;
13692
		}
13693
		return val === "" || isNaN( val ) ? null : val;
13694
	},
13695
13696
	_format: function( value ) {
13697
		if ( value === "" ) {
13698
			return "";
13699
		}
13700
		return window.Globalize && this.options.numberFormat ?
13701
			Globalize.format( value, this.options.numberFormat, this.options.culture ) :
13702
			value;
13703
	},
13704
13705
	_refresh: function() {
13706
		this.element.attr({
13707
			"aria-valuemin": this.options.min,
13708
			"aria-valuemax": this.options.max,
13709
			// TODO: what should we do with values that can't be parsed?
13710
			"aria-valuenow": this._parse( this.element.val() )
13711
		});
13712
	},
13713
13714
	// update the value without triggering change
13715
	_value: function( value, allowAny ) {
13716
		var parsed;
13717
		if ( value !== "" ) {
13718
			parsed = this._parse( value );
13719
			if ( parsed !== null ) {
13720
				if ( !allowAny ) {
13721
					parsed = this._adjustValue( parsed );
13722
				}
13723
				value = this._format( parsed );
13724
			}
13725
		}
13726
		this.element.val( value );
13727
		this._refresh();
13728
	},
13729
13730
	_destroy: function() {
13731
		this.element
13732
			.removeClass( "ui-spinner-input" )
13733
			.prop( "disabled", false )
13734
			.removeAttr( "autocomplete" )
13735
			.removeAttr( "role" )
13736
			.removeAttr( "aria-valuemin" )
13737
			.removeAttr( "aria-valuemax" )
13738
			.removeAttr( "aria-valuenow" );
13739
		this.uiSpinner.replaceWith( this.element );
13740
	},
13741
13742
	stepUp: modifier(function( steps ) {
13743
		this._stepUp( steps );
13744
	}),
13745
	_stepUp: function( steps ) {
13746
		if ( this._start() ) {
13747
			this._spin( (steps || 1) * this.options.step );
13748
			this._stop();
13749
		}
13750
	},
13751
13752
	stepDown: modifier(function( steps ) {
13753
		this._stepDown( steps );
13754
	}),
13755
	_stepDown: function( steps ) {
13756
		if ( this._start() ) {
13757
			this._spin( (steps || 1) * -this.options.step );
13758
			this._stop();
13759
		}
13760
	},
13761
13762
	pageUp: modifier(function( pages ) {
13763
		this._stepUp( (pages || 1) * this.options.page );
13764
	}),
13765
13766
	pageDown: modifier(function( pages ) {
13767
		this._stepDown( (pages || 1) * this.options.page );
13768
	}),
13769
13770
	value: function( newVal ) {
13771
		if ( !arguments.length ) {
13772
			return this._parse( this.element.val() );
13773
		}
13774
		modifier( this._value ).call( this, newVal );
13775
	},
13776
13777
	widget: function() {
13778
		return this.uiSpinner;
13779
	}
13780
});
13781
13782
}( jQuery ) );
13783
13784
(function( $, undefined ) {
13785
13786
var tabId = 0,
13787
	rhash = /#.*$/;
13788
13789
function getNextTabId() {
13790
	return ++tabId;
13791
}
13792
13793
function isLocal( anchor ) {
13794
	return anchor.hash.length > 1 &&
13795
		decodeURIComponent( anchor.href.replace( rhash, "" ) ) ===
13796
			decodeURIComponent( location.href.replace( rhash, "" ) );
13797
}
13798
13799
$.widget( "ui.tabs", {
13800
	version: "1.10.3",
13801
	delay: 300,
13802
	options: {
13803
		active: null,
13804
		collapsible: false,
13805
		event: "click",
13806
		heightStyle: "content",
13807
		hide: null,
13808
		show: null,
13809
13810
		// callbacks
13811
		activate: null,
13812
		beforeActivate: null,
13813
		beforeLoad: null,
13814
		load: null
13815
	},
13816
13817
	_create: function() {
13818
		var that = this,
13819
			options = this.options;
13820
13821
		this.running = false;
13822
13823
		this.element
13824
			.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" )
13825
			.toggleClass( "ui-tabs-collapsible", options.collapsible )
13826
			// Prevent users from focusing disabled tabs via click
13827
			.delegate( ".ui-tabs-nav > li", "mousedown" + this.eventNamespace, function( event ) {
13828
				if ( $( this ).is( ".ui-state-disabled" ) ) {
13829
					event.preventDefault();
13830
				}
13831
			})
13832
			// support: IE <9
13833
			// Preventing the default action in mousedown doesn't prevent IE
13834
			// from focusing the element, so if the anchor gets focused, blur.
13835
			// We don't have to worry about focusing the previously focused
13836
			// element since clicking on a non-focusable element should focus
13837
			// the body anyway.
13838
			.delegate( ".ui-tabs-anchor", "focus" + this.eventNamespace, function() {
13839
				if ( $( this ).closest( "li" ).is( ".ui-state-disabled" ) ) {
13840
					this.blur();
13841
				}
13842
			});
13843
13844
		this._processTabs();
13845
		options.active = this._initialActive();
13846
13847
		// Take disabling tabs via class attribute from HTML
13848
		// into account and update option properly.
13849
		if ( $.isArray( options.disabled ) ) {
13850
			options.disabled = $.unique( options.disabled.concat(
13851
				$.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) {
13852
					return that.tabs.index( li );
13853
				})
13854
			) ).sort();
13855
		}
13856
13857
		// check for length avoids error when initializing empty list
13858
		if ( this.options.active !== false && this.anchors.length ) {
13859
			this.active = this._findActive( options.active );
13860
		} else {
13861
			this.active = $();
13862
		}
13863
13864
		this._refresh();
13865
13866
		if ( this.active.length ) {
13867
			this.load( options.active );
13868
		}
13869
	},
13870
13871
	_initialActive: function() {
13872
		var active = this.options.active,
13873
			collapsible = this.options.collapsible,
13874
			locationHash = location.hash.substring( 1 );
13875
13876
		if ( active === null ) {
13877
			// check the fragment identifier in the URL
13878
			if ( locationHash ) {
13879
				this.tabs.each(function( i, tab ) {
13880
					if ( $( tab ).attr( "aria-controls" ) === locationHash ) {
13881
						active = i;
13882
						return false;
13883
					}
13884
				});
13885
			}
13886
13887
			// check for a tab marked active via a class
13888
			if ( active === null ) {
13889
				active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) );
13890
			}
13891
13892
			// no active tab, set to false
13893
			if ( active === null || active === -1 ) {
13894
				active = this.tabs.length ? 0 : false;
13895
			}
13896
		}
13897
13898
		// handle numbers: negative, out of range
13899
		if ( active !== false ) {
13900
			active = this.tabs.index( this.tabs.eq( active ) );
13901
			if ( active === -1 ) {
13902
				active = collapsible ? false : 0;
13903
			}
13904
		}
13905
13906
		// don't allow collapsible: false and active: false
13907
		if ( !collapsible && active === false && this.anchors.length ) {
13908
			active = 0;
13909
		}
13910
13911
		return active;
13912
	},
13913
13914
	_getCreateEventData: function() {
13915
		return {
13916
			tab: this.active,
13917
			panel: !this.active.length ? $() : this._getPanelForTab( this.active )
13918
		};
13919
	},
13920
13921
	_tabKeydown: function( event ) {
13922
		/*jshint maxcomplexity:15*/
13923
		var focusedTab = $( this.document[0].activeElement ).closest( "li" ),
13924
			selectedIndex = this.tabs.index( focusedTab ),
13925
			goingForward = true;
13926
13927
		if ( this._handlePageNav( event ) ) {
13928
			return;
13929
		}
13930
13931
		switch ( event.keyCode ) {
13932
			case $.ui.keyCode.RIGHT:
13933
			case $.ui.keyCode.DOWN:
13934
				selectedIndex++;
13935
				break;
13936
			case $.ui.keyCode.UP:
13937
			case $.ui.keyCode.LEFT:
13938
				goingForward = false;
13939
				selectedIndex--;
13940
				break;
13941
			case $.ui.keyCode.END:
13942
				selectedIndex = this.anchors.length - 1;
13943
				break;
13944
			case $.ui.keyCode.HOME:
13945
				selectedIndex = 0;
13946
				break;
13947
			case $.ui.keyCode.SPACE:
13948
				// Activate only, no collapsing
13949
				event.preventDefault();
13950
				clearTimeout( this.activating );
13951
				this._activate( selectedIndex );
13952
				return;
13953
			case $.ui.keyCode.ENTER:
13954
				// Toggle (cancel delayed activation, allow collapsing)
13955
				event.preventDefault();
13956
				clearTimeout( this.activating );
13957
				// Determine if we should collapse or activate
13958
				this._activate( selectedIndex === this.options.active ? false : selectedIndex );
13959
				return;
13960
			default:
13961
				return;
13962
		}
13963
13964
		// Focus the appropriate tab, based on which key was pressed
13965
		event.preventDefault();
13966
		clearTimeout( this.activating );
13967
		selectedIndex = this._focusNextTab( selectedIndex, goingForward );
13968
13969
		// Navigating with control key will prevent automatic activation
13970
		if ( !event.ctrlKey ) {
13971
			// Update aria-selected immediately so that AT think the tab is already selected.
13972
			// Otherwise AT may confuse the user by stating that they need to activate the tab,
13973
			// but the tab will already be activated by the time the announcement finishes.
13974
			focusedTab.attr( "aria-selected", "false" );
13975
			this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" );
13976
13977
			this.activating = this._delay(function() {
13978
				this.option( "active", selectedIndex );
13979
			}, this.delay );
13980
		}
13981
	},
13982
13983
	_panelKeydown: function( event ) {
13984
		if ( this._handlePageNav( event ) ) {
13985
			return;
13986
		}
13987
13988
		// Ctrl+up moves focus to the current tab
13989
		if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) {
13990
			event.preventDefault();
13991
			this.active.focus();
13992
		}
13993
	},
13994
13995
	// Alt+page up/down moves focus to the previous/next tab (and activates)
13996
	_handlePageNav: function( event ) {
13997
		if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) {
13998
			this._activate( this._focusNextTab( this.options.active - 1, false ) );
13999
			return true;
14000
		}
14001
		if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) {
14002
			this._activate( this._focusNextTab( this.options.active + 1, true ) );
14003
			return true;
14004
		}
14005
	},
14006
14007
	_findNextTab: function( index, goingForward ) {
14008
		var lastTabIndex = this.tabs.length - 1;
14009
14010
		function constrain() {
14011
			if ( index > lastTabIndex ) {
14012
				index = 0;
14013
			}
14014
			if ( index < 0 ) {
14015
				index = lastTabIndex;
14016
			}
14017
			return index;
14018
		}
14019
14020
		while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) {
14021
			index = goingForward ? index + 1 : index - 1;
14022
		}
14023
14024
		return index;
14025
	},
14026
14027
	_focusNextTab: function( index, goingForward ) {
14028
		index = this._findNextTab( index, goingForward );
14029
		this.tabs.eq( index ).focus();
14030
		return index;
14031
	},
14032
14033
	_setOption: function( key, value ) {
14034
		if ( key === "active" ) {
14035
			// _activate() will handle invalid values and update this.options
14036
			this._activate( value );
14037
			return;
14038
		}
14039
14040
		if ( key === "disabled" ) {
14041
			// don't use the widget factory's disabled handling
14042
			this._setupDisabled( value );
14043
			return;
14044
		}
14045
14046
		this._super( key, value);
14047
14048
		if ( key === "collapsible" ) {
14049
			this.element.toggleClass( "ui-tabs-collapsible", value );
14050
			// Setting collapsible: false while collapsed; open first panel
14051
			if ( !value && this.options.active === false ) {
14052
				this._activate( 0 );
14053
			}
14054
		}
14055
14056
		if ( key === "event" ) {
14057
			this._setupEvents( value );
14058
		}
14059
14060
		if ( key === "heightStyle" ) {
14061
			this._setupHeightStyle( value );
14062
		}
14063
	},
14064
14065
	_tabId: function( tab ) {
14066
		return tab.attr( "aria-controls" ) || "ui-tabs-" + getNextTabId();
14067
	},
14068
14069
	_sanitizeSelector: function( hash ) {
14070
		return hash ? hash.replace( /[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&" ) : "";
14071
	},
14072
14073
	refresh: function() {
14074
		var options = this.options,
14075
			lis = this.tablist.children( ":has(a[href])" );
14076
14077
		// get disabled tabs from class attribute from HTML
14078
		// this will get converted to a boolean if needed in _refresh()
14079
		options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) {
14080
			return lis.index( tab );
14081
		});
14082
14083
		this._processTabs();
14084
14085
		// was collapsed or no tabs
14086
		if ( options.active === false || !this.anchors.length ) {
14087
			options.active = false;
14088
			this.active = $();
14089
		// was active, but active tab is gone
14090
		} else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) {
14091
			// all remaining tabs are disabled
14092
			if ( this.tabs.length === options.disabled.length ) {
14093
				options.active = false;
14094
				this.active = $();
14095
			// activate previous tab
14096
			} else {
14097
				this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) );
14098
			}
14099
		// was active, active tab still exists
14100
		} else {
14101
			// make sure active index is correct
14102
			options.active = this.tabs.index( this.active );
14103
		}
14104
14105
		this._refresh();
14106
	},
14107
14108
	_refresh: function() {
14109
		this._setupDisabled( this.options.disabled );
14110
		this._setupEvents( this.options.event );
14111
		this._setupHeightStyle( this.options.heightStyle );
14112
14113
		this.tabs.not( this.active ).attr({
14114
			"aria-selected": "false",
14115
			tabIndex: -1
14116
		});
14117
		this.panels.not( this._getPanelForTab( this.active ) )
14118
			.hide()
14119
			.attr({
14120
				"aria-expanded": "false",
14121
				"aria-hidden": "true"
14122
			});
14123
14124
		// Make sure one tab is in the tab order
14125
		if ( !this.active.length ) {
14126
			this.tabs.eq( 0 ).attr( "tabIndex", 0 );
14127
		} else {
14128
			this.active
14129
				.addClass( "ui-tabs-active ui-state-active" )
14130
				.attr({
14131
					"aria-selected": "true",
14132
					tabIndex: 0
14133
				});
14134
			this._getPanelForTab( this.active )
14135
				.show()
14136
				.attr({
14137
					"aria-expanded": "true",
14138
					"aria-hidden": "false"
14139
				});
14140
		}
14141
	},
14142
14143
	_processTabs: function() {
14144
		var that = this;
14145
14146
		this.tablist = this._getList()
14147
			.addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" )
14148
			.attr( "role", "tablist" );
14149
14150
		this.tabs = this.tablist.find( "> li:has(a[href])" )
14151
			.addClass( "ui-state-default ui-corner-top" )
14152
			.attr({
14153
				role: "tab",
14154
				tabIndex: -1
14155
			});
14156
14157
		this.anchors = this.tabs.map(function() {
14158
				return $( "a", this )[ 0 ];
14159
			})
14160
			.addClass( "ui-tabs-anchor" )
14161
			.attr({
14162
				role: "presentation",
14163
				tabIndex: -1
14164
			});
14165
14166
		this.panels = $();
14167
14168
		this.anchors.each(function( i, anchor ) {
14169
			var selector, panel, panelId,
14170
				anchorId = $( anchor ).uniqueId().attr( "id" ),
14171
				tab = $( anchor ).closest( "li" ),
14172
				originalAriaControls = tab.attr( "aria-controls" );
14173
14174
			// inline tab
14175
			if ( isLocal( anchor ) ) {
14176
				selector = anchor.hash;
14177
				panel = that.element.find( that._sanitizeSelector( selector ) );
14178
			// remote tab
14179
			} else {
14180
				panelId = that._tabId( tab );
14181
				selector = "#" + panelId;
14182
				panel = that.element.find( selector );
14183
				if ( !panel.length ) {
14184
					panel = that._createPanel( panelId );
14185
					panel.insertAfter( that.panels[ i - 1 ] || that.tablist );
14186
				}
14187
				panel.attr( "aria-live", "polite" );
14188
			}
14189
14190
			if ( panel.length) {
14191
				that.panels = that.panels.add( panel );
14192
			}
14193
			if ( originalAriaControls ) {
14194
				tab.data( "ui-tabs-aria-controls", originalAriaControls );
14195
			}
14196
			tab.attr({
14197
				"aria-controls": selector.substring( 1 ),
14198
				"aria-labelledby": anchorId
14199
			});
14200
			panel.attr( "aria-labelledby", anchorId );
14201
		});
14202
14203
		this.panels
14204
			.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
14205
			.attr( "role", "tabpanel" );
14206
	},
14207
14208
	// allow overriding how to find the list for rare usage scenarios (#7715)
14209
	_getList: function() {
14210
		return this.element.find( "ol,ul" ).eq( 0 );
14211
	},
14212
14213
	_createPanel: function( id ) {
14214
		return $( "<div>" )
14215
			.attr( "id", id )
14216
			.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
14217
			.data( "ui-tabs-destroy", true );
14218
	},
14219
14220
	_setupDisabled: function( disabled ) {
14221
		if ( $.isArray( disabled ) ) {
14222
			if ( !disabled.length ) {
14223
				disabled = false;
14224
			} else if ( disabled.length === this.anchors.length ) {
14225
				disabled = true;
14226
			}
14227
		}
14228
14229
		// disable tabs
14230
		for ( var i = 0, li; ( li = this.tabs[ i ] ); i++ ) {
14231
			if ( disabled === true || $.inArray( i, disabled ) !== -1 ) {
14232
				$( li )
14233
					.addClass( "ui-state-disabled" )
14234
					.attr( "aria-disabled", "true" );
14235
			} else {
14236
				$( li )
14237
					.removeClass( "ui-state-disabled" )
14238
					.removeAttr( "aria-disabled" );
14239
			}
14240
		}
14241
14242
		this.options.disabled = disabled;
14243
	},
14244
14245
	_setupEvents: function( event ) {
14246
		var events = {
14247
			click: function( event ) {
14248
				event.preventDefault();
14249
			}
14250
		};
14251
		if ( event ) {
14252
			$.each( event.split(" "), function( index, eventName ) {
14253
				events[ eventName ] = "_eventHandler";
14254
			});
14255
		}
14256
14257
		this._off( this.anchors.add( this.tabs ).add( this.panels ) );
14258
		this._on( this.anchors, events );
14259
		this._on( this.tabs, { keydown: "_tabKeydown" } );
14260
		this._on( this.panels, { keydown: "_panelKeydown" } );
14261
14262
		this._focusable( this.tabs );
14263
		this._hoverable( this.tabs );
14264
	},
14265
14266
	_setupHeightStyle: function( heightStyle ) {
14267
		var maxHeight,
14268
			parent = this.element.parent();
14269
14270
		if ( heightStyle === "fill" ) {
14271
			maxHeight = parent.height();
14272
			maxHeight -= this.element.outerHeight() - this.element.height();
14273
14274
			this.element.siblings( ":visible" ).each(function() {
14275
				var elem = $( this ),
14276
					position = elem.css( "position" );
14277
14278
				if ( position === "absolute" || position === "fixed" ) {
14279
					return;
14280
				}
14281
				maxHeight -= elem.outerHeight( true );
14282
			});
14283
14284
			this.element.children().not( this.panels ).each(function() {
14285
				maxHeight -= $( this ).outerHeight( true );
14286
			});
14287
14288
			this.panels.each(function() {
14289
				$( this ).height( Math.max( 0, maxHeight -
14290
					$( this ).innerHeight() + $( this ).height() ) );
14291
			})
14292
			.css( "overflow", "auto" );
14293
		} else if ( heightStyle === "auto" ) {
14294
			maxHeight = 0;
14295
			this.panels.each(function() {
14296
				maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
14297
			}).height( maxHeight );
14298
		}
14299
	},
14300
14301
	_eventHandler: function( event ) {
14302
		var options = this.options,
14303
			active = this.active,
14304
			anchor = $( event.currentTarget ),
14305
			tab = anchor.closest( "li" ),
14306
			clickedIsActive = tab[ 0 ] === active[ 0 ],
14307
			collapsing = clickedIsActive && options.collapsible,
14308
			toShow = collapsing ? $() : this._getPanelForTab( tab ),
14309
			toHide = !active.length ? $() : this._getPanelForTab( active ),
14310
			eventData = {
14311
				oldTab: active,
14312
				oldPanel: toHide,
14313
				newTab: collapsing ? $() : tab,
14314
				newPanel: toShow
14315
			};
14316
14317
		event.preventDefault();
14318
14319
		if ( tab.hasClass( "ui-state-disabled" ) ||
14320
				// tab is already loading
14321
				tab.hasClass( "ui-tabs-loading" ) ||
14322
				// can't switch durning an animation
14323
				this.running ||
14324
				// click on active header, but not collapsible
14325
				( clickedIsActive && !options.collapsible ) ||
14326
				// allow canceling activation
14327
				( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
14328
			return;
14329
		}
14330
14331
		options.active = collapsing ? false : this.tabs.index( tab );
14332
14333
		this.active = clickedIsActive ? $() : tab;
14334
		if ( this.xhr ) {
14335
			this.xhr.abort();
14336
		}
14337
14338
		if ( !toHide.length && !toShow.length ) {
14339
			$.error( "jQuery UI Tabs: Mismatching fragment identifier." );
14340
		}
14341
14342
		if ( toShow.length ) {
14343
			this.load( this.tabs.index( tab ), event );
14344
		}
14345
		this._toggle( event, eventData );
14346
	},
14347
14348
	// handles show/hide for selecting tabs
14349
	_toggle: function( event, eventData ) {
14350
		var that = this,
14351
			toShow = eventData.newPanel,
14352
			toHide = eventData.oldPanel;
14353
14354
		this.running = true;
14355
14356
		function complete() {
14357
			that.running = false;
14358
			that._trigger( "activate", event, eventData );
14359
		}
14360
14361
		function show() {
14362
			eventData.newTab.closest( "li" ).addClass( "ui-tabs-active ui-state-active" );
14363
14364
			if ( toShow.length && that.options.show ) {
14365
				that._show( toShow, that.options.show, complete );
14366
			} else {
14367
				toShow.show();
14368
				complete();
14369
			}
14370
		}
14371
14372
		// start out by hiding, then showing, then completing
14373
		if ( toHide.length && this.options.hide ) {
14374
			this._hide( toHide, this.options.hide, function() {
14375
				eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
14376
				show();
14377
			});
14378
		} else {
14379
			eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
14380
			toHide.hide();
14381
			show();
14382
		}
14383
14384
		toHide.attr({
14385
			"aria-expanded": "false",
14386
			"aria-hidden": "true"
14387
		});
14388
		eventData.oldTab.attr( "aria-selected", "false" );
14389
		// If we're switching tabs, remove the old tab from the tab order.
14390
		// If we're opening from collapsed state, remove the previous tab from the tab order.
14391
		// If we're collapsing, then keep the collapsing tab in the tab order.
14392
		if ( toShow.length && toHide.length ) {
14393
			eventData.oldTab.attr( "tabIndex", -1 );
14394
		} else if ( toShow.length ) {
14395
			this.tabs.filter(function() {
14396
				return $( this ).attr( "tabIndex" ) === 0;
14397
			})
14398
			.attr( "tabIndex", -1 );
14399
		}
14400
14401
		toShow.attr({
14402
			"aria-expanded": "true",
14403
			"aria-hidden": "false"
14404
		});
14405
		eventData.newTab.attr({
14406
			"aria-selected": "true",
14407
			tabIndex: 0
14408
		});
14409
	},
14410
14411
	_activate: function( index ) {
14412
		var anchor,
14413
			active = this._findActive( index );
14414
14415
		// trying to activate the already active panel
14416
		if ( active[ 0 ] === this.active[ 0 ] ) {
14417
			return;
14418
		}
14419
14420
		// trying to collapse, simulate a click on the current active header
14421
		if ( !active.length ) {
14422
			active = this.active;
14423
		}
14424
14425
		anchor = active.find( ".ui-tabs-anchor" )[ 0 ];
14426
		this._eventHandler({
14427
			target: anchor,
14428
			currentTarget: anchor,
14429
			preventDefault: $.noop
14430
		});
14431
	},
14432
14433
	_findActive: function( index ) {
14434
		return index === false ? $() : this.tabs.eq( index );
14435
	},
14436
14437
	_getIndex: function( index ) {
14438
		// meta-function to give users option to provide a href string instead of a numerical index.
14439
		if ( typeof index === "string" ) {
14440
			index = this.anchors.index( this.anchors.filter( "[href$='" + index + "']" ) );
14441
		}
14442
14443
		return index;
14444
	},
14445
14446
	_destroy: function() {
14447
		if ( this.xhr ) {
14448
			this.xhr.abort();
14449
		}
14450
14451
		this.element.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" );
14452
14453
		this.tablist
14454
			.removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" )
14455
			.removeAttr( "role" );
14456
14457
		this.anchors
14458
			.removeClass( "ui-tabs-anchor" )
14459
			.removeAttr( "role" )
14460
			.removeAttr( "tabIndex" )
14461
			.removeUniqueId();
14462
14463
		this.tabs.add( this.panels ).each(function() {
14464
			if ( $.data( this, "ui-tabs-destroy" ) ) {
14465
				$( this ).remove();
14466
			} else {
14467
				$( this )
14468
					.removeClass( "ui-state-default ui-state-active ui-state-disabled " +
14469
						"ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel" )
14470
					.removeAttr( "tabIndex" )
14471
					.removeAttr( "aria-live" )
14472
					.removeAttr( "aria-busy" )
14473
					.removeAttr( "aria-selected" )
14474
					.removeAttr( "aria-labelledby" )
14475
					.removeAttr( "aria-hidden" )
14476
					.removeAttr( "aria-expanded" )
14477
					.removeAttr( "role" );
14478
			}
14479
		});
14480
14481
		this.tabs.each(function() {
14482
			var li = $( this ),
14483
				prev = li.data( "ui-tabs-aria-controls" );
14484
			if ( prev ) {
14485
				li
14486
					.attr( "aria-controls", prev )
14487
					.removeData( "ui-tabs-aria-controls" );
14488
			} else {
14489
				li.removeAttr( "aria-controls" );
14490
			}
14491
		});
14492
14493
		this.panels.show();
14494
14495
		if ( this.options.heightStyle !== "content" ) {
14496
			this.panels.css( "height", "" );
14497
		}
14498
	},
14499
14500
	enable: function( index ) {
14501
		var disabled = this.options.disabled;
14502
		if ( disabled === false ) {
14503
			return;
14504
		}
14505
14506
		if ( index === undefined ) {
14507
			disabled = false;
14508
		} else {
14509
			index = this._getIndex( index );
14510
			if ( $.isArray( disabled ) ) {
14511
				disabled = $.map( disabled, function( num ) {
14512
					return num !== index ? num : null;
14513
				});
14514
			} else {
14515
				disabled = $.map( this.tabs, function( li, num ) {
14516
					return num !== index ? num : null;
14517
				});
14518
			}
14519
		}
14520
		this._setupDisabled( disabled );
14521
	},
14522
14523
	disable: function( index ) {
14524
		var disabled = this.options.disabled;
14525
		if ( disabled === true ) {
14526
			return;
14527
		}
14528
14529
		if ( index === undefined ) {
14530
			disabled = true;
14531
		} else {
14532
			index = this._getIndex( index );
14533
			if ( $.inArray( index, disabled ) !== -1 ) {
14534
				return;
14535
			}
14536
			if ( $.isArray( disabled ) ) {
14537
				disabled = $.merge( [ index ], disabled ).sort();
14538
			} else {
14539
				disabled = [ index ];
14540
			}
14541
		}
14542
		this._setupDisabled( disabled );
14543
	},
14544
14545
	load: function( index, event ) {
14546
		index = this._getIndex( index );
14547
		var that = this,
14548
			tab = this.tabs.eq( index ),
14549
			anchor = tab.find( ".ui-tabs-anchor" ),
14550
			panel = this._getPanelForTab( tab ),
14551
			eventData = {
14552
				tab: tab,
14553
				panel: panel
14554
			};
14555
14556
		// not remote
14557
		if ( isLocal( anchor[ 0 ] ) ) {
14558
			return;
14559
		}
14560
14561
		this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) );
14562
14563
		// support: jQuery <1.8
14564
		// jQuery <1.8 returns false if the request is canceled in beforeSend,
14565
		// but as of 1.8, $.ajax() always returns a jqXHR object.
14566
		if ( this.xhr && this.xhr.statusText !== "canceled" ) {
14567
			tab.addClass( "ui-tabs-loading" );
14568
			panel.attr( "aria-busy", "true" );
14569
14570
			this.xhr
14571
				.success(function( response ) {
14572
					// support: jQuery <1.8
14573
					// http://bugs.jquery.com/ticket/11778
14574
					setTimeout(function() {
14575
						panel.html( response );
14576
						that._trigger( "load", event, eventData );
14577
					}, 1 );
14578
				})
14579
				.complete(function( jqXHR, status ) {
14580
					// support: jQuery <1.8
14581
					// http://bugs.jquery.com/ticket/11778
14582
					setTimeout(function() {
14583
						if ( status === "abort" ) {
14584
							that.panels.stop( false, true );
14585
						}
14586
14587
						tab.removeClass( "ui-tabs-loading" );
14588
						panel.removeAttr( "aria-busy" );
14589
14590
						if ( jqXHR === that.xhr ) {
14591
							delete that.xhr;
14592
						}
14593
					}, 1 );
14594
				});
14595
		}
14596
	},
14597
14598
	_ajaxSettings: function( anchor, event, eventData ) {
14599
		var that = this;
14600
		return {
14601
			url: anchor.attr( "href" ),
14602
			beforeSend: function( jqXHR, settings ) {
14603
				return that._trigger( "beforeLoad", event,
14604
					$.extend( { jqXHR : jqXHR, ajaxSettings: settings }, eventData ) );
14605
			}
14606
		};
14607
	},
14608
14609
	_getPanelForTab: function( tab ) {
14610
		var id = $( tab ).attr( "aria-controls" );
14611
		return this.element.find( this._sanitizeSelector( "#" + id ) );
14612
	}
14613
});
14614
14615
})( jQuery );
14616
14617
(function( $ ) {
14618
14619
var increments = 0;
14620
14621
function addDescribedBy( elem, id ) {
14622
	var describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ );
14623
	describedby.push( id );
14624
	elem
14625
		.data( "ui-tooltip-id", id )
14626
		.attr( "aria-describedby", $.trim( describedby.join( " " ) ) );
14627
}
14628
14629
function removeDescribedBy( elem ) {
14630
	var id = elem.data( "ui-tooltip-id" ),
14631
		describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ ),
14632
		index = $.inArray( id, describedby );
14633
	if ( index !== -1 ) {
14634
		describedby.splice( index, 1 );
14635
	}
14636
14637
	elem.removeData( "ui-tooltip-id" );
14638
	describedby = $.trim( describedby.join( " " ) );
14639
	if ( describedby ) {
14640
		elem.attr( "aria-describedby", describedby );
14641
	} else {
14642
		elem.removeAttr( "aria-describedby" );
14643
	}
14644
}
14645
14646
$.widget( "ui.tooltip", {
14647
	version: "1.10.3",
14648
	options: {
14649
		content: function() {
14650
			// support: IE<9, Opera in jQuery <1.7
14651
			// .text() can't accept undefined, so coerce to a string
14652
			var title = $( this ).attr( "title" ) || "";
14653
			// Escape title, since we're going from an attribute to raw HTML
14654
			return $( "<a>" ).text( title ).html();
14655
		},
14656
		hide: true,
14657
		// Disabled elements have inconsistent behavior across browsers (#8661)
14658
		items: "[title]:not([disabled])",
14659
		position: {
14660
			my: "left top+15",
14661
			at: "left bottom",
14662
			collision: "flipfit flip"
14663
		},
14664
		show: true,
14665
		tooltipClass: null,
14666
		track: false,
14667
14668
		// callbacks
14669
		close: null,
14670
		open: null
14671
	},
14672
14673
	_create: function() {
14674
		this._on({
14675
			mouseover: "open",
14676
			focusin: "open"
14677
		});
14678
14679
		// IDs of generated tooltips, needed for destroy
14680
		this.tooltips = {};
14681
		// IDs of parent tooltips where we removed the title attribute
14682
		this.parents = {};
14683
14684
		if ( this.options.disabled ) {
14685
			this._disable();
14686
		}
14687
	},
14688
14689
	_setOption: function( key, value ) {
14690
		var that = this;
14691
14692
		if ( key === "disabled" ) {
14693
			this[ value ? "_disable" : "_enable" ]();
14694
			this.options[ key ] = value;
14695
			// disable element style changes
14696
			return;
14697
		}
14698
14699
		this._super( key, value );
14700
14701
		if ( key === "content" ) {
14702
			$.each( this.tooltips, function( id, element ) {
14703
				that._updateContent( element );
14704
			});
14705
		}
14706
	},
14707
14708
	_disable: function() {
14709
		var that = this;
14710
14711
		// close open tooltips
14712
		$.each( this.tooltips, function( id, element ) {
14713
			var event = $.Event( "blur" );
14714
			event.target = event.currentTarget = element[0];
14715
			that.close( event, true );
14716
		});
14717
14718
		// remove title attributes to prevent native tooltips
14719
		this.element.find( this.options.items ).addBack().each(function() {
14720
			var element = $( this );
14721
			if ( element.is( "[title]" ) ) {
14722
				element
14723
					.data( "ui-tooltip-title", element.attr( "title" ) )
14724
					.attr( "title", "" );
14725
			}
14726
		});
14727
	},
14728
14729
	_enable: function() {
14730
		// restore title attributes
14731
		this.element.find( this.options.items ).addBack().each(function() {
14732
			var element = $( this );
14733
			if ( element.data( "ui-tooltip-title" ) ) {
14734
				element.attr( "title", element.data( "ui-tooltip-title" ) );
14735
			}
14736
		});
14737
	},
14738
14739
	open: function( event ) {
14740
		var that = this,
14741
			target = $( event ? event.target : this.element )
14742
				// we need closest here due to mouseover bubbling,
14743
				// but always pointing at the same event target
14744
				.closest( this.options.items );
14745
14746
		// No element to show a tooltip for or the tooltip is already open
14747
		if ( !target.length || target.data( "ui-tooltip-id" ) ) {
14748
			return;
14749
		}
14750
14751
		if ( target.attr( "title" ) ) {
14752
			target.data( "ui-tooltip-title", target.attr( "title" ) );
14753
		}
14754
14755
		target.data( "ui-tooltip-open", true );
14756
14757
		// kill parent tooltips, custom or native, for hover
14758
		if ( event && event.type === "mouseover" ) {
14759
			target.parents().each(function() {
14760
				var parent = $( this ),
14761
					blurEvent;
14762
				if ( parent.data( "ui-tooltip-open" ) ) {
14763
					blurEvent = $.Event( "blur" );
14764
					blurEvent.target = blurEvent.currentTarget = this;
14765
					that.close( blurEvent, true );
14766
				}
14767
				if ( parent.attr( "title" ) ) {
14768
					parent.uniqueId();
14769
					that.parents[ this.id ] = {
14770
						element: this,
14771
						title: parent.attr( "title" )
14772
					};
14773
					parent.attr( "title", "" );
14774
				}
14775
			});
14776
		}
14777
14778
		this._updateContent( target, event );
14779
	},
14780
14781
	_updateContent: function( target, event ) {
14782
		var content,
14783
			contentOption = this.options.content,
14784
			that = this,
14785
			eventType = event ? event.type : null;
14786
14787
		if ( typeof contentOption === "string" ) {
14788
			return this._open( event, target, contentOption );
14789
		}
14790
14791
		content = contentOption.call( target[0], function( response ) {
14792
			// ignore async response if tooltip was closed already
14793
			if ( !target.data( "ui-tooltip-open" ) ) {
14794
				return;
14795
			}
14796
			// IE may instantly serve a cached response for ajax requests
14797
			// delay this call to _open so the other call to _open runs first
14798
			that._delay(function() {
14799
				// jQuery creates a special event for focusin when it doesn't
14800
				// exist natively. To improve performance, the native event
14801
				// object is reused and the type is changed. Therefore, we can't
14802
				// rely on the type being correct after the event finished
14803
				// bubbling, so we set it back to the previous value. (#8740)
14804
				if ( event ) {
14805
					event.type = eventType;
14806
				}
14807
				this._open( event, target, response );
14808
			});
14809
		});
14810
		if ( content ) {
14811
			this._open( event, target, content );
14812
		}
14813
	},
14814
14815
	_open: function( event, target, content ) {
14816
		var tooltip, events, delayedShow,
14817
			positionOption = $.extend( {}, this.options.position );
14818
14819
		if ( !content ) {
14820
			return;
14821
		}
14822
14823
		// Content can be updated multiple times. If the tooltip already
14824
		// exists, then just update the content and bail.
14825
		tooltip = this._find( target );
14826
		if ( tooltip.length ) {
14827
			tooltip.find( ".ui-tooltip-content" ).html( content );
14828
			return;
14829
		}
14830
14831
		// if we have a title, clear it to prevent the native tooltip
14832
		// we have to check first to avoid defining a title if none exists
14833
		// (we don't want to cause an element to start matching [title])
14834
		//
14835
		// We use removeAttr only for key events, to allow IE to export the correct
14836
		// accessible attributes. For mouse events, set to empty string to avoid
14837
		// native tooltip showing up (happens only when removing inside mouseover).
14838
		if ( target.is( "[title]" ) ) {
14839
			if ( event && event.type === "mouseover" ) {
14840
				target.attr( "title", "" );
14841
			} else {
14842
				target.removeAttr( "title" );
14843
			}
14844
		}
14845
14846
		tooltip = this._tooltip( target );
14847
		addDescribedBy( target, tooltip.attr( "id" ) );
14848
		tooltip.find( ".ui-tooltip-content" ).html( content );
14849
14850
		function position( event ) {
14851
			positionOption.of = event;
14852
			if ( tooltip.is( ":hidden" ) ) {
14853
				return;
14854
			}
14855
			tooltip.position( positionOption );
14856
		}
14857
		if ( this.options.track && event && /^mouse/.test( event.type ) ) {
14858
			this._on( this.document, {
14859
				mousemove: position
14860
			});
14861
			// trigger once to override element-relative positioning
14862
			position( event );
14863
		} else {
14864
			tooltip.position( $.extend({
14865
				of: target
14866
			}, this.options.position ) );
14867
		}
14868
14869
		tooltip.hide();
14870
14871
		this._show( tooltip, this.options.show );
14872
		// Handle tracking tooltips that are shown with a delay (#8644). As soon
14873
		// as the tooltip is visible, position the tooltip using the most recent
14874
		// event.
14875
		if ( this.options.show && this.options.show.delay ) {
14876
			delayedShow = this.delayedShow = setInterval(function() {
14877
				if ( tooltip.is( ":visible" ) ) {
14878
					position( positionOption.of );
14879
					clearInterval( delayedShow );
14880
				}
14881
			}, $.fx.interval );
14882
		}
14883
14884
		this._trigger( "open", event, { tooltip: tooltip } );
14885
14886
		events = {
14887
			keyup: function( event ) {
14888
				if ( event.keyCode === $.ui.keyCode.ESCAPE ) {
14889
					var fakeEvent = $.Event(event);
14890
					fakeEvent.currentTarget = target[0];
14891
					this.close( fakeEvent, true );
14892
				}
14893
			},
14894
			remove: function() {
14895
				this._removeTooltip( tooltip );
14896
			}
14897
		};
14898
		if ( !event || event.type === "mouseover" ) {
14899
			events.mouseleave = "close";
14900
		}
14901
		if ( !event || event.type === "focusin" ) {
14902
			events.focusout = "close";
14903
		}
14904
		this._on( true, target, events );
14905
	},
14906
14907
	close: function( event ) {
14908
		var that = this,
14909
			target = $( event ? event.currentTarget : this.element ),
14910
			tooltip = this._find( target );
14911
14912
		// disabling closes the tooltip, so we need to track when we're closing
14913
		// to avoid an infinite loop in case the tooltip becomes disabled on close
14914
		if ( this.closing ) {
14915
			return;
14916
		}
14917
14918
		// Clear the interval for delayed tracking tooltips
14919
		clearInterval( this.delayedShow );
14920
14921
		// only set title if we had one before (see comment in _open())
14922
		if ( target.data( "ui-tooltip-title" ) ) {
14923
			target.attr( "title", target.data( "ui-tooltip-title" ) );
14924
		}
14925
14926
		removeDescribedBy( target );
14927
14928
		tooltip.stop( true );
14929
		this._hide( tooltip, this.options.hide, function() {
14930
			that._removeTooltip( $( this ) );
14931
		});
14932
14933
		target.removeData( "ui-tooltip-open" );
14934
		this._off( target, "mouseleave focusout keyup" );
14935
		// Remove 'remove' binding only on delegated targets
14936
		if ( target[0] !== this.element[0] ) {
14937
			this._off( target, "remove" );
14938
		}
14939
		this._off( this.document, "mousemove" );
14940
14941
		if ( event && event.type === "mouseleave" ) {
14942
			$.each( this.parents, function( id, parent ) {
14943
				$( parent.element ).attr( "title", parent.title );
14944
				delete that.parents[ id ];
14945
			});
14946
		}
14947
14948
		this.closing = true;
14949
		this._trigger( "close", event, { tooltip: tooltip } );
14950
		this.closing = false;
14951
	},
14952
14953
	_tooltip: function( element ) {
14954
		var id = "ui-tooltip-" + increments++,
14955
			tooltip = $( "<div>" )
14956
				.attr({
14957
					id: id,
14958
					role: "tooltip"
14959
				})
14960
				.addClass( "ui-tooltip ui-widget ui-corner-all ui-widget-content " +
14961
					( this.options.tooltipClass || "" ) );
14962
		$( "<div>" )
14963
			.addClass( "ui-tooltip-content" )
14964
			.appendTo( tooltip );
14965
		tooltip.appendTo( this.document[0].body );
14966
		this.tooltips[ id ] = element;
14967
		return tooltip;
14968
	},
14969
14970
	_find: function( target ) {
14971
		var id = target.data( "ui-tooltip-id" );
14972
		return id ? $( "#" + id ) : $();
14973
	},
14974
14975
	_removeTooltip: function( tooltip ) {
14976
		tooltip.remove();
14977
		delete this.tooltips[ tooltip.attr( "id" ) ];
14978
	},
14979
14980
	_destroy: function() {
14981
		var that = this;
14982
14983
		// close open tooltips
14984
		$.each( this.tooltips, function( id, element ) {
14985
			// Delegate to close method to handle common cleanup
14986
			var event = $.Event( "blur" );
14987
			event.target = event.currentTarget = element[0];
14988
			that.close( event, true );
14989
14990
			// Remove immediately; destroying an open tooltip doesn't use the
14991
			// hide animation
14992
			$( "#" + id ).remove();
14993
14994
			// Restore the title
14995
			if ( element.data( "ui-tooltip-title" ) ) {
14996
				element.attr( "title", element.data( "ui-tooltip-title" ) );
14997
				element.removeData( "ui-tooltip-title" );
14998
			}
14999
		});
15000
	}
15001
});
15002
15003
}( jQuery ) );
15004