1
+/*! jQuery UI - v1.12.1 - 2017-08-04
2
+* http://jqueryui.com
3
+* Includes: widget.js, position.js, data.js, disable-selection.js, focusable.js, form-reset-mixin.js, jquery-1-7.js, keycode.js, labels.js, scroll-parent.js, tabbable.js, unique-id.js, widgets/datepicker.js
4
+* Copyright jQuery Foundation and other contributors; Licensed MIT */
5
+
6
+(function( factory ) {
7
+ if ( typeof define === "function" && define.amd ) {
8
+
9
+ // AMD. Register as an anonymous module.
10
+ define([ "jquery" ], factory );
11
+ } else {
12
+
13
+ // Browser globals
14
+ factory( jQuery );
15
+ }
16
+}(function( $ ) {
17
+
18
+$.ui = $.ui || {};
19
+
20
+var version = $.ui.version = "1.12.1";
21
+
22
+
23
+/*!
24
+ * jQuery UI Widget 1.12.1
25
+ * http://jqueryui.com
26
+ *
27
+ * Copyright jQuery Foundation and other contributors
28
+ * Released under the MIT license.
29
+ * http://jquery.org/license
30
+ */
31
+
32
+//>>label: Widget
33
+//>>group: Core
34
+//>>description: Provides a factory for creating stateful widgets with a common API.
35
+//>>docs: http://api.jqueryui.com/jQuery.widget/
36
+//>>demos: http://jqueryui.com/widget/
37
+
38
+
39
+
40
+var widgetUuid = 0;
41
+var widgetSlice = Array.prototype.slice;
42
+
43
+$.cleanData = ( function( orig ) {
44
+ return function( elems ) {
45
+ var events, elem, i;
46
+ for ( i = 0; ( elem = elems[ i ] ) != null; i++ ) {
47
+ try {
48
+
49
+ // Only trigger remove when necessary to save time
50
+ events = $._data( elem, "events" );
51
+ if ( events && events.remove ) {
52
+ $( elem ).triggerHandler( "remove" );
53
+ }
54
+
55
+ // Http://bugs.jquery.com/ticket/8235
56
+ } catch ( e ) {}
57
+ }
58
+ orig( elems );
59
+ };
60
+} )( $.cleanData );
61
+
62
+$.widget = function( name, base, prototype ) {
63
+ var existingConstructor, constructor, basePrototype;
64
+
65
+ // ProxiedPrototype allows the provided prototype to remain unmodified
66
+ // so that it can be used as a mixin for multiple widgets (#8876)
67
+ var proxiedPrototype = {};
68
+
69
+ var namespace = name.split( "." )[ 0 ];
70
+ name = name.split( "." )[ 1 ];
71
+ var fullName = namespace + "-" + name;
72
+
73
+ if ( !prototype ) {
74
+ prototype = base;
75
+ base = $.Widget;
76
+ }
77
+
78
+ if ( $.isArray( prototype ) ) {
79
+ prototype = $.extend.apply( null, [ {} ].concat( prototype ) );
80
+ }
81
+
82
+ // Create selector for plugin
83
+ $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
84
+ return !!$.data( elem, fullName );
85
+ };
86
+
87
+ $[ namespace ] = $[ namespace ] || {};
88
+ existingConstructor = $[ namespace ][ name ];
89
+ constructor = $[ namespace ][ name ] = function( options, element ) {
90
+
91
+ // Allow instantiation without "new" keyword
92
+ if ( !this._createWidget ) {
93
+ return new constructor( options, element );
94
+ }
95
+
96
+ // Allow instantiation without initializing for simple inheritance
97
+ // must use "new" keyword (the code above always passes args)
98
+ if ( arguments.length ) {
99
+ this._createWidget( options, element );
100
+ }
101
+ };
102
+
103
+ // Extend with the existing constructor to carry over any static properties
104
+ $.extend( constructor, existingConstructor, {
105
+ version: prototype.version,
106
+
107
+ // Copy the object used to create the prototype in case we need to
108
+ // redefine the widget later
109
+ _proto: $.extend( {}, prototype ),
110
+
111
+ // Track widgets that inherit from this widget in case this widget is
112
+ // redefined after a widget inherits from it
113
+ _childConstructors: []
114
+ } );
115
+
116
+ basePrototype = new base();
117
+
118
+ // We need to make the options hash a property directly on the new instance
119
+ // otherwise we'll modify the options hash on the prototype that we're
120
+ // inheriting from
121
+ basePrototype.options = $.widget.extend( {}, basePrototype.options );
122
+ $.each( prototype, function( prop, value ) {
123
+ if ( !$.isFunction( value ) ) {
124
+ proxiedPrototype[ prop ] = value;
125
+ return;
126
+ }
127
+ proxiedPrototype[ prop ] = ( function() {
128
+ function _super() {
129
+ return base.prototype[ prop ].apply( this, arguments );
130
+ }
131
+
132
+ function _superApply( args ) {
133
+ return base.prototype[ prop ].apply( this, args );
134
+ }
135
+
136
+ return function() {
137
+ var __super = this._super;
138
+ var __superApply = this._superApply;
139
+ var returnValue;
140
+
141
+ this._super = _super;
142
+ this._superApply = _superApply;
143
+
144
+ returnValue = value.apply( this, arguments );
145
+
146
+ this._super = __super;
147
+ this._superApply = __superApply;
148
+
149
+ return returnValue;
150
+ };
151
+ } )();
152
+ } );
153
+ constructor.prototype = $.widget.extend( basePrototype, {
154
+
155
+ // TODO: remove support for widgetEventPrefix
156
+ // always use the name + a colon as the prefix, e.g., draggable:start
157
+ // don't prefix for widgets that aren't DOM-based
158
+ widgetEventPrefix: existingConstructor ? ( basePrototype.widgetEventPrefix || name ) : name
159
+ }, proxiedPrototype, {
160
+ constructor: constructor,
161
+ namespace: namespace,
162
+ widgetName: name,
163
+ widgetFullName: fullName
164
+ } );
165
+
166
+ // If this widget is being redefined then we need to find all widgets that
167
+ // are inheriting from it and redefine all of them so that they inherit from
168
+ // the new version of this widget. We're essentially trying to replace one
169
+ // level in the prototype chain.
170
+ if ( existingConstructor ) {
171
+ $.each( existingConstructor._childConstructors, function( i, child ) {
172
+ var childPrototype = child.prototype;
173
+
174
+ // Redefine the child widget using the same prototype that was
175
+ // originally used, but inherit from the new version of the base
176
+ $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor,
177
+ child._proto );
178
+ } );
179
+
180
+ // Remove the list of existing child constructors from the old constructor
181
+ // so the old child constructors can be garbage collected
182
+ delete existingConstructor._childConstructors;
183
+ } else {
184
+ base._childConstructors.push( constructor );
185
+ }
186
+
187
+ $.widget.bridge( name, constructor );
188
+
189
+ return constructor;
190
+};
191
+
192
+$.widget.extend = function( target ) {
193
+ var input = widgetSlice.call( arguments, 1 );
194
+ var inputIndex = 0;
195
+ var inputLength = input.length;
196
+ var key;
197
+ var value;
198
+
199
+ for ( ; inputIndex < inputLength; inputIndex++ ) {
200
+ for ( key in input[ inputIndex ] ) {
201
+ value = input[ inputIndex ][ key ];
202
+ if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
203
+
204
+ // Clone objects
205
+ if ( $.isPlainObject( value ) ) {
206
+ target[ key ] = $.isPlainObject( target[ key ] ) ?
207
+ $.widget.extend( {}, target[ key ], value ) :
208
+
209
+ // Don't extend strings, arrays, etc. with objects
210
+ $.widget.extend( {}, value );
211
+
212
+ // Copy everything else by reference
213
+ } else {
214
+ target[ key ] = value;
215
+ }
216
+ }
217
+ }
218
+ }
219
+ return target;
220
+};
221
+
222
+$.widget.bridge = function( name, object ) {
223
+ var fullName = object.prototype.widgetFullName || name;
224
+ $.fn[ name ] = function( options ) {
225
+ var isMethodCall = typeof options === "string";
226
+ var args = widgetSlice.call( arguments, 1 );
227
+ var returnValue = this;
228
+
229
+ if ( isMethodCall ) {
230
+
231
+ // If this is an empty collection, we need to have the instance method
232
+ // return undefined instead of the jQuery instance
233
+ if ( !this.length && options === "instance" ) {
234
+ returnValue = undefined;
235
+ } else {
236
+ this.each( function() {
237
+ var methodValue;
238
+ var instance = $.data( this, fullName );
239
+
240
+ if ( options === "instance" ) {
241
+ returnValue = instance;
242
+ return false;
243
+ }
244
+
245
+ if ( !instance ) {
246
+ return $.error( "cannot call methods on " + name +
247
+ " prior to initialization; " +
248
+ "attempted to call method '" + options + "'" );
249
+ }
250
+
251
+ if ( !$.isFunction( instance[ options ] ) || options.charAt( 0 ) === "_" ) {
252
+ return $.error( "no such method '" + options + "' for " + name +
253
+ " widget instance" );
254
+ }
255
+
256
+ methodValue = instance[ options ].apply( instance, args );
257
+
258
+ if ( methodValue !== instance && methodValue !== undefined ) {
259
+ returnValue = methodValue && methodValue.jquery ?
260
+ returnValue.pushStack( methodValue.get() ) :
261
+ methodValue;
262
+ return false;
263
+ }
264
+ } );
265
+ }
266
+ } else {
267
+
268
+ // Allow multiple hashes to be passed on init
269
+ if ( args.length ) {
270
+ options = $.widget.extend.apply( null, [ options ].concat( args ) );
271
+ }
272
+
273
+ this.each( function() {
274
+ var instance = $.data( this, fullName );
275
+ if ( instance ) {
276
+ instance.option( options || {} );
277
+ if ( instance._init ) {
278
+ instance._init();
279
+ }
280
+ } else {
281
+ $.data( this, fullName, new object( options, this ) );
282
+ }
283
+ } );
284
+ }
285
+
286
+ return returnValue;
287
+ };
288
+};
289
+
290
+$.Widget = function( /* options, element */ ) {};
291
+$.Widget._childConstructors = [];
292
+
293
+$.Widget.prototype = {
294
+ widgetName: "widget",
295
+ widgetEventPrefix: "",
296
+ defaultElement: "<div>",
297
+
298
+ options: {
299
+ classes: {},
300
+ disabled: false,
301
+
302
+ // Callbacks
303
+ create: null
304
+ },
305
+
306
+ _createWidget: function( options, element ) {
307
+ element = $( element || this.defaultElement || this )[ 0 ];
308
+ this.element = $( element );
309
+ this.uuid = widgetUuid++;
310
+ this.eventNamespace = "." + this.widgetName + this.uuid;
311
+
312
+ this.bindings = $();
313
+ this.hoverable = $();
314
+ this.focusable = $();
315
+ this.classesElementLookup = {};
316
+
317
+ if ( element !== this ) {
318
+ $.data( element, this.widgetFullName, this );
319
+ this._on( true, this.element, {
320
+ remove: function( event ) {
321
+ if ( event.target === element ) {
322
+ this.destroy();
323
+ }
324
+ }
325
+ } );
326
+ this.document = $( element.style ?
327
+
328
+ // Element within the document
329
+ element.ownerDocument :
330
+
331
+ // Element is window or document
332
+ element.document || element );
333
+ this.window = $( this.document[ 0 ].defaultView || this.document[ 0 ].parentWindow );
334
+ }
335
+
336
+ this.options = $.widget.extend( {},
337
+ this.options,
338
+ this._getCreateOptions(),
339
+ options );
340
+
341
+ this._create();
342
+
343
+ if ( this.options.disabled ) {
344
+ this._setOptionDisabled( this.options.disabled );
345
+ }
346
+
347
+ this._trigger( "create", null, this._getCreateEventData() );
348
+ this._init();
349
+ },
350
+
351
+ _getCreateOptions: function() {
352
+ return {};
353
+ },
354
+
355
+ _getCreateEventData: $.noop,
356
+
357
+ _create: $.noop,
358
+
359
+ _init: $.noop,
360
+
361
+ destroy: function() {
362
+ var that = this;
363
+
364
+ this._destroy();
365
+ $.each( this.classesElementLookup, function( key, value ) {
366
+ that._removeClass( value, key );
367
+ } );
368
+
369
+ // We can probably remove the unbind calls in 2.0
370
+ // all event bindings should go through this._on()
371
+ this.element
372
+ .off( this.eventNamespace )
373
+ .removeData( this.widgetFullName );
374
+ this.widget()
375
+ .off( this.eventNamespace )
376
+ .removeAttr( "aria-disabled" );
377
+
378
+ // Clean up events and states
379
+ this.bindings.off( this.eventNamespace );
380
+ },
381
+
382
+ _destroy: $.noop,
383
+
384
+ widget: function() {
385
+ return this.element;
386
+ },
387
+
388
+ option: function( key, value ) {
389
+ var options = key;
390
+ var parts;
391
+ var curOption;
392
+ var i;
393
+
394
+ if ( arguments.length === 0 ) {
395
+
396
+ // Don't return a reference to the internal hash
397
+ return $.widget.extend( {}, this.options );
398
+ }
399
+
400
+ if ( typeof key === "string" ) {
401
+
402
+ // Handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
403
+ options = {};
404
+ parts = key.split( "." );
405
+ key = parts.shift();
406
+ if ( parts.length ) {
407
+ curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
408
+ for ( i = 0; i < parts.length - 1; i++ ) {
409
+ curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
410
+ curOption = curOption[ parts[ i ] ];
411
+ }
412
+ key = parts.pop();
413
+ if ( arguments.length === 1 ) {
414
+ return curOption[ key ] === undefined ? null : curOption[ key ];
415
+ }
416
+ curOption[ key ] = value;
417
+ } else {
418
+ if ( arguments.length === 1 ) {
419
+ return this.options[ key ] === undefined ? null : this.options[ key ];
420
+ }
421
+ options[ key ] = value;
422
+ }
423
+ }
424
+
425
+ this._setOptions( options );
426
+
427
+ return this;
428
+ },
429
+
430
+ _setOptions: function( options ) {
431
+ var key;
432
+
433
+ for ( key in options ) {
434
+ this._setOption( key, options[ key ] );
435
+ }
436
+
437
+ return this;
438
+ },
439
+
440
+ _setOption: function( key, value ) {
441
+ if ( key === "classes" ) {
442
+ this._setOptionClasses( value );
443
+ }
444
+
445
+ this.options[ key ] = value;
446
+
447
+ if ( key === "disabled" ) {
448
+ this._setOptionDisabled( value );
449
+ }
450
+
451
+ return this;
452
+ },
453
+
454
+ _setOptionClasses: function( value ) {
455
+ var classKey, elements, currentElements;
456
+
457
+ for ( classKey in value ) {
458
+ currentElements = this.classesElementLookup[ classKey ];
459
+ if ( value[ classKey ] === this.options.classes[ classKey ] ||
460
+ !currentElements ||
461
+ !currentElements.length ) {
462
+ continue;
463
+ }
464
+
465
+ // We are doing this to create a new jQuery object because the _removeClass() call
466
+ // on the next line is going to destroy the reference to the current elements being
467
+ // tracked. We need to save a copy of this collection so that we can add the new classes
468
+ // below.
469
+ elements = $( currentElements.get() );
470
+ this._removeClass( currentElements, classKey );
471
+
472
+ // We don't use _addClass() here, because that uses this.options.classes
473
+ // for generating the string of classes. We want to use the value passed in from
474
+ // _setOption(), this is the new value of the classes option which was passed to
475
+ // _setOption(). We pass this value directly to _classes().
476
+ elements.addClass( this._classes( {
477
+ element: elements,
478
+ keys: classKey,
479
+ classes: value,
480
+ add: true
481
+ } ) );
482
+ }
483
+ },
484
+
485
+ _setOptionDisabled: function( value ) {
486
+ this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null, !!value );
487
+
488
+ // If the widget is becoming disabled, then nothing is interactive
489
+ if ( value ) {
490
+ this._removeClass( this.hoverable, null, "ui-state-hover" );
491
+ this._removeClass( this.focusable, null, "ui-state-focus" );
492
+ }
493
+ },
494
+
495
+ enable: function() {
496
+ return this._setOptions( { disabled: false } );
497
+ },
498
+
499
+ disable: function() {
500
+ return this._setOptions( { disabled: true } );
501
+ },
502
+
503
+ _classes: function( options ) {
504
+ var full = [];
505
+ var that = this;
506
+
507
+ options = $.extend( {
508
+ element: this.element,
509
+ classes: this.options.classes || {}
510
+ }, options );
511
+
512
+ function processClassString( classes, checkOption ) {
513
+ var current, i;
514
+ for ( i = 0; i < classes.length; i++ ) {
515
+ current = that.classesElementLookup[ classes[ i ] ] || $();
516
+ if ( options.add ) {
517
+ current = $( $.unique( current.get().concat( options.element.get() ) ) );
518
+ } else {
519
+ current = $( current.not( options.element ).get() );
520
+ }
521
+ that.classesElementLookup[ classes[ i ] ] = current;
522
+ full.push( classes[ i ] );
523
+ if ( checkOption && options.classes[ classes[ i ] ] ) {
524
+ full.push( options.classes[ classes[ i ] ] );
525
+ }
526
+ }
527
+ }
528
+
529
+ this._on( options.element, {
530
+ "remove": "_untrackClassesElement"
531
+ } );
532
+
533
+ if ( options.keys ) {
534
+ processClassString( options.keys.match( /\S+/g ) || [], true );
535
+ }
536
+ if ( options.extra ) {
537
+ processClassString( options.extra.match( /\S+/g ) || [] );
538
+ }
539
+
540
+ return full.join( " " );
541
+ },
542
+
543
+ _untrackClassesElement: function( event ) {
544
+ var that = this;
545
+ $.each( that.classesElementLookup, function( key, value ) {
546
+ if ( $.inArray( event.target, value ) !== -1 ) {
547
+ that.classesElementLookup[ key ] = $( value.not( event.target ).get() );
548
+ }
549
+ } );
550
+ },
551
+
552
+ _removeClass: function( element, keys, extra ) {
553
+ return this._toggleClass( element, keys, extra, false );
554
+ },
555
+
556
+ _addClass: function( element, keys, extra ) {
557
+ return this._toggleClass( element, keys, extra, true );
558
+ },
559
+
560
+ _toggleClass: function( element, keys, extra, add ) {
561
+ add = ( typeof add === "boolean" ) ? add : extra;
562
+ var shift = ( typeof element === "string" || element === null ),
563
+ options = {
564
+ extra: shift ? keys : extra,
565
+ keys: shift ? element : keys,
566
+ element: shift ? this.element : element,
567
+ add: add
568
+ };
569
+ options.element.toggleClass( this._classes( options ), add );
570
+ return this;
571
+ },
572
+
573
+ _on: function( suppressDisabledCheck, element, handlers ) {
574
+ var delegateElement;
575
+ var instance = this;
576
+
577
+ // No suppressDisabledCheck flag, shuffle arguments
578
+ if ( typeof suppressDisabledCheck !== "boolean" ) {
579
+ handlers = element;
580
+ element = suppressDisabledCheck;
581
+ suppressDisabledCheck = false;
582
+ }
583
+
584
+ // No element argument, shuffle and use this.element
585
+ if ( !handlers ) {
586
+ handlers = element;
587
+ element = this.element;
588
+ delegateElement = this.widget();
589
+ } else {
590
+ element = delegateElement = $( element );
591
+ this.bindings = this.bindings.add( element );
592
+ }
593
+
594
+ $.each( handlers, function( event, handler ) {
595
+ function handlerProxy() {
596
+
597
+ // Allow widgets to customize the disabled handling
598
+ // - disabled as an array instead of boolean
599
+ // - disabled class as method for disabling individual parts
600
+ if ( !suppressDisabledCheck &&
601
+ ( instance.options.disabled === true ||
602
+ $( this ).hasClass( "ui-state-disabled" ) ) ) {
603
+ return;
604
+ }
605
+ return ( typeof handler === "string" ? instance[ handler ] : handler )
606
+ .apply( instance, arguments );
607
+ }
608
+
609
+ // Copy the guid so direct unbinding works
610
+ if ( typeof handler !== "string" ) {
611
+ handlerProxy.guid = handler.guid =
612
+ handler.guid || handlerProxy.guid || $.guid++;
613
+ }
614
+
615
+ var match = event.match( /^([\w:-]*)\s*(.*)$/ );
616
+ var eventName = match[ 1 ] + instance.eventNamespace;
617
+ var selector = match[ 2 ];
618
+
619
+ if ( selector ) {
620
+ delegateElement.on( eventName, selector, handlerProxy );
621
+ } else {
622
+ element.on( eventName, handlerProxy );
623
+ }
624
+ } );
625
+ },
626
+
627
+ _off: function( element, eventName ) {
628
+ eventName = ( eventName || "" ).split( " " ).join( this.eventNamespace + " " ) +
629
+ this.eventNamespace;
630
+ element.off( eventName ).off( eventName );
631
+
632
+ // Clear the stack to avoid memory leaks (#10056)
633
+ this.bindings = $( this.bindings.not( element ).get() );
634
+ this.focusable = $( this.focusable.not( element ).get() );
635
+ this.hoverable = $( this.hoverable.not( element ).get() );
636
+ },
637
+
638
+ _delay: function( handler, delay ) {
639
+ function handlerProxy() {
640
+ return ( typeof handler === "string" ? instance[ handler ] : handler )
641
+ .apply( instance, arguments );
642
+ }
643
+ var instance = this;
644
+ return setTimeout( handlerProxy, delay || 0 );
645
+ },
646
+
647
+ _hoverable: function( element ) {
648
+ this.hoverable = this.hoverable.add( element );
649
+ this._on( element, {
650
+ mouseenter: function( event ) {
651
+ this._addClass( $( event.currentTarget ), null, "ui-state-hover" );
652
+ },
653
+ mouseleave: function( event ) {
654
+ this._removeClass( $( event.currentTarget ), null, "ui-state-hover" );
655
+ }
656
+ } );
657
+ },
658
+
659
+ _focusable: function( element ) {
660
+ this.focusable = this.focusable.add( element );
661
+ this._on( element, {
662
+ focusin: function( event ) {
663
+ this._addClass( $( event.currentTarget ), null, "ui-state-focus" );
664
+ },
665
+ focusout: function( event ) {
666
+ this._removeClass( $( event.currentTarget ), null, "ui-state-focus" );
667
+ }
668
+ } );
669
+ },
670
+
671
+ _trigger: function( type, event, data ) {
672
+ var prop, orig;
673
+ var callback = this.options[ type ];
674
+
675
+ data = data || {};
676
+ event = $.Event( event );
677
+ event.type = ( type === this.widgetEventPrefix ?
678
+ type :
679
+ this.widgetEventPrefix + type ).toLowerCase();
680
+
681
+ // The original event may come from any element
682
+ // so we need to reset the target on the new event
683
+ event.target = this.element[ 0 ];
684
+
685
+ // Copy original event properties over to the new event
686
+ orig = event.originalEvent;
687
+ if ( orig ) {
688
+ for ( prop in orig ) {
689
+ if ( !( prop in event ) ) {
690
+ event[ prop ] = orig[ prop ];
691
+ }
692
+ }
693
+ }
694
+
695
+ this.element.trigger( event, data );
696
+ return !( $.isFunction( callback ) &&
697
+ callback.apply( this.element[ 0 ], [ event ].concat( data ) ) === false ||
698
+ event.isDefaultPrevented() );
699
+ }
700
+};
701
+
702
+$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
703
+ $.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
704
+ if ( typeof options === "string" ) {
705
+ options = { effect: options };
706
+ }
707
+
708
+ var hasOptions;
709
+ var effectName = !options ?
710
+ method :
711
+ options === true || typeof options === "number" ?
712
+ defaultEffect :
713
+ options.effect || defaultEffect;
714
+
715
+ options = options || {};
716
+ if ( typeof options === "number" ) {
717
+ options = { duration: options };
718
+ }
719
+
720
+ hasOptions = !$.isEmptyObject( options );
721
+ options.complete = callback;
722
+
723
+ if ( options.delay ) {
724
+ element.delay( options.delay );
725
+ }
726
+
727
+ if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
728
+ element[ method ]( options );
729
+ } else if ( effectName !== method && element[ effectName ] ) {
730
+ element[ effectName ]( options.duration, options.easing, callback );
731
+ } else {
732
+ element.queue( function( next ) {
733
+ $( this )[ method ]();
734
+ if ( callback ) {
735
+ callback.call( element[ 0 ] );
736
+ }
737
+ next();
738
+ } );
739
+ }
740
+ };
741
+} );
742
+
743
+var widget = $.widget;
744
+
745
+
746
+/*!
747
+ * jQuery UI Position 1.12.1
748
+ * http://jqueryui.com
749
+ *
750
+ * Copyright jQuery Foundation and other contributors
751
+ * Released under the MIT license.
752
+ * http://jquery.org/license
753
+ *
754
+ * http://api.jqueryui.com/position/
755
+ */
756
+
757
+//>>label: Position
758
+//>>group: Core
759
+//>>description: Positions elements relative to other elements.
760
+//>>docs: http://api.jqueryui.com/position/
761
+//>>demos: http://jqueryui.com/position/
762
+
763
+
764
+( function() {
765
+var cachedScrollbarWidth,
766
+ max = Math.max,
767
+ abs = Math.abs,
768
+ rhorizontal = /left|center|right/,
769
+ rvertical = /top|center|bottom/,
770
+ roffset = /[\+\-]\d+(\.[\d]+)?%?/,
771
+ rposition = /^\w+/,
772
+ rpercent = /%$/,
773
+ _position = $.fn.position;
774
+
775
+function getOffsets( offsets, width, height ) {
776
+ return [
777
+ parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),
778
+ parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )
779
+ ];
780
+}
781
+
782
+function parseCss( element, property ) {
783
+ return parseInt( $.css( element, property ), 10 ) || 0;
784
+}
785
+
786
+function getDimensions( elem ) {
787
+ var raw = elem[ 0 ];
788
+ if ( raw.nodeType === 9 ) {
789
+ return {
790
+ width: elem.width(),
791
+ height: elem.height(),
792
+ offset: { top: 0, left: 0 }
793
+ };
794
+ }
795
+ if ( $.isWindow( raw ) ) {
796
+ return {
797
+ width: elem.width(),
798
+ height: elem.height(),
799
+ offset: { top: elem.scrollTop(), left: elem.scrollLeft() }
800
+ };
801
+ }
802
+ if ( raw.preventDefault ) {
803
+ return {
804
+ width: 0,
805
+ height: 0,
806
+ offset: { top: raw.pageY, left: raw.pageX }
807
+ };
808
+ }
809
+ return {
810
+ width: elem.outerWidth(),
811
+ height: elem.outerHeight(),
812
+ offset: elem.offset()
813
+ };
814
+}
815
+
816
+$.position = {
817
+ scrollbarWidth: function() {
818
+ if ( cachedScrollbarWidth !== undefined ) {
819
+ return cachedScrollbarWidth;
820
+ }
821
+ var w1, w2,
822
+ div = $( "<div " +
823
+ "style='display:block;position:absolute;width:50px;height:50px;overflow:hidden;'>" +
824
+ "<div style='height:100px;width:auto;'></div></div>" ),
825
+ innerDiv = div.children()[ 0 ];
826
+
827
+ $( "body" ).append( div );
828
+ w1 = innerDiv.offsetWidth;
829
+ div.css( "overflow", "scroll" );
830
+
831
+ w2 = innerDiv.offsetWidth;
832
+
833
+ if ( w1 === w2 ) {
834
+ w2 = div[ 0 ].clientWidth;
835
+ }
836
+
837
+ div.remove();
838
+
839
+ return ( cachedScrollbarWidth = w1 - w2 );
840
+ },
841
+ getScrollInfo: function( within ) {
842
+ var overflowX = within.isWindow || within.isDocument ? "" :
843
+ within.element.css( "overflow-x" ),
844
+ overflowY = within.isWindow || within.isDocument ? "" :
845
+ within.element.css( "overflow-y" ),
846
+ hasOverflowX = overflowX === "scroll" ||
847
+ ( overflowX === "auto" && within.width < within.element[ 0 ].scrollWidth ),
848
+ hasOverflowY = overflowY === "scroll" ||
849
+ ( overflowY === "auto" && within.height < within.element[ 0 ].scrollHeight );
850
+ return {
851
+ width: hasOverflowY ? $.position.scrollbarWidth() : 0,
852
+ height: hasOverflowX ? $.position.scrollbarWidth() : 0
853
+ };
854
+ },
855
+ getWithinInfo: function( element ) {
856
+ var withinElement = $( element || window ),
857
+ isWindow = $.isWindow( withinElement[ 0 ] ),
858
+ isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9,
859
+ hasOffset = !isWindow && !isDocument;
860
+ return {
861
+ element: withinElement,
862
+ isWindow: isWindow,
863
+ isDocument: isDocument,
864
+ offset: hasOffset ? $( element ).offset() : { left: 0, top: 0 },
865
+ scrollLeft: withinElement.scrollLeft(),
866
+ scrollTop: withinElement.scrollTop(),
867
+ width: withinElement.outerWidth(),
868
+ height: withinElement.outerHeight()
869
+ };
870
+ }
871
+};
872
+
873
+$.fn.position = function( options ) {
874
+ if ( !options || !options.of ) {
875
+ return _position.apply( this, arguments );
876
+ }
877
+
878
+ // Make a copy, we don't want to modify arguments
879
+ options = $.extend( {}, options );
880
+
881
+ var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,
882
+ target = $( options.of ),
883
+ within = $.position.getWithinInfo( options.within ),
884
+ scrollInfo = $.position.getScrollInfo( within ),
885
+ collision = ( options.collision || "flip" ).split( " " ),
886
+ offsets = {};
887
+
888
+ dimensions = getDimensions( target );
889
+ if ( target[ 0 ].preventDefault ) {
890
+
891
+ // Force left top to allow flipping
892
+ options.at = "left top";
893
+ }
894
+ targetWidth = dimensions.width;
895
+ targetHeight = dimensions.height;
896
+ targetOffset = dimensions.offset;
897
+
898
+ // Clone to reuse original targetOffset later
899
+ basePosition = $.extend( {}, targetOffset );
900
+
901
+ // Force my and at to have valid horizontal and vertical positions
902
+ // if a value is missing or invalid, it will be converted to center
903
+ $.each( [ "my", "at" ], function() {
904
+ var pos = ( options[ this ] || "" ).split( " " ),
905
+ horizontalOffset,
906
+ verticalOffset;
907
+
908
+ if ( pos.length === 1 ) {
909
+ pos = rhorizontal.test( pos[ 0 ] ) ?
910
+ pos.concat( [ "center" ] ) :
911
+ rvertical.test( pos[ 0 ] ) ?
912
+ [ "center" ].concat( pos ) :
913
+ [ "center", "center" ];
914
+ }
915
+ pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center";
916
+ pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";
917
+
918
+ // Calculate offsets
919
+ horizontalOffset = roffset.exec( pos[ 0 ] );
920
+ verticalOffset = roffset.exec( pos[ 1 ] );
921
+ offsets[ this ] = [
922
+ horizontalOffset ? horizontalOffset[ 0 ] : 0,
923
+ verticalOffset ? verticalOffset[ 0 ] : 0
924
+ ];
925
+
926
+ // Reduce to just the positions without the offsets
927
+ options[ this ] = [
928
+ rposition.exec( pos[ 0 ] )[ 0 ],
929
+ rposition.exec( pos[ 1 ] )[ 0 ]
930
+ ];
931
+ } );
932
+
933
+ // Normalize collision option
934
+ if ( collision.length === 1 ) {
935
+ collision[ 1 ] = collision[ 0 ];
936
+ }
937
+
938
+ if ( options.at[ 0 ] === "right" ) {
939
+ basePosition.left += targetWidth;
940
+ } else if ( options.at[ 0 ] === "center" ) {
941
+ basePosition.left += targetWidth / 2;
942
+ }
943
+
944
+ if ( options.at[ 1 ] === "bottom" ) {
945
+ basePosition.top += targetHeight;
946
+ } else if ( options.at[ 1 ] === "center" ) {
947
+ basePosition.top += targetHeight / 2;
948
+ }
949
+
950
+ atOffset = getOffsets( offsets.at, targetWidth, targetHeight );
951
+ basePosition.left += atOffset[ 0 ];
952
+ basePosition.top += atOffset[ 1 ];
953
+
954
+ return this.each( function() {
955
+ var collisionPosition, using,
956
+ elem = $( this ),
957
+ elemWidth = elem.outerWidth(),
958
+ elemHeight = elem.outerHeight(),
959
+ marginLeft = parseCss( this, "marginLeft" ),
960
+ marginTop = parseCss( this, "marginTop" ),
961
+ collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) +
962
+ scrollInfo.width,
963
+ collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) +
964
+ scrollInfo.height,
965
+ position = $.extend( {}, basePosition ),
966
+ myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );
967
+
968
+ if ( options.my[ 0 ] === "right" ) {
969
+ position.left -= elemWidth;
970
+ } else if ( options.my[ 0 ] === "center" ) {
971
+ position.left -= elemWidth / 2;
972
+ }
973
+
974
+ if ( options.my[ 1 ] === "bottom" ) {
975
+ position.top -= elemHeight;
976
+ } else if ( options.my[ 1 ] === "center" ) {
977
+ position.top -= elemHeight / 2;
978
+ }
979
+
980
+ position.left += myOffset[ 0 ];
981
+ position.top += myOffset[ 1 ];
982
+
983
+ collisionPosition = {
984
+ marginLeft: marginLeft,
985
+ marginTop: marginTop
986
+ };
987
+
988
+ $.each( [ "left", "top" ], function( i, dir ) {
989
+ if ( $.ui.position[ collision[ i ] ] ) {
990
+ $.ui.position[ collision[ i ] ][ dir ]( position, {
991
+ targetWidth: targetWidth,
992
+ targetHeight: targetHeight,
993
+ elemWidth: elemWidth,
994
+ elemHeight: elemHeight,
995
+ collisionPosition: collisionPosition,
996
+ collisionWidth: collisionWidth,
997
+ collisionHeight: collisionHeight,
998
+ offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],
999
+ my: options.my,
1000
+ at: options.at,
1001
+ within: within,
1002
+ elem: elem
1003
+ } );
1004
+ }
1005
+ } );
1006
+
1007
+ if ( options.using ) {
1008
+
1009
+ // Adds feedback as second argument to using callback, if present
1010
+ using = function( props ) {
1011
+ var left = targetOffset.left - position.left,
1012
+ right = left + targetWidth - elemWidth,
1013
+ top = targetOffset.top - position.top,
1014
+ bottom = top + targetHeight - elemHeight,
1015
+ feedback = {
1016
+ target: {
1017
+ element: target,
1018
+ left: targetOffset.left,
1019
+ top: targetOffset.top,
1020
+ width: targetWidth,
1021
+ height: targetHeight
1022
+ },
1023
+ element: {
1024
+ element: elem,
1025
+ left: position.left,
1026
+ top: position.top,
1027
+ width: elemWidth,
1028
+ height: elemHeight
1029
+ },
1030
+ horizontal: right < 0 ? "left" : left > 0 ? "right" : "center",
1031
+ vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle"
1032
+ };
1033
+ if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {
1034
+ feedback.horizontal = "center";
1035
+ }
1036
+ if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {
1037
+ feedback.vertical = "middle";
1038
+ }
1039
+ if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {
1040
+ feedback.important = "horizontal";
1041
+ } else {
1042
+ feedback.important = "vertical";
1043
+ }
1044
+ options.using.call( this, props, feedback );
1045
+ };
1046
+ }
1047
+
1048
+ elem.offset( $.extend( position, { using: using } ) );
1049
+ } );
1050
+};
1051
+
1052
+$.ui.position = {
1053
+ fit: {
1054
+ left: function( position, data ) {
1055
+ var within = data.within,
1056
+ withinOffset = within.isWindow ? within.scrollLeft : within.offset.left,
1057
+ outerWidth = within.width,
1058
+ collisionPosLeft = position.left - data.collisionPosition.marginLeft,
1059
+ overLeft = withinOffset - collisionPosLeft,
1060
+ overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
1061
+ newOverRight;
1062
+
1063
+ // Element is wider than within
1064
+ if ( data.collisionWidth > outerWidth ) {
1065
+
1066
+ // Element is initially over the left side of within
1067
+ if ( overLeft > 0 && overRight <= 0 ) {
1068
+ newOverRight = position.left + overLeft + data.collisionWidth - outerWidth -
1069
+ withinOffset;
1070
+ position.left += overLeft - newOverRight;
1071
+
1072
+ // Element is initially over right side of within
1073
+ } else if ( overRight > 0 && overLeft <= 0 ) {
1074
+ position.left = withinOffset;
1075
+
1076
+ // Element is initially over both left and right sides of within
1077
+ } else {
1078
+ if ( overLeft > overRight ) {
1079
+ position.left = withinOffset + outerWidth - data.collisionWidth;
1080
+ } else {
1081
+ position.left = withinOffset;
1082
+ }
1083
+ }
1084
+
1085
+ // Too far left -> align with left edge
1086
+ } else if ( overLeft > 0 ) {
1087
+ position.left += overLeft;
1088
+
1089
+ // Too far right -> align with right edge
1090
+ } else if ( overRight > 0 ) {
1091
+ position.left -= overRight;
1092
+
1093
+ // Adjust based on position and margin
1094
+ } else {
1095
+ position.left = max( position.left - collisionPosLeft, position.left );
1096
+ }
1097
+ },
1098
+ top: function( position, data ) {
1099
+ var within = data.within,
1100
+ withinOffset = within.isWindow ? within.scrollTop : within.offset.top,
1101
+ outerHeight = data.within.height,
1102
+ collisionPosTop = position.top - data.collisionPosition.marginTop,
1103
+ overTop = withinOffset - collisionPosTop,
1104
+ overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
1105
+ newOverBottom;
1106
+
1107
+ // Element is taller than within
1108
+ if ( data.collisionHeight > outerHeight ) {
1109
+
1110
+ // Element is initially over the top of within
1111
+ if ( overTop > 0 && overBottom <= 0 ) {
1112
+ newOverBottom = position.top + overTop + data.collisionHeight - outerHeight -
1113
+ withinOffset;
1114
+ position.top += overTop - newOverBottom;
1115
+
1116
+ // Element is initially over bottom of within
1117
+ } else if ( overBottom > 0 && overTop <= 0 ) {
1118
+ position.top = withinOffset;
1119
+
1120
+ // Element is initially over both top and bottom of within
1121
+ } else {
1122
+ if ( overTop > overBottom ) {
1123
+ position.top = withinOffset + outerHeight - data.collisionHeight;
1124
+ } else {
1125
+ position.top = withinOffset;
1126
+ }
1127
+ }
1128
+
1129
+ // Too far up -> align with top
1130
+ } else if ( overTop > 0 ) {
1131
+ position.top += overTop;
1132
+
1133
+ // Too far down -> align with bottom edge
1134
+ } else if ( overBottom > 0 ) {
1135
+ position.top -= overBottom;
1136
+
1137
+ // Adjust based on position and margin
1138
+ } else {
1139
+ position.top = max( position.top - collisionPosTop, position.top );
1140
+ }
1141
+ }
1142
+ },
1143
+ flip: {
1144
+ left: function( position, data ) {
1145
+ var within = data.within,
1146
+ withinOffset = within.offset.left + within.scrollLeft,
1147
+ outerWidth = within.width,
1148
+ offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,
1149
+ collisionPosLeft = position.left - data.collisionPosition.marginLeft,
1150
+ overLeft = collisionPosLeft - offsetLeft,
1151
+ overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,
1152
+ myOffset = data.my[ 0 ] === "left" ?
1153
+ -data.elemWidth :
1154
+ data.my[ 0 ] === "right" ?
1155
+ data.elemWidth :
1156
+ 0,
1157
+ atOffset = data.at[ 0 ] === "left" ?
1158
+ data.targetWidth :
1159
+ data.at[ 0 ] === "right" ?
1160
+ -data.targetWidth :
1161
+ 0,
1162
+ offset = -2 * data.offset[ 0 ],
1163
+ newOverRight,
1164
+ newOverLeft;
1165
+
1166
+ if ( overLeft < 0 ) {
1167
+ newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth -
1168
+ outerWidth - withinOffset;
1169
+ if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {
1170
+ position.left += myOffset + atOffset + offset;
1171
+ }
1172
+ } else if ( overRight > 0 ) {
1173
+ newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset +
1174
+ atOffset + offset - offsetLeft;
1175
+ if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {
1176
+ position.left += myOffset + atOffset + offset;
1177
+ }
1178
+ }
1179
+ },
1180
+ top: function( position, data ) {
1181
+ var within = data.within,
1182
+ withinOffset = within.offset.top + within.scrollTop,
1183
+ outerHeight = within.height,
1184
+ offsetTop = within.isWindow ? within.scrollTop : within.offset.top,
1185
+ collisionPosTop = position.top - data.collisionPosition.marginTop,
1186
+ overTop = collisionPosTop - offsetTop,
1187
+ overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,
1188
+ top = data.my[ 1 ] === "top",
1189
+ myOffset = top ?
1190
+ -data.elemHeight :
1191
+ data.my[ 1 ] === "bottom" ?
1192
+ data.elemHeight :
1193
+ 0,
1194
+ atOffset = data.at[ 1 ] === "top" ?
1195
+ data.targetHeight :
1196
+ data.at[ 1 ] === "bottom" ?
1197
+ -data.targetHeight :
1198
+ 0,
1199
+ offset = -2 * data.offset[ 1 ],
1200
+ newOverTop,
1201
+ newOverBottom;
1202
+ if ( overTop < 0 ) {
1203
+ newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight -
1204
+ outerHeight - withinOffset;
1205
+ if ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) {
1206
+ position.top += myOffset + atOffset + offset;
1207
+ }
1208
+ } else if ( overBottom > 0 ) {
1209
+ newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset +
1210
+ offset - offsetTop;
1211
+ if ( newOverTop > 0 || abs( newOverTop ) < overBottom ) {
1212
+ position.top += myOffset + atOffset + offset;
1213
+ }
1214
+ }
1215
+ }
1216
+ },
1217
+ flipfit: {
1218
+ left: function() {
1219
+ $.ui.position.flip.left.apply( this, arguments );
1220
+ $.ui.position.fit.left.apply( this, arguments );
1221
+ },
1222
+ top: function() {
1223
+ $.ui.position.flip.top.apply( this, arguments );
1224
+ $.ui.position.fit.top.apply( this, arguments );
1225
+ }
1226
+ }
1227
+};
1228
+
1229
+} )();
1230
+
1231
+var position = $.ui.position;
1232
+
1233
+
1234
+/*!
1235
+ * jQuery UI :data 1.12.1
1236
+ * http://jqueryui.com
1237
+ *
1238
+ * Copyright jQuery Foundation and other contributors
1239
+ * Released under the MIT license.
1240
+ * http://jquery.org/license
1241
+ */
1242
+
1243
+//>>label: :data Selector
1244
+//>>group: Core
1245
+//>>description: Selects elements which have data stored under the specified key.
1246
+//>>docs: http://api.jqueryui.com/data-selector/
1247
+
1248
+
1249
+var data = $.extend( $.expr[ ":" ], {
1250
+ data: $.expr.createPseudo ?
1251
+ $.expr.createPseudo( function( dataName ) {
1252
+ return function( elem ) {
1253
+ return !!$.data( elem, dataName );
1254
+ };
1255
+ } ) :
1256
+
1257
+ // Support: jQuery <1.8
1258
+ function( elem, i, match ) {
1259
+ return !!$.data( elem, match[ 3 ] );
1260
+ }
1261
+} );
1262
+
1263
+/*!
1264
+ * jQuery UI Disable Selection 1.12.1
1265
+ * http://jqueryui.com
1266
+ *
1267
+ * Copyright jQuery Foundation and other contributors
1268
+ * Released under the MIT license.
1269
+ * http://jquery.org/license
1270
+ */
1271
+
1272
+//>>label: disableSelection
1273
+//>>group: Core
1274
+//>>description: Disable selection of text content within the set of matched elements.
1275
+//>>docs: http://api.jqueryui.com/disableSelection/
1276
+
1277
+// This file is deprecated
1278
+
1279
+
1280
+var disableSelection = $.fn.extend( {
1281
+ disableSelection: ( function() {
1282
+ var eventType = "onselectstart" in document.createElement( "div" ) ?
1283
+ "selectstart" :
1284
+ "mousedown";
1285
+
1286
+ return function() {
1287
+ return this.on( eventType + ".ui-disableSelection", function( event ) {
1288
+ event.preventDefault();
1289
+ } );
1290
+ };
1291
+ } )(),
1292
+
1293
+ enableSelection: function() {
1294
+ return this.off( ".ui-disableSelection" );
1295
+ }
1296
+} );
1297
+
1298
+
1299
+/*!
1300
+ * jQuery UI Focusable 1.12.1
1301
+ * http://jqueryui.com
1302
+ *
1303
+ * Copyright jQuery Foundation and other contributors
1304
+ * Released under the MIT license.
1305
+ * http://jquery.org/license
1306
+ */
1307
+
1308
+//>>label: :focusable Selector
1309
+//>>group: Core
1310
+//>>description: Selects elements which can be focused.
1311
+//>>docs: http://api.jqueryui.com/focusable-selector/
1312
+
1313
+
1314
+
1315
+// Selectors
1316
+$.ui.focusable = function( element, hasTabindex ) {
1317
+ var map, mapName, img, focusableIfVisible, fieldset,
1318
+ nodeName = element.nodeName.toLowerCase();
1319
+
1320
+ if ( "area" === nodeName ) {
1321
+ map = element.parentNode;
1322
+ mapName = map.name;
1323
+ if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
1324
+ return false;
1325
+ }
1326
+ img = $( "img[usemap='#" + mapName + "']" );
1327
+ return img.length > 0 && img.is( ":visible" );
1328
+ }
1329
+
1330
+ if ( /^(input|select|textarea|button|object)$/.test( nodeName ) ) {
1331
+ focusableIfVisible = !element.disabled;
1332
+
1333
+ if ( focusableIfVisible ) {
1334
+
1335
+ // Form controls within a disabled fieldset are disabled.
1336
+ // However, controls within the fieldset's legend do not get disabled.
1337
+ // Since controls generally aren't placed inside legends, we skip
1338
+ // this portion of the check.
1339
+ fieldset = $( element ).closest( "fieldset" )[ 0 ];
1340
+ if ( fieldset ) {
1341
+ focusableIfVisible = !fieldset.disabled;
1342
+ }
1343
+ }
1344
+ } else if ( "a" === nodeName ) {
1345
+ focusableIfVisible = element.href || hasTabindex;
1346
+ } else {
1347
+ focusableIfVisible = hasTabindex;
1348
+ }
1349
+
1350
+ return focusableIfVisible && $( element ).is( ":visible" ) && visible( $( element ) );
1351
+};
1352
+
1353
+// Support: IE 8 only
1354
+// IE 8 doesn't resolve inherit to visible/hidden for computed values
1355
+function visible( element ) {
1356
+ var visibility = element.css( "visibility" );
1357
+ while ( visibility === "inherit" ) {
1358
+ element = element.parent();
1359
+ visibility = element.css( "visibility" );
1360
+ }
1361
+ return visibility !== "hidden";
1362
+}
1363
+
1364
+$.extend( $.expr[ ":" ], {
1365
+ focusable: function( element ) {
1366
+ return $.ui.focusable( element, $.attr( element, "tabindex" ) != null );
1367
+ }
1368
+} );
1369
+
1370
+var focusable = $.ui.focusable;
1371
+
1372
+
1373
+
1374
+
1375
+// Support: IE8 Only
1376
+// IE8 does not support the form attribute and when it is supplied. It overwrites the form prop
1377
+// with a string, so we need to find the proper form.
1378
+var form = $.fn.form = function() {
1379
+ return typeof this[ 0 ].form === "string" ? this.closest( "form" ) : $( this[ 0 ].form );
1380
+};
1381
+
1382
+
1383
+/*!
1384
+ * jQuery UI Form Reset Mixin 1.12.1
1385
+ * http://jqueryui.com
1386
+ *
1387
+ * Copyright jQuery Foundation and other contributors
1388
+ * Released under the MIT license.
1389
+ * http://jquery.org/license
1390
+ */
1391
+
1392
+//>>label: Form Reset Mixin
1393
+//>>group: Core
1394
+//>>description: Refresh input widgets when their form is reset
1395
+//>>docs: http://api.jqueryui.com/form-reset-mixin/
1396
+
1397
+
1398
+
1399
+var formResetMixin = $.ui.formResetMixin = {
1400
+ _formResetHandler: function() {
1401
+ var form = $( this );
1402
+
1403
+ // Wait for the form reset to actually happen before refreshing
1404
+ setTimeout( function() {
1405
+ var instances = form.data( "ui-form-reset-instances" );
1406
+ $.each( instances, function() {
1407
+ this.refresh();
1408
+ } );
1409
+ } );
1410
+ },
1411
+
1412
+ _bindFormResetHandler: function() {
1413
+ this.form = this.element.form();
1414
+ if ( !this.form.length ) {
1415
+ return;
1416
+ }
1417
+
1418
+ var instances = this.form.data( "ui-form-reset-instances" ) || [];
1419
+ if ( !instances.length ) {
1420
+
1421
+ // We don't use _on() here because we use a single event handler per form
1422
+ this.form.on( "reset.ui-form-reset", this._formResetHandler );
1423
+ }
1424
+ instances.push( this );
1425
+ this.form.data( "ui-form-reset-instances", instances );
1426
+ },
1427
+
1428
+ _unbindFormResetHandler: function() {
1429
+ if ( !this.form.length ) {
1430
+ return;
1431
+ }
1432
+
1433
+ var instances = this.form.data( "ui-form-reset-instances" );
1434
+ instances.splice( $.inArray( this, instances ), 1 );
1435
+ if ( instances.length ) {
1436
+ this.form.data( "ui-form-reset-instances", instances );
1437
+ } else {
1438
+ this.form
1439
+ .removeData( "ui-form-reset-instances" )
1440
+ .off( "reset.ui-form-reset" );
1441
+ }
1442
+ }
1443
+};
1444
+
1445
+
1446
+/*!
1447
+ * jQuery UI Support for jQuery core 1.7.x 1.12.1
1448
+ * http://jqueryui.com
1449
+ *
1450
+ * Copyright jQuery Foundation and other contributors
1451
+ * Released under the MIT license.
1452
+ * http://jquery.org/license
1453
+ *
1454
+ */
1455
+
1456
+//>>label: jQuery 1.7 Support
1457
+//>>group: Core
1458
+//>>description: Support version 1.7.x of jQuery core
1459
+
1460
+
1461
+
1462
+// Support: jQuery 1.7 only
1463
+// Not a great way to check versions, but since we only support 1.7+ and only
1464
+// need to detect <1.8, this is a simple check that should suffice. Checking
1465
+// for "1.7." would be a bit safer, but the version string is 1.7, not 1.7.0
1466
+// and we'll never reach 1.70.0 (if we do, we certainly won't be supporting
1467
+// 1.7 anymore). See #11197 for why we're not using feature detection.
1468
+if ( $.fn.jquery.substring( 0, 3 ) === "1.7" ) {
1469
+
1470
+ // Setters for .innerWidth(), .innerHeight(), .outerWidth(), .outerHeight()
1471
+ // Unlike jQuery Core 1.8+, these only support numeric values to set the
1472
+ // dimensions in pixels
1473
+ $.each( [ "Width", "Height" ], function( i, name ) {
1474
+ var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
1475
+ type = name.toLowerCase(),
1476
+ orig = {
1477
+ innerWidth: $.fn.innerWidth,
1478
+ innerHeight: $.fn.innerHeight,
1479
+ outerWidth: $.fn.outerWidth,
1480
+ outerHeight: $.fn.outerHeight
1481
+ };
1482
+
1483
+ function reduce( elem, size, border, margin ) {
1484
+ $.each( side, function() {
1485
+ size -= parseFloat( $.css( elem, "padding" + this ) ) || 0;
1486
+ if ( border ) {
1487
+ size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0;
1488
+ }
1489
+ if ( margin ) {
1490
+ size -= parseFloat( $.css( elem, "margin" + this ) ) || 0;
1491
+ }
1492
+ } );
1493
+ return size;
1494
+ }
1495
+
1496
+ $.fn[ "inner" + name ] = function( size ) {
1497
+ if ( size === undefined ) {
1498
+ return orig[ "inner" + name ].call( this );
1499
+ }
1500
+
1501
+ return this.each( function() {
1502
+ $( this ).css( type, reduce( this, size ) + "px" );
1503
+ } );
1504
+ };
1505
+
1506
+ $.fn[ "outer" + name ] = function( size, margin ) {
1507
+ if ( typeof size !== "number" ) {
1508
+ return orig[ "outer" + name ].call( this, size );
1509
+ }
1510
+
1511
+ return this.each( function() {
1512
+ $( this ).css( type, reduce( this, size, true, margin ) + "px" );
1513
+ } );
1514
+ };
1515
+ } );
1516
+
1517
+ $.fn.addBack = function( selector ) {
1518
+ return this.add( selector == null ?
1519
+ this.prevObject : this.prevObject.filter( selector )
1520
+ );
1521
+ };
1522
+}
1523
+
1524
+;
1525
+/*!
1526
+ * jQuery UI Keycode 1.12.1
1527
+ * http://jqueryui.com
1528
+ *
1529
+ * Copyright jQuery Foundation and other contributors
1530
+ * Released under the MIT license.
1531
+ * http://jquery.org/license
1532
+ */
1533
+
1534
+//>>label: Keycode
1535
+//>>group: Core
1536
+//>>description: Provide keycodes as keynames
1537
+//>>docs: http://api.jqueryui.com/jQuery.ui.keyCode/
1538
+
1539
+
1540
+var keycode = $.ui.keyCode = {
1541
+ BACKSPACE: 8,
1542
+ COMMA: 188,
1543
+ DELETE: 46,
1544
+ DOWN: 40,
1545
+ END: 35,
1546
+ ENTER: 13,
1547
+ ESCAPE: 27,
1548
+ HOME: 36,
1549
+ LEFT: 37,
1550
+ PAGE_DOWN: 34,
1551
+ PAGE_UP: 33,
1552
+ PERIOD: 190,
1553
+ RIGHT: 39,
1554
+ SPACE: 32,
1555
+ TAB: 9,
1556
+ UP: 38
1557
+};
1558
+
1559
+
1560
+
1561
+
1562
+// Internal use only
1563
+var escapeSelector = $.ui.escapeSelector = ( function() {
1564
+ var selectorEscape = /([!"#$%&'()*+,./:;<=>?@[\]^`{|}~])/g;
1565
+ return function( selector ) {
1566
+ return selector.replace( selectorEscape, "\\$1" );
1567
+ };
1568
+} )();
1569
+
1570
+
1571
+/*!
1572
+ * jQuery UI Labels 1.12.1
1573
+ * http://jqueryui.com
1574
+ *
1575
+ * Copyright jQuery Foundation and other contributors
1576
+ * Released under the MIT license.
1577
+ * http://jquery.org/license
1578
+ */
1579
+
1580
+//>>label: labels
1581
+//>>group: Core
1582
+//>>description: Find all the labels associated with a given input
1583
+//>>docs: http://api.jqueryui.com/labels/
1584
+
1585
+
1586
+
1587
+var labels = $.fn.labels = function() {
1588
+ var ancestor, selector, id, labels, ancestors;
1589
+
1590
+ // Check control.labels first
1591
+ if ( this[ 0 ].labels && this[ 0 ].labels.length ) {
1592
+ return this.pushStack( this[ 0 ].labels );
1593
+ }
1594
+
1595
+ // Support: IE <= 11, FF <= 37, Android <= 2.3 only
1596
+ // Above browsers do not support control.labels. Everything below is to support them
1597
+ // as well as document fragments. control.labels does not work on document fragments
1598
+ labels = this.eq( 0 ).parents( "label" );
1599
+
1600
+ // Look for the label based on the id
1601
+ id = this.attr( "id" );
1602
+ if ( id ) {
1603
+
1604
+ // We don't search against the document in case the element
1605
+ // is disconnected from the DOM
1606
+ ancestor = this.eq( 0 ).parents().last();
1607
+
1608
+ // Get a full set of top level ancestors
1609
+ ancestors = ancestor.add( ancestor.length ? ancestor.siblings() : this.siblings() );
1610
+
1611
+ // Create a selector for the label based on the id
1612
+ selector = "label[for='" + $.ui.escapeSelector( id ) + "']";
1613
+
1614
+ labels = labels.add( ancestors.find( selector ).addBack( selector ) );
1615
+
1616
+ }
1617
+
1618
+ // Return whatever we have found for labels
1619
+ return this.pushStack( labels );
1620
+};
1621
+
1622
+
1623
+/*!
1624
+ * jQuery UI Scroll Parent 1.12.1
1625
+ * http://jqueryui.com
1626
+ *
1627
+ * Copyright jQuery Foundation and other contributors
1628
+ * Released under the MIT license.
1629
+ * http://jquery.org/license
1630
+ */
1631
+
1632
+//>>label: scrollParent
1633
+//>>group: Core
1634
+//>>description: Get the closest ancestor element that is scrollable.
1635
+//>>docs: http://api.jqueryui.com/scrollParent/
1636
+
1637
+
1638
+
1639
+var scrollParent = $.fn.scrollParent = function( includeHidden ) {
1640
+ var position = this.css( "position" ),
1641
+ excludeStaticParent = position === "absolute",
1642
+ overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/,
1643
+ scrollParent = this.parents().filter( function() {
1644
+ var parent = $( this );
1645
+ if ( excludeStaticParent && parent.css( "position" ) === "static" ) {
1646
+ return false;
1647
+ }
1648
+ return overflowRegex.test( parent.css( "overflow" ) + parent.css( "overflow-y" ) +
1649
+ parent.css( "overflow-x" ) );
1650
+ } ).eq( 0 );
1651
+
1652
+ return position === "fixed" || !scrollParent.length ?
1653
+ $( this[ 0 ].ownerDocument || document ) :
1654
+ scrollParent;
1655
+};
1656
+
1657
+
1658
+/*!
1659
+ * jQuery UI Tabbable 1.12.1
1660
+ * http://jqueryui.com
1661
+ *
1662
+ * Copyright jQuery Foundation and other contributors
1663
+ * Released under the MIT license.
1664
+ * http://jquery.org/license
1665
+ */
1666
+
1667
+//>>label: :tabbable Selector
1668
+//>>group: Core
1669
+//>>description: Selects elements which can be tabbed to.
1670
+//>>docs: http://api.jqueryui.com/tabbable-selector/
1671
+
1672
+
1673
+
1674
+var tabbable = $.extend( $.expr[ ":" ], {
1675
+ tabbable: function( element ) {
1676
+ var tabIndex = $.attr( element, "tabindex" ),
1677
+ hasTabindex = tabIndex != null;
1678
+ return ( !hasTabindex || tabIndex >= 0 ) && $.ui.focusable( element, hasTabindex );
1679
+ }
1680
+} );
1681
+
1682
+
1683
+/*!
1684
+ * jQuery UI Unique ID 1.12.1
1685
+ * http://jqueryui.com
1686
+ *
1687
+ * Copyright jQuery Foundation and other contributors
1688
+ * Released under the MIT license.
1689
+ * http://jquery.org/license
1690
+ */
1691
+
1692
+//>>label: uniqueId
1693
+//>>group: Core
1694
+//>>description: Functions to generate and remove uniqueId's
1695
+//>>docs: http://api.jqueryui.com/uniqueId/
1696
+
1697
+
1698
+
1699
+var uniqueId = $.fn.extend( {
1700
+ uniqueId: ( function() {
1701
+ var uuid = 0;
1702
+
1703
+ return function() {
1704
+ return this.each( function() {
1705
+ if ( !this.id ) {
1706
+ this.id = "ui-id-" + ( ++uuid );
1707
+ }
1708
+ } );
1709
+ };
1710
+ } )(),
1711
+
1712
+ removeUniqueId: function() {
1713
+ return this.each( function() {
1714
+ if ( /^ui-id-\d+$/.test( this.id ) ) {
1715
+ $( this ).removeAttr( "id" );
1716
+ }
1717
+ } );
1718
+ }
1719
+} );
1720
+
1721
+
1722
+// jscs:disable maximumLineLength
1723
+/* jscs:disable requireCamelCaseOrUpperCaseIdentifiers */
1724
+/*!
1725
+ * jQuery UI Datepicker 1.12.1
1726
+ * http://jqueryui.com
1727
+ *
1728
+ * Copyright jQuery Foundation and other contributors
1729
+ * Released under the MIT license.
1730
+ * http://jquery.org/license
1731
+ */
1732
+
1733
+//>>label: Datepicker
1734
+//>>group: Widgets
1735
+//>>description: Displays a calendar from an input or inline for selecting dates.
1736
+//>>docs: http://api.jqueryui.com/datepicker/
1737
+//>>demos: http://jqueryui.com/datepicker/
1738
+//>>css.structure: ../../themes/base/core.css
1739
+//>>css.structure: ../../themes/base/datepicker.css
1740
+//>>css.theme: ../../themes/base/theme.css
1741
+
1742
+
1743
+
1744
+$.extend( $.ui, { datepicker: { version: "1.12.1" } } );
1745
+
1746
+var datepicker_instActive;
1747
+
1748
+function datepicker_getZindex( elem ) {
1749
+ var position, value;
1750
+ while ( elem.length && elem[ 0 ] !== document ) {
1751
+
1752
+ // Ignore z-index if position is set to a value where z-index is ignored by the browser
1753
+ // This makes behavior of this function consistent across browsers
1754
+ // WebKit always returns auto if the element is positioned
1755
+ position = elem.css( "position" );
1756
+ if ( position === "absolute" || position === "relative" || position === "fixed" ) {
1757
+
1758
+ // IE returns 0 when zIndex is not specified
1759
+ // other browsers return a string
1760
+ // we ignore the case of nested elements with an explicit value of 0
1761
+ // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
1762
+ value = parseInt( elem.css( "zIndex" ), 10 );
1763
+ if ( !isNaN( value ) && value !== 0 ) {
1764
+ return value;
1765
+ }
1766
+ }
1767
+ elem = elem.parent();
1768
+ }
1769
+
1770
+ return 0;
1771
+}
1772
+/* Date picker manager.
1773
+ Use the singleton instance of this class, $.datepicker, to interact with the date picker.
1774
+ Settings for (groups of) date pickers are maintained in an instance object,
1775
+ allowing multiple different settings on the same page. */
1776
+
1777
+function Datepicker() {
1778
+ this._curInst = null; // The current instance in use
1779
+ this._keyEvent = false; // If the last event was a key event
1780
+ this._disabledInputs = []; // List of date picker inputs that have been disabled
1781
+ this._datepickerShowing = false; // True if the popup picker is showing , false if not
1782
+ this._inDialog = false; // True if showing within a "dialog", false if not
1783
+ this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division
1784
+ this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class
1785
+ this._appendClass = "ui-datepicker-append"; // The name of the append marker class
1786
+ this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class
1787
+ this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class
1788
+ this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class
1789
+ this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class
1790
+ this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class
1791
+ this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class
1792
+ this.regional = []; // Available regional settings, indexed by language code
1793
+ this.regional[ "" ] = { // Default regional settings
1794
+ closeText: "Done", // Display text for close link
1795
+ prevText: "Prev", // Display text for previous month link
1796
+ nextText: "Next", // Display text for next month link
1797
+ currentText: "Today", // Display text for current month link
1798
+ monthNames: [ "January","February","March","April","May","June",
1799
+ "July","August","September","October","November","December" ], // Names of months for drop-down and formatting
1800
+ monthNamesShort: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ], // For formatting
1801
+ dayNames: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ], // For formatting
1802
+ dayNamesShort: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ], // For formatting
1803
+ dayNamesMin: [ "Su","Mo","Tu","We","Th","Fr","Sa" ], // Column headings for days starting at Sunday
1804
+ weekHeader: "Wk", // Column header for week of the year
1805
+ dateFormat: "mm/dd/yy", // See format options on parseDate
1806
+ firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
1807
+ isRTL: false, // True if right-to-left language, false if left-to-right
1808
+ showMonthAfterYear: false, // True if the year select precedes month, false for month then year
1809
+ yearSuffix: "" // Additional text to append to the year in the month headers
1810
+ };
1811
+ this._defaults = { // Global defaults for all the date picker instances
1812
+ showOn: "focus", // "focus" for popup on focus,
1813
+ // "button" for trigger button, or "both" for either
1814
+ showAnim: "fadeIn", // Name of jQuery animation for popup
1815
+ showOptions: {}, // Options for enhanced animations
1816
+ defaultDate: null, // Used when field is blank: actual date,
1817
+ // +/-number for offset from today, null for today
1818
+ appendText: "", // Display text following the input box, e.g. showing the format
1819
+ buttonText: "...", // Text for trigger button
1820
+ buttonImage: "", // URL for trigger button image
1821
+ buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
1822
+ hideIfNoPrevNext: false, // True to hide next/previous month links
1823
+ // if not applicable, false to just disable them
1824
+ navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
1825
+ gotoCurrent: false, // True if today link goes back to current selection instead
1826
+ changeMonth: false, // True if month can be selected directly, false if only prev/next
1827
+ changeYear: false, // True if year can be selected directly, false if only prev/next
1828
+ yearRange: "c-10:c+10", // Range of years to display in drop-down,
1829
+ // either relative to today's year (-nn:+nn), relative to currently displayed year
1830
+ // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
1831
+ showOtherMonths: false, // True to show dates in other months, false to leave blank
1832
+ selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
1833
+ showWeek: false, // True to show week of the year, false to not show it
1834
+ calculateWeek: this.iso8601Week, // How to calculate the week of the year,
1835
+ // takes a Date and returns the number of the week for it
1836
+ shortYearCutoff: "+10", // Short year values < this are in the current century,
1837
+ // > this are in the previous century,
1838
+ // string value starting with "+" for current year + value
1839
+ minDate: null, // The earliest selectable date, or null for no limit
1840
+ maxDate: null, // The latest selectable date, or null for no limit
1841
+ duration: "fast", // Duration of display/closure
1842
+ beforeShowDay: null, // Function that takes a date and returns an array with
1843
+ // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "",
1844
+ // [2] = cell title (optional), e.g. $.datepicker.noWeekends
1845
+ beforeShow: null, // Function that takes an input field and
1846
+ // returns a set of custom settings for the date picker
1847
+ onSelect: null, // Define a callback function when a date is selected
1848
+ onChangeMonthYear: null, // Define a callback function when the month or year is changed
1849
+ onClose: null, // Define a callback function when the datepicker is closed
1850
+ numberOfMonths: 1, // Number of months to show at a time
1851
+ showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
1852
+ stepMonths: 1, // Number of months to step back/forward
1853
+ stepBigMonths: 12, // Number of months to step back/forward for the big links
1854
+ altField: "", // Selector for an alternate field to store selected dates into
1855
+ altFormat: "", // The date format to use for the alternate field
1856
+ constrainInput: true, // The input is constrained by the current date format
1857
+ showButtonPanel: false, // True to show button panel, false to not show it
1858
+ autoSize: false, // True to size the input for the date format, false to leave as is
1859
+ disabled: false // The initial disabled state
1860
+ };
1861
+ $.extend( this._defaults, this.regional[ "" ] );
1862
+ this.regional.en = $.extend( true, {}, this.regional[ "" ] );
1863
+ this.regional[ "en-US" ] = $.extend( true, {}, this.regional.en );
1864
+ this.dpDiv = datepicker_bindHover( $( "<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>" ) );
1865
+}
1866
+
1867
+$.extend( Datepicker.prototype, {
1868
+ /* Class name added to elements to indicate already configured with a date picker. */
1869
+ markerClassName: "hasDatepicker",
1870
+
1871
+ //Keep track of the maximum number of rows displayed (see #7043)
1872
+ maxRows: 4,
1873
+
1874
+ // TODO rename to "widget" when switching to widget factory
1875
+ _widgetDatepicker: function() {
1876
+ return this.dpDiv;
1877
+ },
1878
+
1879
+ /* Override the default settings for all instances of the date picker.
1880
+ * @param settings object - the new settings to use as defaults (anonymous object)
1881
+ * @return the manager object
1882
+ */
1883
+ setDefaults: function( settings ) {
1884
+ datepicker_extendRemove( this._defaults, settings || {} );
1885
+ return this;
1886
+ },
1887
+
1888
+ /* Attach the date picker to a jQuery selection.
1889
+ * @param target element - the target input field or division or span
1890
+ * @param settings object - the new settings to use for this date picker instance (anonymous)
1891
+ */
1892
+ _attachDatepicker: function( target, settings ) {
1893
+ var nodeName, inline, inst;
1894
+ nodeName = target.nodeName.toLowerCase();
1895
+ inline = ( nodeName === "div" || nodeName === "span" );
1896
+ if ( !target.id ) {
1897
+ this.uuid += 1;
1898
+ target.id = "dp" + this.uuid;
1899
+ }
1900
+ inst = this._newInst( $( target ), inline );
1901
+ inst.settings = $.extend( {}, settings || {} );
1902
+ if ( nodeName === "input" ) {
1903
+ this._connectDatepicker( target, inst );
1904
+ } else if ( inline ) {
1905
+ this._inlineDatepicker( target, inst );
1906
+ }
1907
+ },
1908
+
1909
+ /* Create a new instance object. */
1910
+ _newInst: function( target, inline ) {
1911
+ var id = target[ 0 ].id.replace( /([^A-Za-z0-9_\-])/g, "\\\\$1" ); // escape jQuery meta chars
1912
+ return { id: id, input: target, // associated target
1913
+ selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
1914
+ drawMonth: 0, drawYear: 0, // month being drawn
1915
+ inline: inline, // is datepicker inline or not
1916
+ dpDiv: ( !inline ? this.dpDiv : // presentation div
1917
+ datepicker_bindHover( $( "<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>" ) ) ) };
1918
+ },
1919
+
1920
+ /* Attach the date picker to an input field. */
1921
+ _connectDatepicker: function( target, inst ) {
1922
+ var input = $( target );
1923
+ inst.append = $( [] );
1924
+ inst.trigger = $( [] );
1925
+ if ( input.hasClass( this.markerClassName ) ) {
1926
+ return;
1927
+ }
1928
+ this._attachments( input, inst );
1929
+ input.addClass( this.markerClassName ).on( "keydown", this._doKeyDown ).
1930
+ on( "keypress", this._doKeyPress ).on( "keyup", this._doKeyUp );
1931
+ this._autoSize( inst );
1932
+ $.data( target, "datepicker", inst );
1933
+
1934
+ //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
1935
+ if ( inst.settings.disabled ) {
1936
+ this._disableDatepicker( target );
1937
+ }
1938
+ },
1939
+
1940
+ /* Make attachments based on settings. */
1941
+ _attachments: function( input, inst ) {
1942
+ var showOn, buttonText, buttonImage,
1943
+ appendText = this._get( inst, "appendText" ),
1944
+ isRTL = this._get( inst, "isRTL" );
1945
+
1946
+ if ( inst.append ) {
1947
+ inst.append.remove();
1948
+ }
1949
+ if ( appendText ) {
1950
+ inst.append = $( "<span class='" + this._appendClass + "'>" + appendText + "</span>" );
1951
+ input[ isRTL ? "before" : "after" ]( inst.append );
1952
+ }
1953
+
1954
+ input.off( "focus", this._showDatepicker );
1955
+
1956
+ if ( inst.trigger ) {
1957
+ inst.trigger.remove();
1958
+ }
1959
+
1960
+ showOn = this._get( inst, "showOn" );
1961
+ if ( showOn === "focus" || showOn === "both" ) { // pop-up date picker when in the marked field
1962
+ input.on( "focus", this._showDatepicker );
1963
+ }
1964
+ if ( showOn === "button" || showOn === "both" ) { // pop-up date picker when button clicked
1965
+ buttonText = this._get( inst, "buttonText" );
1966
+ buttonImage = this._get( inst, "buttonImage" );
1967
+ inst.trigger = $( this._get( inst, "buttonImageOnly" ) ?
1968
+ $( "<img/>" ).addClass( this._triggerClass ).
1969
+ attr( { src: buttonImage, alt: buttonText, title: buttonText } ) :
1970
+ $( "<button type='button'></button>" ).addClass( this._triggerClass ).
1971
+ html( !buttonImage ? buttonText : $( "<img/>" ).attr(
1972
+ { src:buttonImage, alt:buttonText, title:buttonText } ) ) );
1973
+ input[ isRTL ? "before" : "after" ]( inst.trigger );
1974
+ inst.trigger.on( "click", function() {
1975
+ if ( $.datepicker._datepickerShowing && $.datepicker._lastInput === input[ 0 ] ) {
1976
+ $.datepicker._hideDatepicker();
1977
+ } else if ( $.datepicker._datepickerShowing && $.datepicker._lastInput !== input[ 0 ] ) {
1978
+ $.datepicker._hideDatepicker();
1979
+ $.datepicker._showDatepicker( input[ 0 ] );
1980
+ } else {
1981
+ $.datepicker._showDatepicker( input[ 0 ] );
1982
+ }
1983
+ return false;
1984
+ } );
1985
+ }
1986
+ },
1987
+
1988
+ /* Apply the maximum length for the date format. */
1989
+ _autoSize: function( inst ) {
1990
+ if ( this._get( inst, "autoSize" ) && !inst.inline ) {
1991
+ var findMax, max, maxI, i,
1992
+ date = new Date( 2009, 12 - 1, 20 ), // Ensure double digits
1993
+ dateFormat = this._get( inst, "dateFormat" );
1994
+
1995
+ if ( dateFormat.match( /[DM]/ ) ) {
1996
+ findMax = function( names ) {
1997
+ max = 0;
1998
+ maxI = 0;
1999
+ for ( i = 0; i < names.length; i++ ) {
2000
+ if ( names[ i ].length > max ) {
2001
+ max = names[ i ].length;
2002
+ maxI = i;
2003
+ }
2004
+ }
2005
+ return maxI;
2006
+ };
2007
+ date.setMonth( findMax( this._get( inst, ( dateFormat.match( /MM/ ) ?
2008
+ "monthNames" : "monthNamesShort" ) ) ) );
2009
+ date.setDate( findMax( this._get( inst, ( dateFormat.match( /DD/ ) ?
2010
+ "dayNames" : "dayNamesShort" ) ) ) + 20 - date.getDay() );
2011
+ }
2012
+ inst.input.attr( "size", this._formatDate( inst, date ).length );
2013
+ }
2014
+ },
2015
+
2016
+ /* Attach an inline date picker to a div. */
2017
+ _inlineDatepicker: function( target, inst ) {
2018
+ var divSpan = $( target );
2019
+ if ( divSpan.hasClass( this.markerClassName ) ) {
2020
+ return;
2021
+ }
2022
+ divSpan.addClass( this.markerClassName ).append( inst.dpDiv );
2023
+ $.data( target, "datepicker", inst );
2024
+ this._setDate( inst, this._getDefaultDate( inst ), true );
2025
+ this._updateDatepicker( inst );
2026
+ this._updateAlternate( inst );
2027
+
2028
+ //If disabled option is true, disable the datepicker before showing it (see ticket #5665)
2029
+ if ( inst.settings.disabled ) {
2030
+ this._disableDatepicker( target );
2031
+ }
2032
+
2033
+ // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
2034
+ // http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
2035
+ inst.dpDiv.css( "display", "block" );
2036
+ },
2037
+
2038
+ /* Pop-up the date picker in a "dialog" box.
2039
+ * @param input element - ignored
2040
+ * @param date string or Date - the initial date to display
2041
+ * @param onSelect function - the function to call when a date is selected
2042
+ * @param settings object - update the dialog date picker instance's settings (anonymous object)
2043
+ * @param pos int[2] - coordinates for the dialog's position within the screen or
2044
+ * event - with x/y coordinates or
2045
+ * leave empty for default (screen centre)
2046
+ * @return the manager object
2047
+ */
2048
+ _dialogDatepicker: function( input, date, onSelect, settings, pos ) {
2049
+ var id, browserWidth, browserHeight, scrollX, scrollY,
2050
+ inst = this._dialogInst; // internal instance
2051
+
2052
+ if ( !inst ) {
2053
+ this.uuid += 1;
2054
+ id = "dp" + this.uuid;
2055
+ this._dialogInput = $( "<input type='text' id='" + id +
2056
+ "' style='position: absolute; top: -100px; width: 0px;'/>" );
2057
+ this._dialogInput.on( "keydown", this._doKeyDown );
2058
+ $( "body" ).append( this._dialogInput );
2059
+ inst = this._dialogInst = this._newInst( this._dialogInput, false );
2060
+ inst.settings = {};
2061
+ $.data( this._dialogInput[ 0 ], "datepicker", inst );
2062
+ }
2063
+ datepicker_extendRemove( inst.settings, settings || {} );
2064
+ date = ( date && date.constructor === Date ? this._formatDate( inst, date ) : date );
2065
+ this._dialogInput.val( date );
2066
+
2067
+ this._pos = ( pos ? ( pos.length ? pos : [ pos.pageX, pos.pageY ] ) : null );
2068
+ if ( !this._pos ) {
2069
+ browserWidth = document.documentElement.clientWidth;
2070
+ browserHeight = document.documentElement.clientHeight;
2071
+ scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
2072
+ scrollY = document.documentElement.scrollTop || document.body.scrollTop;
2073
+ this._pos = // should use actual width/height below
2074
+ [ ( browserWidth / 2 ) - 100 + scrollX, ( browserHeight / 2 ) - 150 + scrollY ];
2075
+ }
2076
+
2077
+ // Move input on screen for focus, but hidden behind dialog
2078
+ this._dialogInput.css( "left", ( this._pos[ 0 ] + 20 ) + "px" ).css( "top", this._pos[ 1 ] + "px" );
2079
+ inst.settings.onSelect = onSelect;
2080
+ this._inDialog = true;
2081
+ this.dpDiv.addClass( this._dialogClass );
2082
+ this._showDatepicker( this._dialogInput[ 0 ] );
2083
+ if ( $.blockUI ) {
2084
+ $.blockUI( this.dpDiv );
2085
+ }
2086
+ $.data( this._dialogInput[ 0 ], "datepicker", inst );
2087
+ return this;
2088
+ },
2089
+
2090
+ /* Detach a datepicker from its control.
2091
+ * @param target element - the target input field or division or span
2092
+ */
2093
+ _destroyDatepicker: function( target ) {
2094
+ var nodeName,
2095
+ $target = $( target ),
2096
+ inst = $.data( target, "datepicker" );
2097
+
2098
+ if ( !$target.hasClass( this.markerClassName ) ) {
2099
+ return;
2100
+ }
2101
+
2102
+ nodeName = target.nodeName.toLowerCase();
2103
+ $.removeData( target, "datepicker" );
2104
+ if ( nodeName === "input" ) {
2105
+ inst.append.remove();
2106
+ inst.trigger.remove();
2107
+ $target.removeClass( this.markerClassName ).
2108
+ off( "focus", this._showDatepicker ).
2109
+ off( "keydown", this._doKeyDown ).
2110
+ off( "keypress", this._doKeyPress ).
2111
+ off( "keyup", this._doKeyUp );
2112
+ } else if ( nodeName === "div" || nodeName === "span" ) {
2113
+ $target.removeClass( this.markerClassName ).empty();
2114
+ }
2115
+
2116
+ if ( datepicker_instActive === inst ) {
2117
+ datepicker_instActive = null;
2118
+ }
2119
+ },
2120
+
2121
+ /* Enable the date picker to a jQuery selection.
2122
+ * @param target element - the target input field or division or span
2123
+ */
2124
+ _enableDatepicker: function( target ) {
2125
+ var nodeName, inline,
2126
+ $target = $( target ),
2127
+ inst = $.data( target, "datepicker" );
2128
+
2129
+ if ( !$target.hasClass( this.markerClassName ) ) {
2130
+ return;
2131
+ }
2132
+
2133
+ nodeName = target.nodeName.toLowerCase();
2134
+ if ( nodeName === "input" ) {
2135
+ target.disabled = false;
2136
+ inst.trigger.filter( "button" ).
2137
+ each( function() { this.disabled = false; } ).end().
2138
+ filter( "img" ).css( { opacity: "1.0", cursor: "" } );
2139
+ } else if ( nodeName === "div" || nodeName === "span" ) {
2140
+ inline = $target.children( "." + this._inlineClass );
2141
+ inline.children().removeClass( "ui-state-disabled" );
2142
+ inline.find( "select.ui-datepicker-month, select.ui-datepicker-year" ).
2143
+ prop( "disabled", false );
2144
+ }
2145
+ this._disabledInputs = $.map( this._disabledInputs,
2146
+ function( value ) { return ( value === target ? null : value ); } ); // delete entry
2147
+ },
2148
+
2149
+ /* Disable the date picker to a jQuery selection.
2150
+ * @param target element - the target input field or division or span
2151
+ */
2152
+ _disableDatepicker: function( target ) {
2153
+ var nodeName, inline,
2154
+ $target = $( target ),
2155
+ inst = $.data( target, "datepicker" );
2156
+
2157
+ if ( !$target.hasClass( this.markerClassName ) ) {
2158
+ return;
2159
+ }
2160
+
2161
+ nodeName = target.nodeName.toLowerCase();
2162
+ if ( nodeName === "input" ) {
2163
+ target.disabled = true;
2164
+ inst.trigger.filter( "button" ).
2165
+ each( function() { this.disabled = true; } ).end().
2166
+ filter( "img" ).css( { opacity: "0.5", cursor: "default" } );
2167
+ } else if ( nodeName === "div" || nodeName === "span" ) {
2168
+ inline = $target.children( "." + this._inlineClass );
2169
+ inline.children().addClass( "ui-state-disabled" );
2170
+ inline.find( "select.ui-datepicker-month, select.ui-datepicker-year" ).
2171
+ prop( "disabled", true );
2172
+ }
2173
+ this._disabledInputs = $.map( this._disabledInputs,
2174
+ function( value ) { return ( value === target ? null : value ); } ); // delete entry
2175
+ this._disabledInputs[ this._disabledInputs.length ] = target;
2176
+ },
2177
+
2178
+ /* Is the first field in a jQuery collection disabled as a datepicker?
2179
+ * @param target element - the target input field or division or span
2180
+ * @return boolean - true if disabled, false if enabled
2181
+ */
2182
+ _isDisabledDatepicker: function( target ) {
2183
+ if ( !target ) {
2184
+ return false;
2185
+ }
2186
+ for ( var i = 0; i < this._disabledInputs.length; i++ ) {
2187
+ if ( this._disabledInputs[ i ] === target ) {
2188
+ return true;
2189
+ }
2190
+ }
2191
+ return false;
2192
+ },
2193
+
2194
+ /* Retrieve the instance data for the target control.
2195
+ * @param target element - the target input field or division or span
2196
+ * @return object - the associated instance data
2197
+ * @throws error if a jQuery problem getting data
2198
+ */
2199
+ _getInst: function( target ) {
2200
+ try {
2201
+ return $.data( target, "datepicker" );
2202
+ }
2203
+ catch ( err ) {
2204
+ throw "Missing instance data for this datepicker";
2205
+ }
2206
+ },
2207
+
2208
+ /* Update or retrieve the settings for a date picker attached to an input field or division.
2209
+ * @param target element - the target input field or division or span
2210
+ * @param name object - the new settings to update or
2211
+ * string - the name of the setting to change or retrieve,
2212
+ * when retrieving also "all" for all instance settings or
2213
+ * "defaults" for all global defaults
2214
+ * @param value any - the new value for the setting
2215
+ * (omit if above is an object or to retrieve a value)
2216
+ */
2217
+ _optionDatepicker: function( target, name, value ) {
2218
+ var settings, date, minDate, maxDate,
2219
+ inst = this._getInst( target );
2220
+
2221
+ if ( arguments.length === 2 && typeof name === "string" ) {
2222
+ return ( name === "defaults" ? $.extend( {}, $.datepicker._defaults ) :
2223
+ ( inst ? ( name === "all" ? $.extend( {}, inst.settings ) :
2224
+ this._get( inst, name ) ) : null ) );
2225
+ }
2226
+
2227
+ settings = name || {};
2228
+ if ( typeof name === "string" ) {
2229
+ settings = {};
2230
+ settings[ name ] = value;
2231
+ }
2232
+
2233
+ if ( inst ) {
2234
+ if ( this._curInst === inst ) {
2235
+ this._hideDatepicker();
2236
+ }
2237
+
2238
+ date = this._getDateDatepicker( target, true );
2239
+ minDate = this._getMinMaxDate( inst, "min" );
2240
+ maxDate = this._getMinMaxDate( inst, "max" );
2241
+ datepicker_extendRemove( inst.settings, settings );
2242
+
2243
+ // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
2244
+ if ( minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined ) {
2245
+ inst.settings.minDate = this._formatDate( inst, minDate );
2246
+ }
2247
+ if ( maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined ) {
2248
+ inst.settings.maxDate = this._formatDate( inst, maxDate );
2249
+ }
2250
+ if ( "disabled" in settings ) {
2251
+ if ( settings.disabled ) {
2252
+ this._disableDatepicker( target );
2253
+ } else {
2254
+ this._enableDatepicker( target );
2255
+ }
2256
+ }
2257
+ this._attachments( $( target ), inst );
2258
+ this._autoSize( inst );
2259
+ this._setDate( inst, date );
2260
+ this._updateAlternate( inst );
2261
+ this._updateDatepicker( inst );
2262
+ }
2263
+ },
2264
+
2265
+ // Change method deprecated
2266
+ _changeDatepicker: function( target, name, value ) {
2267
+ this._optionDatepicker( target, name, value );
2268
+ },
2269
+
2270
+ /* Redraw the date picker attached to an input field or division.
2271
+ * @param target element - the target input field or division or span
2272
+ */
2273
+ _refreshDatepicker: function( target ) {
2274
+ var inst = this._getInst( target );
2275
+ if ( inst ) {
2276
+ this._updateDatepicker( inst );
2277
+ }
2278
+ },
2279
+
2280
+ /* Set the dates for a jQuery selection.
2281
+ * @param target element - the target input field or division or span
2282
+ * @param date Date - the new date
2283
+ */
2284
+ _setDateDatepicker: function( target, date ) {
2285
+ var inst = this._getInst( target );
2286
+ if ( inst ) {
2287
+ this._setDate( inst, date );
2288
+ this._updateDatepicker( inst );
2289
+ this._updateAlternate( inst );
2290
+ }
2291
+ },
2292
+
2293
+ /* Get the date(s) for the first entry in a jQuery selection.
2294
+ * @param target element - the target input field or division or span
2295
+ * @param noDefault boolean - true if no default date is to be used
2296
+ * @return Date - the current date
2297
+ */
2298
+ _getDateDatepicker: function( target, noDefault ) {
2299
+ var inst = this._getInst( target );
2300
+ if ( inst && !inst.inline ) {
2301
+ this._setDateFromField( inst, noDefault );
2302
+ }
2303
+ return ( inst ? this._getDate( inst ) : null );
2304
+ },
2305
+
2306
+ /* Handle keystrokes. */
2307
+ _doKeyDown: function( event ) {
2308
+ var onSelect, dateStr, sel,
2309
+ inst = $.datepicker._getInst( event.target ),
2310
+ handled = true,
2311
+ isRTL = inst.dpDiv.is( ".ui-datepicker-rtl" );
2312
+
2313
+ inst._keyEvent = true;
2314
+ if ( $.datepicker._datepickerShowing ) {
2315
+ switch ( event.keyCode ) {
2316
+ case 9: $.datepicker._hideDatepicker();
2317
+ handled = false;
2318
+ break; // hide on tab out
2319
+ case 13: sel = $( "td." + $.datepicker._dayOverClass + ":not(." +
2320
+ $.datepicker._currentClass + ")", inst.dpDiv );
2321
+ if ( sel[ 0 ] ) {
2322
+ $.datepicker._selectDay( event.target, inst.selectedMonth, inst.selectedYear, sel[ 0 ] );
2323
+ }
2324
+
2325
+ onSelect = $.datepicker._get( inst, "onSelect" );
2326
+ if ( onSelect ) {
2327
+ dateStr = $.datepicker._formatDate( inst );
2328
+
2329
+ // Trigger custom callback
2330
+ onSelect.apply( ( inst.input ? inst.input[ 0 ] : null ), [ dateStr, inst ] );
2331
+ } else {
2332
+ $.datepicker._hideDatepicker();
2333
+ }
2334
+
2335
+ return false; // don't submit the form
2336
+ case 27: $.datepicker._hideDatepicker();
2337
+ break; // hide on escape
2338
+ case 33: $.datepicker._adjustDate( event.target, ( event.ctrlKey ?
2339
+ -$.datepicker._get( inst, "stepBigMonths" ) :
2340
+ -$.datepicker._get( inst, "stepMonths" ) ), "M" );
2341
+ break; // previous month/year on page up/+ ctrl
2342
+ case 34: $.datepicker._adjustDate( event.target, ( event.ctrlKey ?
2343
+ +$.datepicker._get( inst, "stepBigMonths" ) :
2344
+ +$.datepicker._get( inst, "stepMonths" ) ), "M" );
2345
+ break; // next month/year on page down/+ ctrl
2346
+ case 35: if ( event.ctrlKey || event.metaKey ) {
2347
+ $.datepicker._clearDate( event.target );
2348
+ }
2349
+ handled = event.ctrlKey || event.metaKey;
2350
+ break; // clear on ctrl or command +end
2351
+ case 36: if ( event.ctrlKey || event.metaKey ) {
2352
+ $.datepicker._gotoToday( event.target );
2353
+ }
2354
+ handled = event.ctrlKey || event.metaKey;
2355
+ break; // current on ctrl or command +home
2356
+ case 37: if ( event.ctrlKey || event.metaKey ) {
2357
+ $.datepicker._adjustDate( event.target, ( isRTL ? +1 : -1 ), "D" );
2358
+ }
2359
+ handled = event.ctrlKey || event.metaKey;
2360
+
2361
+ // -1 day on ctrl or command +left
2362
+ if ( event.originalEvent.altKey ) {
2363
+ $.datepicker._adjustDate( event.target, ( event.ctrlKey ?
2364
+ -$.datepicker._get( inst, "stepBigMonths" ) :
2365
+ -$.datepicker._get( inst, "stepMonths" ) ), "M" );
2366
+ }
2367
+
2368
+ // next month/year on alt +left on Mac
2369
+ break;
2370
+ case 38: if ( event.ctrlKey || event.metaKey ) {
2371
+ $.datepicker._adjustDate( event.target, -7, "D" );
2372
+ }
2373
+ handled = event.ctrlKey || event.metaKey;
2374
+ break; // -1 week on ctrl or command +up
2375
+ case 39: if ( event.ctrlKey || event.metaKey ) {
2376
+ $.datepicker._adjustDate( event.target, ( isRTL ? -1 : +1 ), "D" );
2377
+ }
2378
+ handled = event.ctrlKey || event.metaKey;
2379
+
2380
+ // +1 day on ctrl or command +right
2381
+ if ( event.originalEvent.altKey ) {
2382
+ $.datepicker._adjustDate( event.target, ( event.ctrlKey ?
2383
+ +$.datepicker._get( inst, "stepBigMonths" ) :
2384
+ +$.datepicker._get( inst, "stepMonths" ) ), "M" );
2385
+ }
2386
+
2387
+ // next month/year on alt +right
2388
+ break;
2389
+ case 40: if ( event.ctrlKey || event.metaKey ) {
2390
+ $.datepicker._adjustDate( event.target, +7, "D" );
2391
+ }
2392
+ handled = event.ctrlKey || event.metaKey;
2393
+ break; // +1 week on ctrl or command +down
2394
+ default: handled = false;
2395
+ }
2396
+ } else if ( event.keyCode === 36 && event.ctrlKey ) { // display the date picker on ctrl+home
2397
+ $.datepicker._showDatepicker( this );
2398
+ } else {
2399
+ handled = false;
2400
+ }
2401
+
2402
+ if ( handled ) {
2403
+ event.preventDefault();
2404
+ event.stopPropagation();
2405
+ }
2406
+ },
2407
+
2408
+ /* Filter entered characters - based on date format. */
2409
+ _doKeyPress: function( event ) {
2410
+ var chars, chr,
2411
+ inst = $.datepicker._getInst( event.target );
2412
+
2413
+ if ( $.datepicker._get( inst, "constrainInput" ) ) {
2414
+ chars = $.datepicker._possibleChars( $.datepicker._get( inst, "dateFormat" ) );
2415
+ chr = String.fromCharCode( event.charCode == null ? event.keyCode : event.charCode );
2416
+ return event.ctrlKey || event.metaKey || ( chr < " " || !chars || chars.indexOf( chr ) > -1 );
2417
+ }
2418
+ },
2419
+
2420
+ /* Synchronise manual entry and field/alternate field. */
2421
+ _doKeyUp: function( event ) {
2422
+ var date,
2423
+ inst = $.datepicker._getInst( event.target );
2424
+
2425
+ if ( inst.input.val() !== inst.lastVal ) {
2426
+ try {
2427
+ date = $.datepicker.parseDate( $.datepicker._get( inst, "dateFormat" ),
2428
+ ( inst.input ? inst.input.val() : null ),
2429
+ $.datepicker._getFormatConfig( inst ) );
2430
+
2431
+ if ( date ) { // only if valid
2432
+ $.datepicker._setDateFromField( inst );
2433
+ $.datepicker._updateAlternate( inst );
2434
+ $.datepicker._updateDatepicker( inst );
2435
+ }
2436
+ }
2437
+ catch ( err ) {
2438
+ }
2439
+ }
2440
+ return true;
2441
+ },
2442
+
2443
+ /* Pop-up the date picker for a given input field.
2444
+ * If false returned from beforeShow event handler do not show.
2445
+ * @param input element - the input field attached to the date picker or
2446
+ * event - if triggered by focus
2447
+ */
2448
+ _showDatepicker: function( input ) {
2449
+ input = input.target || input;
2450
+ if ( input.nodeName.toLowerCase() !== "input" ) { // find from button/image trigger
2451
+ input = $( "input", input.parentNode )[ 0 ];
2452
+ }
2453
+
2454
+ if ( $.datepicker._isDisabledDatepicker( input ) || $.datepicker._lastInput === input ) { // already here
2455
+ return;
2456
+ }
2457
+
2458
+ var inst, beforeShow, beforeShowSettings, isFixed,
2459
+ offset, showAnim, duration;
2460
+
2461
+ inst = $.datepicker._getInst( input );
2462
+ if ( $.datepicker._curInst && $.datepicker._curInst !== inst ) {
2463
+ $.datepicker._curInst.dpDiv.stop( true, true );
2464
+ if ( inst && $.datepicker._datepickerShowing ) {
2465
+ $.datepicker._hideDatepicker( $.datepicker._curInst.input[ 0 ] );
2466
+ }
2467
+ }
2468
+
2469
+ beforeShow = $.datepicker._get( inst, "beforeShow" );
2470
+ beforeShowSettings = beforeShow ? beforeShow.apply( input, [ input, inst ] ) : {};
2471
+ if ( beforeShowSettings === false ) {
2472
+ return;
2473
+ }
2474
+ datepicker_extendRemove( inst.settings, beforeShowSettings );
2475
+
2476
+ inst.lastVal = null;
2477
+ $.datepicker._lastInput = input;
2478
+ $.datepicker._setDateFromField( inst );
2479
+
2480
+ if ( $.datepicker._inDialog ) { // hide cursor
2481
+ input.value = "";
2482
+ }
2483
+ if ( !$.datepicker._pos ) { // position below input
2484
+ $.datepicker._pos = $.datepicker._findPos( input );
2485
+ $.datepicker._pos[ 1 ] += input.offsetHeight; // add the height
2486
+ }
2487
+
2488
+ isFixed = false;
2489
+ $( input ).parents().each( function() {
2490
+ isFixed |= $( this ).css( "position" ) === "fixed";
2491
+ return !isFixed;
2492
+ } );
2493
+
2494
+ offset = { left: $.datepicker._pos[ 0 ], top: $.datepicker._pos[ 1 ] };
2495
+ $.datepicker._pos = null;
2496
+
2497
+ //to avoid flashes on Firefox
2498
+ inst.dpDiv.empty();
2499
+
2500
+ // determine sizing offscreen
2501
+ inst.dpDiv.css( { position: "absolute", display: "block", top: "-1000px" } );
2502
+ $.datepicker._updateDatepicker( inst );
2503
+
2504
+ // fix width for dynamic number of date pickers
2505
+ // and adjust position before showing
2506
+ offset = $.datepicker._checkOffset( inst, offset, isFixed );
2507
+ inst.dpDiv.css( { position: ( $.datepicker._inDialog && $.blockUI ?
2508
+ "static" : ( isFixed ? "fixed" : "absolute" ) ), display: "none",
2509
+ left: offset.left + "px", top: offset.top + "px" } );
2510
+
2511
+ if ( !inst.inline ) {
2512
+ showAnim = $.datepicker._get( inst, "showAnim" );
2513
+ duration = $.datepicker._get( inst, "duration" );
2514
+ inst.dpDiv.css( "z-index", datepicker_getZindex( $( input ) ) + 1 );
2515
+ $.datepicker._datepickerShowing = true;
2516
+
2517
+ if ( $.effects && $.effects.effect[ showAnim ] ) {
2518
+ inst.dpDiv.show( showAnim, $.datepicker._get( inst, "showOptions" ), duration );
2519
+ } else {
2520
+ inst.dpDiv[ showAnim || "show" ]( showAnim ? duration : null );
2521
+ }
2522
+
2523
+ if ( $.datepicker._shouldFocusInput( inst ) ) {
2524
+ inst.input.trigger( "focus" );
2525
+ }
2526
+
2527
+ $.datepicker._curInst = inst;
2528
+ }
2529
+ },
2530
+
2531
+ /* Generate the date picker content. */
2532
+ _updateDatepicker: function( inst ) {
2533
+ this.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
2534
+ datepicker_instActive = inst; // for delegate hover events
2535
+ inst.dpDiv.empty().append( this._generateHTML( inst ) );
2536
+ this._attachHandlers( inst );
2537
+
2538
+ var origyearshtml,
2539
+ numMonths = this._getNumberOfMonths( inst ),
2540
+ cols = numMonths[ 1 ],
2541
+ width = 17,
2542
+ activeCell = inst.dpDiv.find( "." + this._dayOverClass + " a" );
2543
+
2544
+ if ( activeCell.length > 0 ) {
2545
+ datepicker_handleMouseover.apply( activeCell.get( 0 ) );
2546
+ }
2547
+
2548
+ inst.dpDiv.removeClass( "ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4" ).width( "" );
2549
+ if ( cols > 1 ) {
2550
+ inst.dpDiv.addClass( "ui-datepicker-multi-" + cols ).css( "width", ( width * cols ) + "em" );
2551
+ }
2552
+ inst.dpDiv[ ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ? "add" : "remove" ) +
2553
+ "Class" ]( "ui-datepicker-multi" );
2554
+ inst.dpDiv[ ( this._get( inst, "isRTL" ) ? "add" : "remove" ) +
2555
+ "Class" ]( "ui-datepicker-rtl" );
2556
+
2557
+ if ( inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) {
2558
+ inst.input.trigger( "focus" );
2559
+ }
2560
+
2561
+ // Deffered render of the years select (to avoid flashes on Firefox)
2562
+ if ( inst.yearshtml ) {
2563
+ origyearshtml = inst.yearshtml;
2564
+ setTimeout( function() {
2565
+
2566
+ //assure that inst.yearshtml didn't change.
2567
+ if ( origyearshtml === inst.yearshtml && inst.yearshtml ) {
2568
+ inst.dpDiv.find( "select.ui-datepicker-year:first" ).replaceWith( inst.yearshtml );
2569
+ }
2570
+ origyearshtml = inst.yearshtml = null;
2571
+ }, 0 );
2572
+ }
2573
+ },
2574
+
2575
+ // #6694 - don't focus the input if it's already focused
2576
+ // this breaks the change event in IE
2577
+ // Support: IE and jQuery <1.9
2578
+ _shouldFocusInput: function( inst ) {
2579
+ return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" ) && !inst.input.is( ":focus" );
2580
+ },
2581
+
2582
+ /* Check positioning to remain on screen. */
2583
+ _checkOffset: function( inst, offset, isFixed ) {
2584
+ var dpWidth = inst.dpDiv.outerWidth(),
2585
+ dpHeight = inst.dpDiv.outerHeight(),
2586
+ inputWidth = inst.input ? inst.input.outerWidth() : 0,
2587
+ inputHeight = inst.input ? inst.input.outerHeight() : 0,
2588
+ viewWidth = document.documentElement.clientWidth + ( isFixed ? 0 : $( document ).scrollLeft() ),
2589
+ viewHeight = document.documentElement.clientHeight + ( isFixed ? 0 : $( document ).scrollTop() );
2590
+
2591
+ offset.left -= ( this._get( inst, "isRTL" ) ? ( dpWidth - inputWidth ) : 0 );
2592
+ offset.left -= ( isFixed && offset.left === inst.input.offset().left ) ? $( document ).scrollLeft() : 0;
2593
+ offset.top -= ( isFixed && offset.top === ( inst.input.offset().top + inputHeight ) ) ? $( document ).scrollTop() : 0;
2594
+
2595
+ // Now check if datepicker is showing outside window viewport - move to a better place if so.
2596
+ offset.left -= Math.min( offset.left, ( offset.left + dpWidth > viewWidth && viewWidth > dpWidth ) ?
2597
+ Math.abs( offset.left + dpWidth - viewWidth ) : 0 );
2598
+ offset.top -= Math.min( offset.top, ( offset.top + dpHeight > viewHeight && viewHeight > dpHeight ) ?
2599
+ Math.abs( dpHeight + inputHeight ) : 0 );
2600
+
2601
+ return offset;
2602
+ },
2603
+
2604
+ /* Find an object's position on the screen. */
2605
+ _findPos: function( obj ) {
2606
+ var position,
2607
+ inst = this._getInst( obj ),
2608
+ isRTL = this._get( inst, "isRTL" );
2609
+
2610
+ while ( obj && ( obj.type === "hidden" || obj.nodeType !== 1 || $.expr.filters.hidden( obj ) ) ) {
2611
+ obj = obj[ isRTL ? "previousSibling" : "nextSibling" ];
2612
+ }
2613
+
2614
+ position = $( obj ).offset();
2615
+ return [ position.left, position.top ];
2616
+ },
2617
+
2618
+ /* Hide the date picker from view.
2619
+ * @param input element - the input field attached to the date picker
2620
+ */
2621
+ _hideDatepicker: function( input ) {
2622
+ var showAnim, duration, postProcess, onClose,
2623
+ inst = this._curInst;
2624
+
2625
+ if ( !inst || ( input && inst !== $.data( input, "datepicker" ) ) ) {
2626
+ return;
2627
+ }
2628
+
2629
+ if ( this._datepickerShowing ) {
2630
+ showAnim = this._get( inst, "showAnim" );
2631
+ duration = this._get( inst, "duration" );
2632
+ postProcess = function() {
2633
+ $.datepicker._tidyDialog( inst );
2634
+ };
2635
+
2636
+ // DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed
2637
+ if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) {
2638
+ inst.dpDiv.hide( showAnim, $.datepicker._get( inst, "showOptions" ), duration, postProcess );
2639
+ } else {
2640
+ inst.dpDiv[ ( showAnim === "slideDown" ? "slideUp" :
2641
+ ( showAnim === "fadeIn" ? "fadeOut" : "hide" ) ) ]( ( showAnim ? duration : null ), postProcess );
2642
+ }
2643
+
2644
+ if ( !showAnim ) {
2645
+ postProcess();
2646
+ }
2647
+ this._datepickerShowing = false;
2648
+
2649
+ onClose = this._get( inst, "onClose" );
2650
+ if ( onClose ) {
2651
+ onClose.apply( ( inst.input ? inst.input[ 0 ] : null ), [ ( inst.input ? inst.input.val() : "" ), inst ] );
2652
+ }
2653
+
2654
+ this._lastInput = null;
2655
+ if ( this._inDialog ) {
2656
+ this._dialogInput.css( { position: "absolute", left: "0", top: "-100px" } );
2657
+ if ( $.blockUI ) {
2658
+ $.unblockUI();
2659
+ $( "body" ).append( this.dpDiv );
2660
+ }
2661
+ }
2662
+ this._inDialog = false;
2663
+ }
2664
+ },
2665
+
2666
+ /* Tidy up after a dialog display. */
2667
+ _tidyDialog: function( inst ) {
2668
+ inst.dpDiv.removeClass( this._dialogClass ).off( ".ui-datepicker-calendar" );
2669
+ },
2670
+
2671
+ /* Close date picker if clicked elsewhere. */
2672
+ _checkExternalClick: function( event ) {
2673
+ if ( !$.datepicker._curInst ) {
2674
+ return;
2675
+ }
2676
+
2677
+ var $target = $( event.target ),
2678
+ inst = $.datepicker._getInst( $target[ 0 ] );
2679
+
2680
+ if ( ( ( $target[ 0 ].id !== $.datepicker._mainDivId &&
2681
+ $target.parents( "#" + $.datepicker._mainDivId ).length === 0 &&
2682
+ !$target.hasClass( $.datepicker.markerClassName ) &&
2683
+ !$target.closest( "." + $.datepicker._triggerClass ).length &&
2684
+ $.datepicker._datepickerShowing && !( $.datepicker._inDialog && $.blockUI ) ) ) ||
2685
+ ( $target.hasClass( $.datepicker.markerClassName ) && $.datepicker._curInst !== inst ) ) {
2686
+ $.datepicker._hideDatepicker();
2687
+ }
2688
+ },
2689
+
2690
+ /* Adjust one of the date sub-fields. */
2691
+ _adjustDate: function( id, offset, period ) {
2692
+ var target = $( id ),
2693
+ inst = this._getInst( target[ 0 ] );
2694
+
2695
+ if ( this._isDisabledDatepicker( target[ 0 ] ) ) {
2696
+ return;
2697
+ }
2698
+ this._adjustInstDate( inst, offset +
2699
+ ( period === "M" ? this._get( inst, "showCurrentAtPos" ) : 0 ), // undo positioning
2700
+ period );
2701
+ this._updateDatepicker( inst );
2702
+ },
2703
+
2704
+ /* Action for current link. */
2705
+ _gotoToday: function( id ) {
2706
+ var date,
2707
+ target = $( id ),
2708
+ inst = this._getInst( target[ 0 ] );
2709
+
2710
+ if ( this._get( inst, "gotoCurrent" ) && inst.currentDay ) {
2711
+ inst.selectedDay = inst.currentDay;
2712
+ inst.drawMonth = inst.selectedMonth = inst.currentMonth;
2713
+ inst.drawYear = inst.selectedYear = inst.currentYear;
2714
+ } else {
2715
+ date = new Date();
2716
+ inst.selectedDay = date.getDate();
2717
+ inst.drawMonth = inst.selectedMonth = date.getMonth();
2718
+ inst.drawYear = inst.selectedYear = date.getFullYear();
2719
+ }
2720
+ this._notifyChange( inst );
2721
+ this._adjustDate( target );
2722
+ },
2723
+
2724
+ /* Action for selecting a new month/year. */
2725
+ _selectMonthYear: function( id, select, period ) {
2726
+ var target = $( id ),
2727
+ inst = this._getInst( target[ 0 ] );
2728
+
2729
+ inst[ "selected" + ( period === "M" ? "Month" : "Year" ) ] =
2730
+ inst[ "draw" + ( period === "M" ? "Month" : "Year" ) ] =
2731
+ parseInt( select.options[ select.selectedIndex ].value, 10 );
2732
+
2733
+ this._notifyChange( inst );
2734
+ this._adjustDate( target );
2735
+ },
2736
+
2737
+ /* Action for selecting a day. */
2738
+ _selectDay: function( id, month, year, td ) {
2739
+ var inst,
2740
+ target = $( id );
2741
+
2742
+ if ( $( td ).hasClass( this._unselectableClass ) || this._isDisabledDatepicker( target[ 0 ] ) ) {
2743
+ return;
2744
+ }
2745
+
2746
+ inst = this._getInst( target[ 0 ] );
2747
+ inst.selectedDay = inst.currentDay = $( "a", td ).html();
2748
+ inst.selectedMonth = inst.currentMonth = month;
2749
+ inst.selectedYear = inst.currentYear = year;
2750
+ this._selectDate( id, this._formatDate( inst,
2751
+ inst.currentDay, inst.currentMonth, inst.currentYear ) );
2752
+ },
2753
+
2754
+ /* Erase the input field and hide the date picker. */
2755
+ _clearDate: function( id ) {
2756
+ var target = $( id );
2757
+ this._selectDate( target, "" );
2758
+ },
2759
+
2760
+ /* Update the input field with the selected date. */
2761
+ _selectDate: function( id, dateStr ) {
2762
+ var onSelect,
2763
+ target = $( id ),
2764
+ inst = this._getInst( target[ 0 ] );
2765
+
2766
+ dateStr = ( dateStr != null ? dateStr : this._formatDate( inst ) );
2767
+ if ( inst.input ) {
2768
+ inst.input.val( dateStr );
2769
+ }
2770
+ this._updateAlternate( inst );
2771
+
2772
+ onSelect = this._get( inst, "onSelect" );
2773
+ if ( onSelect ) {
2774
+ onSelect.apply( ( inst.input ? inst.input[ 0 ] : null ), [ dateStr, inst ] ); // trigger custom callback
2775
+ } else if ( inst.input ) {
2776
+ inst.input.trigger( "change" ); // fire the change event
2777
+ }
2778
+
2779
+ if ( inst.inline ) {
2780
+ this._updateDatepicker( inst );
2781
+ } else {
2782
+ this._hideDatepicker();
2783
+ this._lastInput = inst.input[ 0 ];
2784
+ if ( typeof( inst.input[ 0 ] ) !== "object" ) {
2785
+ inst.input.trigger( "focus" ); // restore focus
2786
+ }
2787
+ this._lastInput = null;
2788
+ }
2789
+ },
2790
+
2791
+ /* Update any alternate field to synchronise with the main field. */
2792
+ _updateAlternate: function( inst ) {
2793
+ var altFormat, date, dateStr,
2794
+ altField = this._get( inst, "altField" );
2795
+
2796
+ if ( altField ) { // update alternate field too
2797
+ altFormat = this._get( inst, "altFormat" ) || this._get( inst, "dateFormat" );
2798
+ date = this._getDate( inst );
2799
+ dateStr = this.formatDate( altFormat, date, this._getFormatConfig( inst ) );
2800
+ $( altField ).val( dateStr );
2801
+ }
2802
+ },
2803
+
2804
+ /* Set as beforeShowDay function to prevent selection of weekends.
2805
+ * @param date Date - the date to customise
2806
+ * @return [boolean, string] - is this date selectable?, what is its CSS class?
2807
+ */
2808
+ noWeekends: function( date ) {
2809
+ var day = date.getDay();
2810
+ return [ ( day > 0 && day < 6 ), "" ];
2811
+ },
2812
+
2813
+ /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
2814
+ * @param date Date - the date to get the week for
2815
+ * @return number - the number of the week within the year that contains this date
2816
+ */
2817
+ iso8601Week: function( date ) {
2818
+ var time,
2819
+ checkDate = new Date( date.getTime() );
2820
+
2821
+ // Find Thursday of this week starting on Monday
2822
+ checkDate.setDate( checkDate.getDate() + 4 - ( checkDate.getDay() || 7 ) );
2823
+
2824
+ time = checkDate.getTime();
2825
+ checkDate.setMonth( 0 ); // Compare with Jan 1
2826
+ checkDate.setDate( 1 );
2827
+ return Math.floor( Math.round( ( time - checkDate ) / 86400000 ) / 7 ) + 1;
2828
+ },
2829
+
2830
+ /* Parse a string value into a date object.
2831
+ * See formatDate below for the possible formats.
2832
+ *
2833
+ * @param format string - the expected format of the date
2834
+ * @param value string - the date in the above format
2835
+ * @param settings Object - attributes include:
2836
+ * shortYearCutoff number - the cutoff year for determining the century (optional)
2837
+ * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
2838
+ * dayNames string[7] - names of the days from Sunday (optional)
2839
+ * monthNamesShort string[12] - abbreviated names of the months (optional)
2840
+ * monthNames string[12] - names of the months (optional)
2841
+ * @return Date - the extracted date value or null if value is blank
2842
+ */
2843
+ parseDate: function( format, value, settings ) {
2844
+ if ( format == null || value == null ) {
2845
+ throw "Invalid arguments";
2846
+ }
2847
+
2848
+ value = ( typeof value === "object" ? value.toString() : value + "" );
2849
+ if ( value === "" ) {
2850
+ return null;
2851
+ }
2852
+
2853
+ var iFormat, dim, extra,
2854
+ iValue = 0,
2855
+ shortYearCutoffTemp = ( settings ? settings.shortYearCutoff : null ) || this._defaults.shortYearCutoff,
2856
+ shortYearCutoff = ( typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp :
2857
+ new Date().getFullYear() % 100 + parseInt( shortYearCutoffTemp, 10 ) ),
2858
+ dayNamesShort = ( settings ? settings.dayNamesShort : null ) || this._defaults.dayNamesShort,
2859
+ dayNames = ( settings ? settings.dayNames : null ) || this._defaults.dayNames,
2860
+ monthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort,
2861
+ monthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames,
2862
+ year = -1,
2863
+ month = -1,
2864
+ day = -1,
2865
+ doy = -1,
2866
+ literal = false,
2867
+ date,
2868
+
2869
+ // Check whether a format character is doubled
2870
+ lookAhead = function( match ) {
2871
+ var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );
2872
+ if ( matches ) {
2873
+ iFormat++;
2874
+ }
2875
+ return matches;
2876
+ },
2877
+
2878
+ // Extract a number from the string value
2879
+ getNumber = function( match ) {
2880
+ var isDoubled = lookAhead( match ),
2881
+ size = ( match === "@" ? 14 : ( match === "!" ? 20 :
2882
+ ( match === "y" && isDoubled ? 4 : ( match === "o" ? 3 : 2 ) ) ) ),
2883
+ minSize = ( match === "y" ? size : 1 ),
2884
+ digits = new RegExp( "^\\d{" + minSize + "," + size + "}" ),
2885
+ num = value.substring( iValue ).match( digits );
2886
+ if ( !num ) {
2887
+ throw "Missing number at position " + iValue;
2888
+ }
2889
+ iValue += num[ 0 ].length;
2890
+ return parseInt( num[ 0 ], 10 );
2891
+ },
2892
+
2893
+ // Extract a name from the string value and convert to an index
2894
+ getName = function( match, shortNames, longNames ) {
2895
+ var index = -1,
2896
+ names = $.map( lookAhead( match ) ? longNames : shortNames, function( v, k ) {
2897
+ return [ [ k, v ] ];
2898
+ } ).sort( function( a, b ) {
2899
+ return -( a[ 1 ].length - b[ 1 ].length );
2900
+ } );
2901
+
2902
+ $.each( names, function( i, pair ) {
2903
+ var name = pair[ 1 ];
2904
+ if ( value.substr( iValue, name.length ).toLowerCase() === name.toLowerCase() ) {
2905
+ index = pair[ 0 ];
2906
+ iValue += name.length;
2907
+ return false;
2908
+ }
2909
+ } );
2910
+ if ( index !== -1 ) {
2911
+ return index + 1;
2912
+ } else {
2913
+ throw "Unknown name at position " + iValue;
2914
+ }
2915
+ },
2916
+
2917
+ // Confirm that a literal character matches the string value
2918
+ checkLiteral = function() {
2919
+ if ( value.charAt( iValue ) !== format.charAt( iFormat ) ) {
2920
+ throw "Unexpected literal at position " + iValue;
2921
+ }
2922
+ iValue++;
2923
+ };
2924
+
2925
+ for ( iFormat = 0; iFormat < format.length; iFormat++ ) {
2926
+ if ( literal ) {
2927
+ if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) {
2928
+ literal = false;
2929
+ } else {
2930
+ checkLiteral();
2931
+ }
2932
+ } else {
2933
+ switch ( format.charAt( iFormat ) ) {
2934
+ case "d":
2935
+ day = getNumber( "d" );
2936
+ break;
2937
+ case "D":
2938
+ getName( "D", dayNamesShort, dayNames );
2939
+ break;
2940
+ case "o":
2941
+ doy = getNumber( "o" );
2942
+ break;
2943
+ case "m":
2944
+ month = getNumber( "m" );
2945
+ break;
2946
+ case "M":
2947
+ month = getName( "M", monthNamesShort, monthNames );
2948
+ break;
2949
+ case "y":
2950
+ year = getNumber( "y" );
2951
+ break;
2952
+ case "@":
2953
+ date = new Date( getNumber( "@" ) );
2954
+ year = date.getFullYear();
2955
+ month = date.getMonth() + 1;
2956
+ day = date.getDate();
2957
+ break;
2958
+ case "!":
2959
+ date = new Date( ( getNumber( "!" ) - this._ticksTo1970 ) / 10000 );
2960
+ year = date.getFullYear();
2961
+ month = date.getMonth() + 1;
2962
+ day = date.getDate();
2963
+ break;
2964
+ case "'":
2965
+ if ( lookAhead( "'" ) ) {
2966
+ checkLiteral();
2967
+ } else {
2968
+ literal = true;
2969
+ }
2970
+ break;
2971
+ default:
2972
+ checkLiteral();
2973
+ }
2974
+ }
2975
+ }
2976
+
2977
+ if ( iValue < value.length ) {
2978
+ extra = value.substr( iValue );
2979
+ if ( !/^\s+/.test( extra ) ) {
2980
+ throw "Extra/unparsed characters found in date: " + extra;
2981
+ }
2982
+ }
2983
+
2984
+ if ( year === -1 ) {
2985
+ year = new Date().getFullYear();
2986
+ } else if ( year < 100 ) {
2987
+ year += new Date().getFullYear() - new Date().getFullYear() % 100 +
2988
+ ( year <= shortYearCutoff ? 0 : -100 );
2989
+ }
2990
+
2991
+ if ( doy > -1 ) {
2992
+ month = 1;
2993
+ day = doy;
2994
+ do {
2995
+ dim = this._getDaysInMonth( year, month - 1 );
2996
+ if ( day <= dim ) {
2997
+ break;
2998
+ }
2999
+ month++;
3000
+ day -= dim;
3001
+ } while ( true );
3002
+ }
3003
+
3004
+ date = this._daylightSavingAdjust( new Date( year, month - 1, day ) );
3005
+ if ( date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day ) {
3006
+ throw "Invalid date"; // E.g. 31/02/00
3007
+ }
3008
+ return date;
3009
+ },
3010
+
3011
+ /* Standard date formats. */
3012
+ ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601)
3013
+ COOKIE: "D, dd M yy",
3014
+ ISO_8601: "yy-mm-dd",
3015
+ RFC_822: "D, d M y",
3016
+ RFC_850: "DD, dd-M-y",
3017
+ RFC_1036: "D, d M y",
3018
+ RFC_1123: "D, d M yy",
3019
+ RFC_2822: "D, d M yy",
3020
+ RSS: "D, d M y", // RFC 822
3021
+ TICKS: "!",
3022
+ TIMESTAMP: "@",
3023
+ W3C: "yy-mm-dd", // ISO 8601
3024
+
3025
+ _ticksTo1970: ( ( ( 1970 - 1 ) * 365 + Math.floor( 1970 / 4 ) - Math.floor( 1970 / 100 ) +
3026
+ Math.floor( 1970 / 400 ) ) * 24 * 60 * 60 * 10000000 ),
3027
+
3028
+ /* Format a date object into a string value.
3029
+ * The format can be combinations of the following:
3030
+ * d - day of month (no leading zero)
3031
+ * dd - day of month (two digit)
3032
+ * o - day of year (no leading zeros)
3033
+ * oo - day of year (three digit)
3034
+ * D - day name short
3035
+ * DD - day name long
3036
+ * m - month of year (no leading zero)
3037
+ * mm - month of year (two digit)
3038
+ * M - month name short
3039
+ * MM - month name long
3040
+ * y - year (two digit)
3041
+ * yy - year (four digit)
3042
+ * @ - Unix timestamp (ms since 01/01/1970)
3043
+ * ! - Windows ticks (100ns since 01/01/0001)
3044
+ * "..." - literal text
3045
+ * '' - single quote
3046
+ *
3047
+ * @param format string - the desired format of the date
3048
+ * @param date Date - the date value to format
3049
+ * @param settings Object - attributes include:
3050
+ * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
3051
+ * dayNames string[7] - names of the days from Sunday (optional)
3052
+ * monthNamesShort string[12] - abbreviated names of the months (optional)
3053
+ * monthNames string[12] - names of the months (optional)
3054
+ * @return string - the date in the above format
3055
+ */
3056
+ formatDate: function( format, date, settings ) {
3057
+ if ( !date ) {
3058
+ return "";
3059
+ }
3060
+
3061
+ var iFormat,
3062
+ dayNamesShort = ( settings ? settings.dayNamesShort : null ) || this._defaults.dayNamesShort,
3063
+ dayNames = ( settings ? settings.dayNames : null ) || this._defaults.dayNames,
3064
+ monthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort,
3065
+ monthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames,
3066
+
3067
+ // Check whether a format character is doubled
3068
+ lookAhead = function( match ) {
3069
+ var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );
3070
+ if ( matches ) {
3071
+ iFormat++;
3072
+ }
3073
+ return matches;
3074
+ },
3075
+
3076
+ // Format a number, with leading zero if necessary
3077
+ formatNumber = function( match, value, len ) {
3078
+ var num = "" + value;
3079
+ if ( lookAhead( match ) ) {
3080
+ while ( num.length < len ) {
3081
+ num = "0" + num;
3082
+ }
3083
+ }
3084
+ return num;
3085
+ },
3086
+
3087
+ // Format a name, short or long as requested
3088
+ formatName = function( match, value, shortNames, longNames ) {
3089
+ return ( lookAhead( match ) ? longNames[ value ] : shortNames[ value ] );
3090
+ },
3091
+ output = "",
3092
+ literal = false;
3093
+
3094
+ if ( date ) {
3095
+ for ( iFormat = 0; iFormat < format.length; iFormat++ ) {
3096
+ if ( literal ) {
3097
+ if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) {
3098
+ literal = false;
3099
+ } else {
3100
+ output += format.charAt( iFormat );
3101
+ }
3102
+ } else {
3103
+ switch ( format.charAt( iFormat ) ) {
3104
+ case "d":
3105
+ output += formatNumber( "d", date.getDate(), 2 );
3106
+ break;
3107
+ case "D":
3108
+ output += formatName( "D", date.getDay(), dayNamesShort, dayNames );
3109
+ break;
3110
+ case "o":
3111
+ output += formatNumber( "o",
3112
+ Math.round( ( new Date( date.getFullYear(), date.getMonth(), date.getDate() ).getTime() - new Date( date.getFullYear(), 0, 0 ).getTime() ) / 86400000 ), 3 );
3113
+ break;
3114
+ case "m":
3115
+ output += formatNumber( "m", date.getMonth() + 1, 2 );
3116
+ break;
3117
+ case "M":
3118
+ output += formatName( "M", date.getMonth(), monthNamesShort, monthNames );
3119
+ break;
3120
+ case "y":
3121
+ output += ( lookAhead( "y" ) ? date.getFullYear() :
3122
+ ( date.getFullYear() % 100 < 10 ? "0" : "" ) + date.getFullYear() % 100 );
3123
+ break;
3124
+ case "@":
3125
+ output += date.getTime();
3126
+ break;
3127
+ case "!":
3128
+ output += date.getTime() * 10000 + this._ticksTo1970;
3129
+ break;
3130
+ case "'":
3131
+ if ( lookAhead( "'" ) ) {
3132
+ output += "'";
3133
+ } else {
3134
+ literal = true;
3135
+ }
3136
+ break;
3137
+ default:
3138
+ output += format.charAt( iFormat );
3139
+ }
3140
+ }
3141
+ }
3142
+ }
3143
+ return output;
3144
+ },
3145
+
3146
+ /* Extract all possible characters from the date format. */
3147
+ _possibleChars: function( format ) {
3148
+ var iFormat,
3149
+ chars = "",
3150
+ literal = false,
3151
+
3152
+ // Check whether a format character is doubled
3153
+ lookAhead = function( match ) {
3154
+ var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );
3155
+ if ( matches ) {
3156
+ iFormat++;
3157
+ }
3158
+ return matches;
3159
+ };
3160
+
3161
+ for ( iFormat = 0; iFormat < format.length; iFormat++ ) {
3162
+ if ( literal ) {
3163
+ if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) {
3164
+ literal = false;
3165
+ } else {
3166
+ chars += format.charAt( iFormat );
3167
+ }
3168
+ } else {
3169
+ switch ( format.charAt( iFormat ) ) {
3170
+ case "d": case "m": case "y": case "@":
3171
+ chars += "0123456789";
3172
+ break;
3173
+ case "D": case "M":
3174
+ return null; // Accept anything
3175
+ case "'":
3176
+ if ( lookAhead( "'" ) ) {
3177
+ chars += "'";
3178
+ } else {
3179
+ literal = true;
3180
+ }
3181
+ break;
3182
+ default:
3183
+ chars += format.charAt( iFormat );
3184
+ }
3185
+ }
3186
+ }
3187
+ return chars;
3188
+ },
3189
+
3190
+ /* Get a setting value, defaulting if necessary. */
3191
+ _get: function( inst, name ) {
3192
+ return inst.settings[ name ] !== undefined ?
3193
+ inst.settings[ name ] : this._defaults[ name ];
3194
+ },
3195
+
3196
+ /* Parse existing date and initialise date picker. */
3197
+ _setDateFromField: function( inst, noDefault ) {
3198
+ if ( inst.input.val() === inst.lastVal ) {
3199
+ return;
3200
+ }
3201
+
3202
+ var dateFormat = this._get( inst, "dateFormat" ),
3203
+ dates = inst.lastVal = inst.input ? inst.input.val() : null,
3204
+ defaultDate = this._getDefaultDate( inst ),
3205
+ date = defaultDate,
3206
+ settings = this._getFormatConfig( inst );
3207
+
3208
+ try {
3209
+ date = this.parseDate( dateFormat, dates, settings ) || defaultDate;
3210
+ } catch ( event ) {
3211
+ dates = ( noDefault ? "" : dates );
3212
+ }
3213
+ inst.selectedDay = date.getDate();
3214
+ inst.drawMonth = inst.selectedMonth = date.getMonth();
3215
+ inst.drawYear = inst.selectedYear = date.getFullYear();
3216
+ inst.currentDay = ( dates ? date.getDate() : 0 );
3217
+ inst.currentMonth = ( dates ? date.getMonth() : 0 );
3218
+ inst.currentYear = ( dates ? date.getFullYear() : 0 );
3219
+ this._adjustInstDate( inst );
3220
+ },
3221
+
3222
+ /* Retrieve the default date shown on opening. */
3223
+ _getDefaultDate: function( inst ) {
3224
+ return this._restrictMinMax( inst,
3225
+ this._determineDate( inst, this._get( inst, "defaultDate" ), new Date() ) );
3226
+ },
3227
+
3228
+ /* A date may be specified as an exact value or a relative one. */
3229
+ _determineDate: function( inst, date, defaultDate ) {
3230
+ var offsetNumeric = function( offset ) {
3231
+ var date = new Date();
3232
+ date.setDate( date.getDate() + offset );
3233
+ return date;
3234
+ },
3235
+ offsetString = function( offset ) {
3236
+ try {
3237
+ return $.datepicker.parseDate( $.datepicker._get( inst, "dateFormat" ),
3238
+ offset, $.datepicker._getFormatConfig( inst ) );
3239
+ }
3240
+ catch ( e ) {
3241
+
3242
+ // Ignore
3243
+ }
3244
+
3245
+ var date = ( offset.toLowerCase().match( /^c/ ) ?
3246
+ $.datepicker._getDate( inst ) : null ) || new Date(),
3247
+ year = date.getFullYear(),
3248
+ month = date.getMonth(),
3249
+ day = date.getDate(),
3250
+ pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,
3251
+ matches = pattern.exec( offset );
3252
+
3253
+ while ( matches ) {
3254
+ switch ( matches[ 2 ] || "d" ) {
3255
+ case "d" : case "D" :
3256
+ day += parseInt( matches[ 1 ], 10 ); break;
3257
+ case "w" : case "W" :
3258
+ day += parseInt( matches[ 1 ], 10 ) * 7; break;
3259
+ case "m" : case "M" :
3260
+ month += parseInt( matches[ 1 ], 10 );
3261
+ day = Math.min( day, $.datepicker._getDaysInMonth( year, month ) );
3262
+ break;
3263
+ case "y": case "Y" :
3264
+ year += parseInt( matches[ 1 ], 10 );
3265
+ day = Math.min( day, $.datepicker._getDaysInMonth( year, month ) );
3266
+ break;
3267
+ }
3268
+ matches = pattern.exec( offset );
3269
+ }
3270
+ return new Date( year, month, day );
3271
+ },
3272
+ newDate = ( date == null || date === "" ? defaultDate : ( typeof date === "string" ? offsetString( date ) :
3273
+ ( typeof date === "number" ? ( isNaN( date ) ? defaultDate : offsetNumeric( date ) ) : new Date( date.getTime() ) ) ) );
3274
+
3275
+ newDate = ( newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate );
3276
+ if ( newDate ) {
3277
+ newDate.setHours( 0 );
3278
+ newDate.setMinutes( 0 );
3279
+ newDate.setSeconds( 0 );
3280
+ newDate.setMilliseconds( 0 );
3281
+ }
3282
+ return this._daylightSavingAdjust( newDate );
3283
+ },
3284
+
3285
+ /* Handle switch to/from daylight saving.
3286
+ * Hours may be non-zero on daylight saving cut-over:
3287
+ * > 12 when midnight changeover, but then cannot generate
3288
+ * midnight datetime, so jump to 1AM, otherwise reset.
3289
+ * @param date (Date) the date to check
3290
+ * @return (Date) the corrected date
3291
+ */
3292
+ _daylightSavingAdjust: function( date ) {
3293
+ if ( !date ) {
3294
+ return null;
3295
+ }
3296
+ date.setHours( date.getHours() > 12 ? date.getHours() + 2 : 0 );
3297
+ return date;
3298
+ },
3299
+
3300
+ /* Set the date(s) directly. */
3301
+ _setDate: function( inst, date, noChange ) {
3302
+ var clear = !date,
3303
+ origMonth = inst.selectedMonth,
3304
+ origYear = inst.selectedYear,
3305
+ newDate = this._restrictMinMax( inst, this._determineDate( inst, date, new Date() ) );
3306
+
3307
+ inst.selectedDay = inst.currentDay = newDate.getDate();
3308
+ inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
3309
+ inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
3310
+ if ( ( origMonth !== inst.selectedMonth || origYear !== inst.selectedYear ) && !noChange ) {
3311
+ this._notifyChange( inst );
3312
+ }
3313
+ this._adjustInstDate( inst );
3314
+ if ( inst.input ) {
3315
+ inst.input.val( clear ? "" : this._formatDate( inst ) );
3316
+ }
3317
+ },
3318
+
3319
+ /* Retrieve the date(s) directly. */
3320
+ _getDate: function( inst ) {
3321
+ var startDate = ( !inst.currentYear || ( inst.input && inst.input.val() === "" ) ? null :
3322
+ this._daylightSavingAdjust( new Date(
3323
+ inst.currentYear, inst.currentMonth, inst.currentDay ) ) );
3324
+ return startDate;
3325
+ },
3326
+
3327
+ /* Attach the onxxx handlers. These are declared statically so
3328
+ * they work with static code transformers like Caja.
3329
+ */
3330
+ _attachHandlers: function( inst ) {
3331
+ var stepMonths = this._get( inst, "stepMonths" ),
3332
+ id = "#" + inst.id.replace( /\\\\/g, "\\" );
3333
+ inst.dpDiv.find( "[data-handler]" ).map( function() {
3334
+ var handler = {
3335
+ prev: function() {
3336
+ $.datepicker._adjustDate( id, -stepMonths, "M" );
3337
+ },
3338
+ next: function() {
3339
+ $.datepicker._adjustDate( id, +stepMonths, "M" );
3340
+ },
3341
+ hide: function() {
3342
+ $.datepicker._hideDatepicker();
3343
+ },
3344
+ today: function() {
3345
+ $.datepicker._gotoToday( id );
3346
+ },
3347
+ selectDay: function() {
3348
+ $.datepicker._selectDay( id, +this.getAttribute( "data-month" ), +this.getAttribute( "data-year" ), this );
3349
+ return false;
3350
+ },
3351
+ selectMonth: function() {
3352
+ $.datepicker._selectMonthYear( id, this, "M" );
3353
+ return false;
3354
+ },
3355
+ selectYear: function() {
3356
+ $.datepicker._selectMonthYear( id, this, "Y" );
3357
+ return false;
3358
+ }
3359
+ };
3360
+ $( this ).on( this.getAttribute( "data-event" ), handler[ this.getAttribute( "data-handler" ) ] );
3361
+ } );
3362
+ },
3363
+
3364
+ /* Generate the HTML for the current state of the date picker. */
3365
+ _generateHTML: function( inst ) {
3366
+ var maxDraw, prevText, prev, nextText, next, currentText, gotoDate,
3367
+ controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin,
3368
+ monthNames, monthNamesShort, beforeShowDay, showOtherMonths,
3369
+ selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate,
3370
+ cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows,
3371
+ printDate, dRow, tbody, daySettings, otherMonth, unselectable,
3372
+ tempDate = new Date(),
3373
+ today = this._daylightSavingAdjust(
3374
+ new Date( tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate() ) ), // clear time
3375
+ isRTL = this._get( inst, "isRTL" ),
3376
+ showButtonPanel = this._get( inst, "showButtonPanel" ),
3377
+ hideIfNoPrevNext = this._get( inst, "hideIfNoPrevNext" ),
3378
+ navigationAsDateFormat = this._get( inst, "navigationAsDateFormat" ),
3379
+ numMonths = this._getNumberOfMonths( inst ),
3380
+ showCurrentAtPos = this._get( inst, "showCurrentAtPos" ),
3381
+ stepMonths = this._get( inst, "stepMonths" ),
3382
+ isMultiMonth = ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ),
3383
+ currentDate = this._daylightSavingAdjust( ( !inst.currentDay ? new Date( 9999, 9, 9 ) :
3384
+ new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) ),
3385
+ minDate = this._getMinMaxDate( inst, "min" ),
3386
+ maxDate = this._getMinMaxDate( inst, "max" ),
3387
+ drawMonth = inst.drawMonth - showCurrentAtPos,
3388
+ drawYear = inst.drawYear;
3389
+
3390
+ if ( drawMonth < 0 ) {
3391
+ drawMonth += 12;
3392
+ drawYear--;
3393
+ }
3394
+ if ( maxDate ) {
3395
+ maxDraw = this._daylightSavingAdjust( new Date( maxDate.getFullYear(),
3396
+ maxDate.getMonth() - ( numMonths[ 0 ] * numMonths[ 1 ] ) + 1, maxDate.getDate() ) );
3397
+ maxDraw = ( minDate && maxDraw < minDate ? minDate : maxDraw );
3398
+ while ( this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 ) ) > maxDraw ) {
3399
+ drawMonth--;
3400
+ if ( drawMonth < 0 ) {
3401
+ drawMonth = 11;
3402
+ drawYear--;
3403
+ }
3404
+ }
3405
+ }
3406
+ inst.drawMonth = drawMonth;
3407
+ inst.drawYear = drawYear;
3408
+
3409
+ prevText = this._get( inst, "prevText" );
3410
+ prevText = ( !navigationAsDateFormat ? prevText : this.formatDate( prevText,
3411
+ this._daylightSavingAdjust( new Date( drawYear, drawMonth - stepMonths, 1 ) ),
3412
+ this._getFormatConfig( inst ) ) );
3413
+
3414
+ prev = ( this._canAdjustMonth( inst, -1, drawYear, drawMonth ) ?
3415
+ "<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click'" +
3416
+ " title='" + prevText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w" ) + "'>" + prevText + "</span></a>" :
3417
+ ( 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>" ) );
3418
+
3419
+ nextText = this._get( inst, "nextText" );
3420
+ nextText = ( !navigationAsDateFormat ? nextText : this.formatDate( nextText,
3421
+ this._daylightSavingAdjust( new Date( drawYear, drawMonth + stepMonths, 1 ) ),
3422
+ this._getFormatConfig( inst ) ) );
3423
+
3424
+ next = ( this._canAdjustMonth( inst, +1, drawYear, drawMonth ) ?
3425
+ "<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click'" +
3426
+ " title='" + nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e" ) + "'>" + nextText + "</span></a>" :
3427
+ ( 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>" ) );
3428
+
3429
+ currentText = this._get( inst, "currentText" );
3430
+ gotoDate = ( this._get( inst, "gotoCurrent" ) && inst.currentDay ? currentDate : today );
3431
+ currentText = ( !navigationAsDateFormat ? currentText :
3432
+ this.formatDate( currentText, gotoDate, this._getFormatConfig( inst ) ) );
3433
+
3434
+ 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'>" +
3435
+ this._get( inst, "closeText" ) + "</button>" : "" );
3436
+
3437
+ buttonPanel = ( showButtonPanel ) ? "<div class='ui-datepicker-buttonpane ui-widget-content'>" + ( isRTL ? controls : "" ) +
3438
+ ( 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'" +
3439
+ ">" + currentText + "</button>" : "" ) + ( isRTL ? "" : controls ) + "</div>" : "";
3440
+
3441
+ firstDay = parseInt( this._get( inst, "firstDay" ), 10 );
3442
+ firstDay = ( isNaN( firstDay ) ? 0 : firstDay );
3443
+
3444
+ showWeek = this._get( inst, "showWeek" );
3445
+ dayNames = this._get( inst, "dayNames" );
3446
+ dayNamesMin = this._get( inst, "dayNamesMin" );
3447
+ monthNames = this._get( inst, "monthNames" );
3448
+ monthNamesShort = this._get( inst, "monthNamesShort" );
3449
+ beforeShowDay = this._get( inst, "beforeShowDay" );
3450
+ showOtherMonths = this._get( inst, "showOtherMonths" );
3451
+ selectOtherMonths = this._get( inst, "selectOtherMonths" );
3452
+ defaultDate = this._getDefaultDate( inst );
3453
+ html = "";
3454
+
3455
+ for ( row = 0; row < numMonths[ 0 ]; row++ ) {
3456
+ group = "";
3457
+ this.maxRows = 4;
3458
+ for ( col = 0; col < numMonths[ 1 ]; col++ ) {
3459
+ selectedDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, inst.selectedDay ) );
3460
+ cornerClass = " ui-corner-all";
3461
+ calender = "";
3462
+ if ( isMultiMonth ) {
3463
+ calender += "<div class='ui-datepicker-group";
3464
+ if ( numMonths[ 1 ] > 1 ) {
3465
+ switch ( col ) {
3466
+ case 0: calender += " ui-datepicker-group-first";
3467
+ cornerClass = " ui-corner-" + ( isRTL ? "right" : "left" ); break;
3468
+ case numMonths[ 1 ] - 1: calender += " ui-datepicker-group-last";
3469
+ cornerClass = " ui-corner-" + ( isRTL ? "left" : "right" ); break;
3470
+ default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break;
3471
+ }
3472
+ }
3473
+ calender += "'>";
3474
+ }
3475
+ calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" +
3476
+ ( /all|left/.test( cornerClass ) && row === 0 ? ( isRTL ? next : prev ) : "" ) +
3477
+ ( /all|right/.test( cornerClass ) && row === 0 ? ( isRTL ? prev : next ) : "" ) +
3478
+ this._generateMonthYearHeader( inst, drawMonth, drawYear, minDate, maxDate,
3479
+ row > 0 || col > 0, monthNames, monthNamesShort ) + // draw month headers
3480
+ "</div><table class='ui-datepicker-calendar'><thead>" +
3481
+ "<tr>";
3482
+ thead = ( showWeek ? "<th class='ui-datepicker-week-col'>" + this._get( inst, "weekHeader" ) + "</th>" : "" );
3483
+ for ( dow = 0; dow < 7; dow++ ) { // days of the week
3484
+ day = ( dow + firstDay ) % 7;
3485
+ thead += "<th scope='col'" + ( ( dow + firstDay + 6 ) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "" ) + ">" +
3486
+ "<span title='" + dayNames[ day ] + "'>" + dayNamesMin[ day ] + "</span></th>";
3487
+ }
3488
+ calender += thead + "</tr></thead><tbody>";
3489
+ daysInMonth = this._getDaysInMonth( drawYear, drawMonth );
3490
+ if ( drawYear === inst.selectedYear && drawMonth === inst.selectedMonth ) {
3491
+ inst.selectedDay = Math.min( inst.selectedDay, daysInMonth );
3492
+ }
3493
+ leadDays = ( this._getFirstDayOfMonth( drawYear, drawMonth ) - firstDay + 7 ) % 7;
3494
+ curRows = Math.ceil( ( leadDays + daysInMonth ) / 7 ); // calculate the number of rows to generate
3495
+ numRows = ( isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows ); //If multiple months, use the higher number of rows (see #7043)
3496
+ this.maxRows = numRows;
3497
+ printDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 - leadDays ) );
3498
+ for ( dRow = 0; dRow < numRows; dRow++ ) { // create date picker rows
3499
+ calender += "<tr>";
3500
+ tbody = ( !showWeek ? "" : "<td class='ui-datepicker-week-col'>" +
3501
+ this._get( inst, "calculateWeek" )( printDate ) + "</td>" );
3502
+ for ( dow = 0; dow < 7; dow++ ) { // create date picker days
3503
+ daySettings = ( beforeShowDay ?
3504
+ beforeShowDay.apply( ( inst.input ? inst.input[ 0 ] : null ), [ printDate ] ) : [ true, "" ] );
3505
+ otherMonth = ( printDate.getMonth() !== drawMonth );
3506
+ unselectable = ( otherMonth && !selectOtherMonths ) || !daySettings[ 0 ] ||
3507
+ ( minDate && printDate < minDate ) || ( maxDate && printDate > maxDate );
3508
+ tbody += "<td class='" +
3509
+ ( ( dow + firstDay + 6 ) % 7 >= 5 ? " ui-datepicker-week-end" : "" ) + // highlight weekends
3510
+ ( otherMonth ? " ui-datepicker-other-month" : "" ) + // highlight days from other months
3511
+ ( ( printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent ) || // user pressed key
3512
+ ( defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime() ) ?
3513
+
3514
+ // or defaultDate is current printedDate and defaultDate is selectedDate
3515
+ " " + this._dayOverClass : "" ) + // highlight selected day
3516
+ ( unselectable ? " " + this._unselectableClass + " ui-state-disabled" : "" ) + // highlight unselectable days
3517
+ ( otherMonth && !showOtherMonths ? "" : " " + daySettings[ 1 ] + // highlight custom dates
3518
+ ( printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "" ) + // highlight selected day
3519
+ ( printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "" ) ) + "'" + // highlight today (if different)
3520
+ ( ( !otherMonth || showOtherMonths ) && daySettings[ 2 ] ? " title='" + daySettings[ 2 ].replace( /'/g, "'" ) + "'" : "" ) + // cell title
3521
+ ( unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'" ) + ">" + // actions
3522
+ ( otherMonth && !showOtherMonths ? " " : // display for other months
3523
+ ( unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" +
3524
+ ( printDate.getTime() === today.getTime() ? " ui-state-highlight" : "" ) +
3525
+ ( printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "" ) + // highlight selected day
3526
+ ( otherMonth ? " ui-priority-secondary" : "" ) + // distinguish dates from other months
3527
+ "' href='#'>" + printDate.getDate() + "</a>" ) ) + "</td>"; // display selectable date
3528
+ printDate.setDate( printDate.getDate() + 1 );
3529
+ printDate = this._daylightSavingAdjust( printDate );
3530
+ }
3531
+ calender += tbody + "</tr>";
3532
+ }
3533
+ drawMonth++;
3534
+ if ( drawMonth > 11 ) {
3535
+ drawMonth = 0;
3536
+ drawYear++;
3537
+ }
3538
+ calender += "</tbody></table>" + ( isMultiMonth ? "</div>" +
3539
+ ( ( numMonths[ 0 ] > 0 && col === numMonths[ 1 ] - 1 ) ? "<div class='ui-datepicker-row-break'></div>" : "" ) : "" );
3540
+ group += calender;
3541
+ }
3542
+ html += group;
3543
+ }
3544
+ html += buttonPanel;
3545
+ inst._keyEvent = false;
3546
+ return html;
3547
+ },
3548
+
3549
+ /* Generate the month and year header. */
3550
+ _generateMonthYearHeader: function( inst, drawMonth, drawYear, minDate, maxDate,
3551
+ secondary, monthNames, monthNamesShort ) {
3552
+
3553
+ var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear,
3554
+ changeMonth = this._get( inst, "changeMonth" ),
3555
+ changeYear = this._get( inst, "changeYear" ),
3556
+ showMonthAfterYear = this._get( inst, "showMonthAfterYear" ),
3557
+ html = "<div class='ui-datepicker-title'>",
3558
+ monthHtml = "";
3559
+
3560
+ // Month selection
3561
+ if ( secondary || !changeMonth ) {
3562
+ monthHtml += "<span class='ui-datepicker-month'>" + monthNames[ drawMonth ] + "</span>";
3563
+ } else {
3564
+ inMinYear = ( minDate && minDate.getFullYear() === drawYear );
3565
+ inMaxYear = ( maxDate && maxDate.getFullYear() === drawYear );
3566
+ monthHtml += "<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>";
3567
+ for ( month = 0; month < 12; month++ ) {
3568
+ if ( ( !inMinYear || month >= minDate.getMonth() ) && ( !inMaxYear || month <= maxDate.getMonth() ) ) {
3569
+ monthHtml += "<option value='" + month + "'" +
3570
+ ( month === drawMonth ? " selected='selected'" : "" ) +
3571
+ ">" + monthNamesShort[ month ] + "</option>";
3572
+ }
3573
+ }
3574
+ monthHtml += "</select>";
3575
+ }
3576
+
3577
+ if ( !showMonthAfterYear ) {
3578
+ html += monthHtml + ( secondary || !( changeMonth && changeYear ) ? " " : "" );
3579
+ }
3580
+
3581
+ // Year selection
3582
+ if ( !inst.yearshtml ) {
3583
+ inst.yearshtml = "";
3584
+ if ( secondary || !changeYear ) {
3585
+ html += "<span class='ui-datepicker-year'>" + drawYear + "</span>";
3586
+ } else {
3587
+
3588
+ // determine range of years to display
3589
+ years = this._get( inst, "yearRange" ).split( ":" );
3590
+ thisYear = new Date().getFullYear();
3591
+ determineYear = function( value ) {
3592
+ var year = ( value.match( /c[+\-].*/ ) ? drawYear + parseInt( value.substring( 1 ), 10 ) :
3593
+ ( value.match( /[+\-].*/ ) ? thisYear + parseInt( value, 10 ) :
3594
+ parseInt( value, 10 ) ) );
3595
+ return ( isNaN( year ) ? thisYear : year );
3596
+ };
3597
+ year = determineYear( years[ 0 ] );
3598
+ endYear = Math.max( year, determineYear( years[ 1 ] || "" ) );
3599
+ year = ( minDate ? Math.max( year, minDate.getFullYear() ) : year );
3600
+ endYear = ( maxDate ? Math.min( endYear, maxDate.getFullYear() ) : endYear );
3601
+ inst.yearshtml += "<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>";
3602
+ for ( ; year <= endYear; year++ ) {
3603
+ inst.yearshtml += "<option value='" + year + "'" +
3604
+ ( year === drawYear ? " selected='selected'" : "" ) +
3605
+ ">" + year + "</option>";
3606
+ }
3607
+ inst.yearshtml += "</select>";
3608
+
3609
+ html += inst.yearshtml;
3610
+ inst.yearshtml = null;
3611
+ }
3612
+ }
3613
+
3614
+ html += this._get( inst, "yearSuffix" );
3615
+ if ( showMonthAfterYear ) {
3616
+ html += ( secondary || !( changeMonth && changeYear ) ? " " : "" ) + monthHtml;
3617
+ }
3618
+ html += "</div>"; // Close datepicker_header
3619
+ return html;
3620
+ },
3621
+
3622
+ /* Adjust one of the date sub-fields. */
3623
+ _adjustInstDate: function( inst, offset, period ) {
3624
+ var year = inst.selectedYear + ( period === "Y" ? offset : 0 ),
3625
+ month = inst.selectedMonth + ( period === "M" ? offset : 0 ),
3626
+ day = Math.min( inst.selectedDay, this._getDaysInMonth( year, month ) ) + ( period === "D" ? offset : 0 ),
3627
+ date = this._restrictMinMax( inst, this._daylightSavingAdjust( new Date( year, month, day ) ) );
3628
+
3629
+ inst.selectedDay = date.getDate();
3630
+ inst.drawMonth = inst.selectedMonth = date.getMonth();
3631
+ inst.drawYear = inst.selectedYear = date.getFullYear();
3632
+ if ( period === "M" || period === "Y" ) {
3633
+ this._notifyChange( inst );
3634
+ }
3635
+ },
3636
+
3637
+ /* Ensure a date is within any min/max bounds. */
3638
+ _restrictMinMax: function( inst, date ) {
3639
+ var minDate = this._getMinMaxDate( inst, "min" ),
3640
+ maxDate = this._getMinMaxDate( inst, "max" ),
3641
+ newDate = ( minDate && date < minDate ? minDate : date );
3642
+ return ( maxDate && newDate > maxDate ? maxDate : newDate );
3643
+ },
3644
+
3645
+ /* Notify change of month/year. */
3646
+ _notifyChange: function( inst ) {
3647
+ var onChange = this._get( inst, "onChangeMonthYear" );
3648
+ if ( onChange ) {
3649
+ onChange.apply( ( inst.input ? inst.input[ 0 ] : null ),
3650
+ [ inst.selectedYear, inst.selectedMonth + 1, inst ] );
3651
+ }
3652
+ },
3653
+
3654
+ /* Determine the number of months to show. */
3655
+ _getNumberOfMonths: function( inst ) {
3656
+ var numMonths = this._get( inst, "numberOfMonths" );
3657
+ return ( numMonths == null ? [ 1, 1 ] : ( typeof numMonths === "number" ? [ 1, numMonths ] : numMonths ) );
3658
+ },
3659
+
3660
+ /* Determine the current maximum date - ensure no time components are set. */
3661
+ _getMinMaxDate: function( inst, minMax ) {
3662
+ return this._determineDate( inst, this._get( inst, minMax + "Date" ), null );
3663
+ },
3664
+
3665
+ /* Find the number of days in a given month. */
3666
+ _getDaysInMonth: function( year, month ) {
3667
+ return 32 - this._daylightSavingAdjust( new Date( year, month, 32 ) ).getDate();
3668
+ },
3669
+
3670
+ /* Find the day of the week of the first of a month. */
3671
+ _getFirstDayOfMonth: function( year, month ) {
3672
+ return new Date( year, month, 1 ).getDay();
3673
+ },
3674
+
3675
+ /* Determines if we should allow a "next/prev" month display change. */
3676
+ _canAdjustMonth: function( inst, offset, curYear, curMonth ) {
3677
+ var numMonths = this._getNumberOfMonths( inst ),
3678
+ date = this._daylightSavingAdjust( new Date( curYear,
3679
+ curMonth + ( offset < 0 ? offset : numMonths[ 0 ] * numMonths[ 1 ] ), 1 ) );
3680
+
3681
+ if ( offset < 0 ) {
3682
+ date.setDate( this._getDaysInMonth( date.getFullYear(), date.getMonth() ) );
3683
+ }
3684
+ return this._isInRange( inst, date );
3685
+ },
3686
+
3687
+ /* Is the given date in the accepted range? */
3688
+ _isInRange: function( inst, date ) {
3689
+ var yearSplit, currentYear,
3690
+ minDate = this._getMinMaxDate( inst, "min" ),
3691
+ maxDate = this._getMinMaxDate( inst, "max" ),
3692
+ minYear = null,
3693
+ maxYear = null,
3694
+ years = this._get( inst, "yearRange" );
3695
+ if ( years ) {
3696
+ yearSplit = years.split( ":" );
3697
+ currentYear = new Date().getFullYear();
3698
+ minYear = parseInt( yearSplit[ 0 ], 10 );
3699
+ maxYear = parseInt( yearSplit[ 1 ], 10 );
3700
+ if ( yearSplit[ 0 ].match( /[+\-].*/ ) ) {
3701
+ minYear += currentYear;
3702
+ }
3703
+ if ( yearSplit[ 1 ].match( /[+\-].*/ ) ) {
3704
+ maxYear += currentYear;
3705
+ }
3706
+ }
3707
+
3708
+ return ( ( !minDate || date.getTime() >= minDate.getTime() ) &&
3709
+ ( !maxDate || date.getTime() <= maxDate.getTime() ) &&
3710
+ ( !minYear || date.getFullYear() >= minYear ) &&
3711
+ ( !maxYear || date.getFullYear() <= maxYear ) );
3712
+ },
3713
+
3714
+ /* Provide the configuration settings for formatting/parsing. */
3715
+ _getFormatConfig: function( inst ) {
3716
+ var shortYearCutoff = this._get( inst, "shortYearCutoff" );
3717
+ shortYearCutoff = ( typeof shortYearCutoff !== "string" ? shortYearCutoff :
3718
+ new Date().getFullYear() % 100 + parseInt( shortYearCutoff, 10 ) );
3719
+ return { shortYearCutoff: shortYearCutoff,
3720
+ dayNamesShort: this._get( inst, "dayNamesShort" ), dayNames: this._get( inst, "dayNames" ),
3721
+ monthNamesShort: this._get( inst, "monthNamesShort" ), monthNames: this._get( inst, "monthNames" ) };
3722
+ },
3723
+
3724
+ /* Format the given date for display. */
3725
+ _formatDate: function( inst, day, month, year ) {
3726
+ if ( !day ) {
3727
+ inst.currentDay = inst.selectedDay;
3728
+ inst.currentMonth = inst.selectedMonth;
3729
+ inst.currentYear = inst.selectedYear;
3730
+ }
3731
+ var date = ( day ? ( typeof day === "object" ? day :
3732
+ this._daylightSavingAdjust( new Date( year, month, day ) ) ) :
3733
+ this._daylightSavingAdjust( new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) );
3734
+ return this.formatDate( this._get( inst, "dateFormat" ), date, this._getFormatConfig( inst ) );
3735
+ }
3736
+} );
3737
+
3738
+/*
3739
+ * Bind hover events for datepicker elements.
3740
+ * Done via delegate so the binding only occurs once in the lifetime of the parent div.
3741
+ * Global datepicker_instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
3742
+ */
3743
+function datepicker_bindHover( dpDiv ) {
3744
+ var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";
3745
+ return dpDiv.on( "mouseout", selector, function() {
3746
+ $( this ).removeClass( "ui-state-hover" );
3747
+ if ( this.className.indexOf( "ui-datepicker-prev" ) !== -1 ) {
3748
+ $( this ).removeClass( "ui-datepicker-prev-hover" );
3749
+ }
3750
+ if ( this.className.indexOf( "ui-datepicker-next" ) !== -1 ) {
3751
+ $( this ).removeClass( "ui-datepicker-next-hover" );
3752
+ }
3753
+ } )
3754
+ .on( "mouseover", selector, datepicker_handleMouseover );
3755
+}
3756
+
3757
+function datepicker_handleMouseover() {
3758
+ if ( !$.datepicker._isDisabledDatepicker( datepicker_instActive.inline ? datepicker_instActive.dpDiv.parent()[ 0 ] : datepicker_instActive.input[ 0 ] ) ) {
3759
+ $( this ).parents( ".ui-datepicker-calendar" ).find( "a" ).removeClass( "ui-state-hover" );
3760
+ $( this ).addClass( "ui-state-hover" );
3761
+ if ( this.className.indexOf( "ui-datepicker-prev" ) !== -1 ) {
3762
+ $( this ).addClass( "ui-datepicker-prev-hover" );
3763
+ }
3764
+ if ( this.className.indexOf( "ui-datepicker-next" ) !== -1 ) {
3765
+ $( this ).addClass( "ui-datepicker-next-hover" );
3766
+ }
3767
+ }
3768
+}
3769
+
3770
+/* jQuery extend now ignores nulls! */
3771
+function datepicker_extendRemove( target, props ) {
3772
+ $.extend( target, props );
3773
+ for ( var name in props ) {
3774
+ if ( props[ name ] == null ) {
3775
+ target[ name ] = props[ name ];
3776
+ }
3777
+ }
3778
+ return target;
3779
+}
3780
+
3781
+/* Invoke the datepicker functionality.
3782
+ @param options string - a command, optionally followed by additional parameters or
3783
+ Object - settings for attaching new datepicker functionality
3784
+ @return jQuery object */
3785
+$.fn.datepicker = function( options ) {
3786
+
3787
+ /* Verify an empty collection wasn't passed - Fixes #6976 */
3788
+ if ( !this.length ) {
3789
+ return this;
3790
+ }
3791
+
3792
+ /* Initialise the date picker. */
3793
+ if ( !$.datepicker.initialized ) {
3794
+ $( document ).on( "mousedown", $.datepicker._checkExternalClick );
3795
+ $.datepicker.initialized = true;
3796
+ }
3797
+
3798
+ /* Append datepicker main container to body if not exist. */
3799
+ if ( $( "#" + $.datepicker._mainDivId ).length === 0 ) {
3800
+ $( "body" ).append( $.datepicker.dpDiv );
3801
+ }
3802
+
3803
+ var otherArgs = Array.prototype.slice.call( arguments, 1 );
3804
+ if ( typeof options === "string" && ( options === "isDisabled" || options === "getDate" || options === "widget" ) ) {
3805
+ return $.datepicker[ "_" + options + "Datepicker" ].
3806
+ apply( $.datepicker, [ this[ 0 ] ].concat( otherArgs ) );
3807
+ }
3808
+ if ( options === "option" && arguments.length === 2 && typeof arguments[ 1 ] === "string" ) {
3809
+ return $.datepicker[ "_" + options + "Datepicker" ].
3810
+ apply( $.datepicker, [ this[ 0 ] ].concat( otherArgs ) );
3811
+ }
3812
+ return this.each( function() {
3813
+ typeof options === "string" ?
3814
+ $.datepicker[ "_" + options + "Datepicker" ].
3815
+ apply( $.datepicker, [ this ].concat( otherArgs ) ) :
3816
+ $.datepicker._attachDatepicker( this, options );
3817
+ } );
3818
+};
3819
+
3820
+$.datepicker = new Datepicker(); // singleton instance
3821
+$.datepicker.initialized = false;
3822
+$.datepicker.uuid = new Date().getTime();
3823
+$.datepicker.version = "1.12.1";
3824
+
3825
+var widgetsDatepicker = $.datepicker;
3826
+
3827
+
3828
+
3829
+
3830
+}));
0
3831
\ No newline at end of file
...
...