PageSourceSearch

https://shoredailynews.com/wp-includes/js/jquery/ui/datepicker.js?ver=1.14.2

js shoredailynews.com collected 2026-10-02 07:51:31 UTC 82,291 bytes, 2,237 lines download raw bytes

vendor: 82,291 bytes, lines 1-2237
1/* eslint-disable max-len */
2/*!
3 * jQuery UI Datepicker 1.14.2
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.14.2" } } );
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		$.datepicker._hideDatepicker();
439		if ( datepicker_instActive === inst ) {
440			datepicker_instActive = null;
441			this._curInst = null;
442		}
443	},
444
445	/* Enable the date picker to a jQuery selection.
446	 * @param  target	element - the target input field or division or span
447	 */
448	_enableDatepicker: function( target ) {
449		var nodeName, inline,
450			$target = $( target ),
451			inst = $.data( target, "datepicker" );
452
453		if ( !$target.hasClass( this.markerClassName ) ) {
454			return;
455		}
456
457		nodeName = target.nodeName.toLowerCase();
458		if ( nodeName === "input" ) {
459			target.disabled = false;
460			inst.trigger.filter( "button" ).
461				each( function() {
462					this.disabled = false;
463				} ).end().
464				filter( "img" ).css( { opacity: "1.0", cursor: "" } );
465		} else if ( nodeName === "div" || nodeName === "span" ) {
466			inline = $target.children( "." + this._inlineClass );
467			inline.children().removeClass( "ui-state-disabled" );
468			inline.find( "select.ui-datepicker-month, select.ui-datepicker-year" ).
469				prop( "disabled", false );
470		}
471		this._disabledInputs = $.map( this._disabledInputs,
472
473			// Delete entry
474			function( value ) {
475				return ( value === target ? null : value );
476			} );
477	},
478
479	/* Disable the date picker to a jQuery selection.
480	 * @param  target	element - the target input field or division or span
481	 */
482	_disableDatepicker: function( target ) {
483		var nodeName, inline,
484			$target = $( target ),
485			inst = $.data( target, "datepicker" );
486
487		if ( !$target.hasClass( this.markerClassName ) ) {
488			return;
489		}
490
491		nodeName = target.nodeName.toLowerCase();
492		if ( nodeName === "input" ) {
493			target.disabled = true;
494			inst.trigger.filter( "button" ).
495				each( function() {
496					this.disabled = true;
497				} ).end().
498				filter( "img" ).css( { opacity: "0.5", cursor: "default" } );
499		} else if ( nodeName === "div" || nodeName === "span" ) {
500			inline = $target.children( "." + this._inlineClass );
501			inline.children().addClass( "ui-state-disabled" );
502			inline.find( "select.ui-datepicker-month, select.ui-datepicker-year" ).
503				prop( "disabled", true );
504		}
505		this._disabledInputs = $.map( this._disabledInputs,
506
507			// Delete entry
508			function( value ) {
509				return ( value === target ? null : value );
510			} );
511		this._disabledInputs[ this._disabledInputs.length ] = target;
512	},
513
514	/* Is the first field in a jQuery collection disabled as a datepicker?
515	 * @param  target	element - the target input field or division or span
516	 * @return boolean - true if disabled, false if enabled
517	 */
518	_isDisabledDatepicker: function( target ) {
519		if ( !target ) {
520			return false;
521		}
522		for ( var i = 0; i < this._disabledInputs.length; i++ ) {
523			if ( this._disabledInputs[ i ] === target ) {
524				return true;
525			}
526		}
527		return false;
528	},
529
530	/* Retrieve the instance data for the target control.
531	 * @param  target  element - the target input field or division or span
532	 * @return  object - the associated instance data
533	 * @throws  error if a jQuery problem getting data
534	 */
535	_getInst: function( target ) {
536		try {
537			return $.data( target, "datepicker" );
538		} catch ( _err ) {
539			throw "Missing instance data for this datepicker";
540		}
541	},
542
543	/* Update or retrieve the settings for a date picker attached to an input field or division.
544	 * @param  target  element - the target input field or division or span
545	 * @param  name	object - the new settings to update or
546	 *				string - the name of the setting to change or retrieve,
547	 *				when retrieving also "all" for all instance settings or
548	 *				"defaults" for all global defaults
549	 * @param  value   any - the new value for the setting
550	 *				(omit if above is an object or to retrieve a value)
551	 */
552	_optionDatepicker: function( target, name, value ) {
553		var settings, date, minDate, maxDate,
554			inst = this._getInst( target );
555
556		if ( arguments.length === 2 && typeof name === "string" ) {
557			return ( name === "defaults" ? $.extend( {}, $.datepicker._defaults ) :
558				( inst ? ( name === "all" ? $.extend( {}, inst.settings ) :
559				this._get( inst, name ) ) : null ) );
560		}
561
562		settings = name || {};
563		if ( typeof name === "string" ) {
564			settings = {};
565			settings[ name ] = value;
566		}
567
568		if ( inst ) {
569			if ( this._curInst === inst ) {
570				this._hideDatepicker();
571			}
572
573			date = this._getDateDatepicker( target, true );
574			minDate = this._getMinMaxDate( inst, "min" );
575			maxDate = this._getMinMaxDate( inst, "max" );
576			datepicker_extendRemove( inst.settings, settings );
577
578			// reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
579			if ( minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined ) {
580				inst.settings.minDate = this._formatDate( inst, minDate );
581			}
582			if ( maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined ) {
583				inst.settings.maxDate = this._formatDate( inst, maxDate );
584			}
585			if ( "disabled" in settings ) {
586				if ( settings.disabled ) {
587					this._disableDatepicker( target );
588				} else {
589					this._enableDatepicker( target );
590				}
591			}
592			this._attachments( $( target ), inst );
593			this._autoSize( inst );
594			this._setDate( inst, date );
595			this._updateAlternate( inst );
596			this._updateDatepicker( inst );
597		}
598	},
599
600	// Change method deprecated
601	_changeDatepicker: function( target, name, value ) {
602		this._optionDatepicker( target, name, value );
603	},
604
605	/* Redraw the date picker attached to an input field or division.
606	 * @param  target  element - the target input field or division or span
607	 */
608	_refreshDatepicker: function( target ) {
609		var inst = this._getInst( target );
610		if ( inst ) {
611			this._updateDatepicker( inst );
612		}
613	},
614
615	/* Set the dates for a jQuery selection.
616	 * @param  target element - the target input field or division or span
617	 * @param  date	Date - the new date
618	 */
619	_setDateDatepicker: function( target, date ) {
620		var inst = this._getInst( target );
621		if ( inst ) {
622			this._setDate( inst, date );
623			this._updateDatepicker( inst );
624			this._updateAlternate( inst );
625		}
626	},
627
628	/* Get the date(s) for the first entry in a jQuery selection.
629	 * @param  target element - the target input field or division or span
630	 * @param  noDefault boolean - true if no default date is to be used
631	 * @return Date - the current date
632	 */
633	_getDateDatepicker: function( target, noDefault ) {
634		var inst = this._getInst( target );
635		if ( inst && !inst.inline ) {
636			this._setDateFromField( inst, noDefault );
637		}
638		return ( inst ? this._getDate( inst ) : null );
639	},
640
641	/* Handle keystrokes. */
642	_doKeyDown: function( event ) {
643		var onSelect, dateStr, sel,
644			inst = $.datepicker._getInst( event.target ),
645			handled = true,
646			isRTL = inst.dpDiv.is( ".ui-datepicker-rtl" );
647
648		inst._keyEvent = true;
649		if ( $.datepicker._datepickerShowing ) {
650			switch ( event.keyCode ) {
651				case 9: $.datepicker._hideDatepicker();
652						handled = false;
653						break; // hide on tab out
654				case 13: sel = $( "td." + $.datepicker._dayOverClass + ":not(." +
655									$.datepicker._currentClass + ")", inst.dpDiv );
656						if ( sel[ 0 ] ) {
657							$.datepicker._selectDay( event.target, inst.selectedMonth, inst.selectedYear, sel[ 0 ] );
658						}
659
660						onSelect = $.datepicker._get( inst, "onSelect" );
661						if ( onSelect ) {
662							dateStr = $.datepicker._formatDate( inst );
663
664							// Trigger custom callback
665							onSelect.apply( ( inst.input ? inst.input[ 0 ] : null ), [ dateStr, inst ] );
666						} else {
667							$.datepicker._hideDatepicker();
668						}
669
670						return false; // don't submit the form
671				case 27: $.datepicker._hideDatepicker();
672						break; // hide on escape
673				case 33: $.datepicker._adjustDate( event.target, ( event.ctrlKey ?
674							-$.datepicker._get( inst, "stepBigMonths" ) :
675							-$.datepicker._get( inst, "stepMonths" ) ), "M" );
676						break; // previous month/year on page up/+ ctrl
677				case 34: $.datepicker._adjustDate( event.target, ( event.ctrlKey ?
678							+$.datepicker._get( inst, "stepBigMonths" ) :
679							+$.datepicker._get( inst, "stepMonths" ) ), "M" );
680						break; // next month/year on page down/+ ctrl
681				case 35: if ( event.ctrlKey || event.metaKey ) {
682							$.datepicker._clearDate( event.target );
683						}
684						handled = event.ctrlKey || event.metaKey;
685						break; // clear on ctrl or command +end
686				case 36: if ( event.ctrlKey || event.metaKey ) {
687							$.datepicker._gotoToday( event.target );
688						}
689						handled = event.ctrlKey || event.metaKey;
690						break; // current on ctrl or command +home
691				case 37: if ( event.ctrlKey || event.metaKey ) {
692							$.datepicker._adjustDate( event.target, ( isRTL ? +1 : -1 ), "D" );
693						}
694						handled = event.ctrlKey || event.metaKey;
695
696						// -1 day on ctrl or command +left
697						if ( event.originalEvent.altKey ) {
698							$.datepicker._adjustDate( event.target, ( event.ctrlKey ?
699								-$.datepicker._get( inst, "stepBigMonths" ) :
700								-$.datepicker._get( inst, "stepMonths" ) ), "M" );
701						}
702
703						// next month/year on alt +left on Mac
704						break;
705				case 38: if ( event.ctrlKey || event.metaKey ) {
706							$.datepicker._adjustDate( event.target, -7, "D" );
707						}
708						handled = event.ctrlKey || event.metaKey;
709						break; // -1 week on ctrl or command +up
710				case 39: if ( event.ctrlKey || event.metaKey ) {
711							$.datepicker._adjustDate( event.target, ( isRTL ? -1 : +1 ), "D" );
712						}
713						handled = event.ctrlKey || event.metaKey;
714
715						// +1 day on ctrl or command +right
716						if ( event.originalEvent.altKey ) {
717							$.datepicker._adjustDate( event.target, ( event.ctrlKey ?
718								+$.datepicker._get( inst, "stepBigMonths" ) :
719								+$.datepicker._get( inst, "stepMonths" ) ), "M" );
720						}
721
722						// next month/year on alt +right
723						break;
724				case 40: if ( event.ctrlKey || event.metaKey ) {
725							$.datepicker._adjustDate( event.target, +7, "D" );
726						}
727						handled = event.ctrlKey || event.metaKey;
728						break; // +1 week on ctrl or command +down
729				default: handled = false;
730			}
731		} else if ( event.keyCode === 36 && event.ctrlKey ) { // display the date picker on ctrl+home
732			$.datepicker._showDatepicker( this );
733		} else {
734			handled = false;
735		}
736
737		if ( handled ) {
738			event.preventDefault();
739			event.stopPropagation();
740		}
741	},
742
743	/* Filter entered characters - based on date format. */
744	_doKeyPress: function( event ) {
745		var chars, chr,
746			inst = $.datepicker._getInst( event.target );
747
748		if ( $.datepicker._get( inst, "constrainInput" ) ) {
749			chars = $.datepicker._possibleChars( $.datepicker._get( inst, "dateFormat" ) );
750			chr = String.fromCharCode( event.charCode == null ? event.keyCode : event.charCode );
751			return event.ctrlKey || event.metaKey || ( chr < " " || !chars || chars.indexOf( chr ) > -1 );
752		}
753	},
754
755	/* Synchronise manual entry and field/alternate field. */
756	_doKeyUp: function( event ) {
757		var date,
758			inst = $.datepicker._getInst( event.target );
759
760		if ( inst.input.val() !== inst.lastVal ) {
761			try {
762				date = $.datepicker.parseDate( $.datepicker._get( inst, "dateFormat" ),
763					( inst.input ? inst.input.val() : null ),
764					$.datepicker._getFormatConfig( inst ) );
765
766				if ( date ) { // only if valid
767					$.datepicker._setDateFromField( inst );
768					$.datepicker._updateAlternate( inst );
769					$.datepicker._updateDatepicker( inst );
770				}
771			} catch ( _err ) {
772			}
773		}
774		return true;
775	},
776
777	/* Pop-up the date picker for a given input field.
778	 * If false returned from beforeShow event handler do not show.
779	 * @param  input  element - the input field attached to the date picker or
780	 *					event - if triggered by focus
781	 */
782	_showDatepicker: function( input ) {
783		input = input.target || input;
784		if ( input.nodeName.toLowerCase() !== "input" ) { // find from button/image trigger
785			input = $( "input", input.parentNode )[ 0 ];
786		}
787
788		if ( $.datepicker._isDisabledDatepicker( input ) || $.datepicker._lastInput === input ) { // already here
789			return;
790		}
791
792		var inst, beforeShow, beforeShowSettings, isFixed,
793			offset, showAnim, duration;
794
795		inst = $.datepicker._getInst( input );
796		if ( $.datepicker._curInst && $.datepicker._curInst !== inst ) {
797			$.datepicker._curInst.dpDiv.stop( true, true );
798			if ( inst && $.datepicker._datepickerShowing ) {
799				$.datepicker._hideDatepicker( $.datepicker._curInst.input[ 0 ] );
800			}
801		}
802
803		beforeShow = $.datepicker._get( inst, "beforeShow" );
804		beforeShowSettings = beforeShow ? beforeShow.apply( input, [ input, inst ] ) : {};
805		if ( beforeShowSettings === false ) {
806			return;
807		}
808		datepicker_extendRemove( inst.settings, beforeShowSettings );
809
810		inst.lastVal = null;
811		$.datepicker._lastInput = input;
812		$.datepicker._setDateFromField( inst );
813
814		if ( $.datepicker._inDialog ) { // hide cursor
815			input.value = "";
816		}
817		if ( !$.datepicker._pos ) { // position below input
818			$.datepicker._pos = $.datepicker._findPos( input );
819			$.datepicker._pos[ 1 ] += input.offsetHeight; // add the height
820		}
821
822		isFixed = false;
823		$( input ).parents().each( function() {
824			isFixed |= $( this ).css( "position" ) === "fixed";
825			return !isFixed;
826		} );
827
828		offset = { left: $.datepicker._pos[ 0 ], top: $.datepicker._pos[ 1 ] };
829		$.datepicker._pos = null;
830
831		//to avoid flashes on Firefox
832		inst.dpDiv.empty();
833
834		// determine sizing offscreen
835		inst.dpDiv.css( { position: "absolute", display: "block", top: "-1000px" } );
836		$.datepicker._updateDatepicker( inst );
837
838		// fix width for dynamic number of date pickers
839		// and adjust position before showing
840		offset = $.datepicker._checkOffset( inst, offset, isFixed );
841		inst.dpDiv.css( { position: ( $.datepicker._inDialog && $.blockUI ?
842			"static" : ( isFixed ? "fixed" : "absolute" ) ), display: "none",
843			left: offset.left + "px", top: offset.top + "px" } );
844
845		if ( !inst.inline ) {
846			showAnim = $.datepicker._get( inst, "showAnim" );
847			duration = $.datepicker._get( inst, "duration" );
848			inst.dpDiv.css( "z-index", datepicker_getZindex( $( input ) ) + 1 );
849			$.datepicker._datepickerShowing = true;
850
851			if ( $.effects && $.effects.effect[ showAnim ] ) {
852				inst.dpDiv.show( showAnim, $.datepicker._get( inst, "showOptions" ), duration );
853			} else {
854				inst.dpDiv[ showAnim || "show" ]( showAnim ? duration : null );
855			}
856
857			if ( $.datepicker._shouldFocusInput( inst ) ) {
858				inst.input.trigger( "focus" );
859			}
860
861			$.datepicker._curInst = inst;
862		}
863	},
864
865	/* Generate the date picker content. */
866	_updateDatepicker: function( inst ) {
867		this.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
868		datepicker_instActive = inst; // for delegate hover events
869		inst.dpDiv.empty().append( this._generateHTML( inst ) );
870		this._attachHandlers( inst );
871
872		var origyearshtml,
873			numMonths = this._getNumberOfMonths( inst ),
874			cols = numMonths[ 1 ],
875			width = 17,
876			activeCell = inst.dpDiv.find( "." + this._dayOverClass + " a" ),
877			onUpdateDatepicker = $.datepicker._get( inst, "onUpdateDatepicker" );
878
879		if ( activeCell.length > 0 ) {
880			datepicker_handleMouseover.apply( activeCell.get( 0 ) );
881		}
882
883		inst.dpDiv.removeClass( "ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4" ).width( "" );
884		if ( cols > 1 ) {
885			inst.dpDiv.addClass( "ui-datepicker-multi-" + cols ).css( "width", ( width * cols ) + "em" );
886		}
887		inst.dpDiv[ ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ? "add" : "remove" ) +
888			"Class" ]( "ui-datepicker-multi" );
889		inst.dpDiv[ ( this._get( inst, "isRTL" ) ? "add" : "remove" ) +
890			"Class" ]( "ui-datepicker-rtl" );
891
892		if ( inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) {
893			inst.input.trigger( "focus" );
894		}
895
896		// Deffered render of the years select (to avoid flashes on Firefox)
897		if ( inst.yearshtml ) {
898			origyearshtml = inst.yearshtml;
899			setTimeout( function() {
900
901				//assure that inst.yearshtml didn't change.
902				if ( origyearshtml === inst.yearshtml && inst.yearshtml ) {
903					inst.dpDiv.find( "select.ui-datepicker-year" ).first().replaceWith( inst.yearshtml );
904				}
905				origyearshtml = inst.yearshtml = null;
906			}, 0 );
907		}
908
909		if ( onUpdateDatepicker ) {
910			onUpdateDatepicker.apply( ( inst.input ? inst.input[ 0 ] : null ), [ inst ] );
911		}
912	},
913
914	_shouldFocusInput: function( inst ) {
915		return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" );
916	},
917
918	/* Check positioning to remain on screen. */
919	_checkOffset: function( inst, offset, isFixed ) {
920		var dpWidth = inst.dpDiv.outerWidth(),
921			dpHeight = inst.dpDiv.outerHeight(),
922			inputWidth = inst.input ? inst.input.outerWidth() : 0,
923			inputHeight = inst.input ? inst.input.outerHeight() : 0,
924			viewWidth = document.documentElement.clientWidth + ( isFixed ? 0 : $( document ).scrollLeft() ),
925			viewHeight = document.documentElement.clientHeight + ( isFixed ? 0 : $( document ).scrollTop() );
926
927		offset.left -= ( this._get( inst, "isRTL" ) ? ( dpWidth - inputWidth ) : 0 );
928		offset.left -= ( isFixed && offset.left === inst.input.offset().left ) ? $( document ).scrollLeft() : 0;
929		offset.top -= ( isFixed && offset.top === ( inst.input.offset().top + inputHeight ) ) ? $( document ).scrollTop() : 0;
930
931		// Now check if datepicker is showing outside window viewport - move to a better place if so.
932		offset.left -= Math.min( offset.left, ( offset.left + dpWidth > viewWidth && viewWidth > dpWidth ) ?
933			Math.abs( offset.left + dpWidth - viewWidth ) : 0 );
934		offset.top -= Math.min( offset.top, ( offset.top + dpHeight > viewHeight && viewHeight > dpHeight ) ?
935			Math.abs( dpHeight + inputHeight ) : 0 );
936
937		return offset;
938	},
939
940	/* Find an object's position on the screen. */
941	_findPos: function( obj ) {
942		var position,
943			inst = this._getInst( obj ),
944			isRTL = this._get( inst, "isRTL" );
945
946		while ( obj && ( obj.type === "hidden" || obj.nodeType !== 1 || $.expr.pseudos.hidden( obj ) ) ) {
947			obj = obj[ isRTL ? "previousSibling" : "nextSibling" ];
948		}
949
950		position = $( obj ).offset();
951		return [ position.left, position.top ];
952	},
953
954	/* Hide the date picker from view.
955	 * @param  input  element - the input field attached to the date picker
956	 */
957	_hideDatepicker: function( input ) {
958		var showAnim, duration, postProcess, onClose,
959			inst = this._curInst;
960
961		if ( !inst || ( input && inst !== $.data( input, "datepicker" ) ) ) {
962			return;
963		}
964
965		if ( this._datepickerShowing ) {
966			showAnim = this._get( inst, "showAnim" );
967			duration = this._get( inst, "duration" );
968			postProcess = function() {
969				$.datepicker._tidyDialog( inst );
970			};
971
972			if ( $.effects && ( $.effects.effect[ showAnim ] ) ) {
973				inst.dpDiv.hide( showAnim, $.datepicker._get( inst, "showOptions" ), duration, postProcess );
974			} else {
975				inst.dpDiv[ ( showAnim === "slideDown" ? "slideUp" :
976					( showAnim === "fadeIn" ? "fadeOut" : "hide" ) ) ]( ( showAnim ? duration : null ), postProcess );
977			}
978
979			if ( !showAnim ) {
980				postProcess();
981			}
982			this._datepickerShowing = false;
983
984			onClose = this._get( inst, "onClose" );
985			if ( onClose ) {
986				onClose.apply( ( inst.input ? inst.input[ 0 ] : null ), [ ( inst.input ? inst.input.val() : "" ), inst ] );
987			}
988
989			this._lastInput = null;
990			if ( this._inDialog ) {
991				this._dialogInput.css( { position: "absolute", left: "0", top: "-100px" } );
992				if ( $.blockUI ) {
993					$.unblockUI();
994					$( "body" ).append( this.dpDiv );
995				}
996			}
997			this._inDialog = false;
998		}
999	},
1000
1001	/* Tidy up after a dialog display. */
1002	_tidyDialog: function( inst ) {
1003		inst.dpDiv.removeClass( this._dialogClass ).off( ".ui-datepicker-calendar" );
1004	},
1005
1006	/* Close date picker if clicked elsewhere. */
1007	_checkExternalClick: function( event ) {
1008		if ( !$.datepicker._curInst ) {
1009			return;
1010		}
1011
1012		var $target = $( event.target ),
1013			inst = $.datepicker._getInst( $target[ 0 ] );
1014
1015		if ( ( ( $target[ 0 ].id !== $.datepicker._mainDivId &&
1016				$target.parents( "#" + $.datepicker._mainDivId ).length === 0 &&
1017				!$target.hasClass( $.datepicker.markerClassName ) &&
1018				!$target.closest( "." + $.datepicker._triggerClass ).length &&
1019				$.datepicker._datepickerShowing && !( $.datepicker._inDialog && $.blockUI ) ) ) ||
1020			( $target.hasClass( $.datepicker.markerClassName ) && $.datepicker._curInst !== inst ) ) {
1021				$.datepicker._hideDatepicker();
1022		}
1023	},
1024
1025	/* Adjust one of the date sub-fields. */
1026	_adjustDate: function( id, offset, period ) {
1027		var target = $( id ),
1028			inst = this._getInst( target[ 0 ] );
1029
1030		if ( this._isDisabledDatepicker( target[ 0 ] ) ) {
1031			return;
1032		}
1033		this._adjustInstDate( inst, offset, period );
1034		this._updateDatepicker( inst );
1035	},
1036
1037	/* Action for current link. */
1038	_gotoToday: function( id ) {
1039		var date,
1040			target = $( id ),
1041			inst = this._getInst( target[ 0 ] );
1042
1043		if ( this._get( inst, "gotoCurrent" ) && inst.currentDay ) {
1044			inst.selectedDay = inst.currentDay;
1045			inst.drawMonth = inst.selectedMonth = inst.currentMonth;
1046			inst.drawYear = inst.selectedYear = inst.currentYear;
1047		} else {
1048			date = new Date();
1049			inst.selectedDay = date.getDate();
1050			inst.drawMonth = inst.selectedMonth = date.getMonth();
1051			inst.drawYear = inst.selectedYear = date.getFullYear();
1052		}
1053		this._notifyChange( inst );
1054		this._adjustDate( target );
1055	},
1056
1057	/* Action for selecting a new month/year. */
1058	_selectMonthYear: function( id, select, period ) {
1059		var target = $( id ),
1060			inst = this._getInst( target[ 0 ] );
1061
1062		inst[ "selected" + ( period === "M" ? "Month" : "Year" ) ] =
1063		inst[ "draw" + ( period === "M" ? "Month" : "Year" ) ] =
1064			parseInt( select.options[ select.selectedIndex ].value, 10 );
1065
1066		this._notifyChange( inst );
1067		this._adjustDate( target );
1068	},
1069
1070	/* Action for selecting a day. */
1071	_selectDay: function( id, month, year, td ) {
1072		var inst,
1073			target = $( id );
1074
1075		if ( $( td ).hasClass( this._unselectableClass ) || this._isDisabledDatepicker( target[ 0 ] ) ) {
1076			return;
1077		}
1078
1079		inst = this._getInst( target[ 0 ] );
1080		inst.selectedDay = inst.currentDay = parseInt( $( "a", td ).attr( "data-date" ) );
1081		inst.selectedMonth = inst.currentMonth = month;
1082		inst.selectedYear = inst.currentYear = year;
1083		this._selectDate( id, this._formatDate( inst,
1084			inst.currentDay, inst.currentMonth, inst.currentYear ) );
1085	},
1086
1087	/* Erase the input field and hide the date picker. */
1088	_clearDate: function( id ) {
1089		var target = $( id );
1090		this._selectDate( target, "" );
1091	},
1092
1093	/* Update the input field with the selected date. */
1094	_selectDate: function( id, dateStr ) {
1095		var onSelect,
1096			target = $( id ),
1097			inst = this._getInst( target[ 0 ] );
1098
1099		dateStr = ( dateStr != null ? dateStr : this._formatDate( inst ) );
1100		if ( inst.input ) {
1101			inst.input.val( dateStr );
1102		}
1103		this._updateAlternate( inst );
1104
1105		onSelect = this._get( inst, "onSelect" );
1106		if ( onSelect ) {
1107			onSelect.apply( ( inst.input ? inst.input[ 0 ] : null ), [ dateStr, inst ] );  // trigger custom callback
1108		} else if ( inst.input ) {
1109			inst.input.trigger( "change" ); // fire the change event
1110		}
1111
1112		if ( inst.inline ) {
1113			this._updateDatepicker( inst );
1114		} else {
1115			this._hideDatepicker();
1116			this._lastInput = inst.input[ 0 ];
1117			if ( typeof( inst.input[ 0 ] ) !== "object" ) {
1118				inst.input.trigger( "focus" ); // restore focus
1119			}
1120			this._lastInput = null;
1121		}
1122	},
1123
1124	/* Update any alternate field to synchronise with the main field. */
1125	_updateAlternate: function( inst ) {
1126		var altFormat, date, dateStr,
1127			altField = this._get( inst, "altField" );
1128
1129		if ( altField ) { // update alternate field too
1130			altFormat = this._get( inst, "altFormat" ) || this._get( inst, "dateFormat" );
1131			date = this._getDate( inst );
1132			dateStr = this.formatDate( altFormat, date, this._getFormatConfig( inst ) );
1133			$( document ).find( altField ).val( dateStr );
1134		}
1135	},
1136
1137	/* Set as beforeShowDay function to prevent selection of weekends.
1138	 * @param  date  Date - the date to customise
1139	 * @return [boolean, string] - is this date selectable?, what is its CSS class?
1140	 */
1141	noWeekends: function( date ) {
1142		var day = date.getDay();
1143		return [ ( day > 0 && day < 6 ), "" ];
1144	},
1145
1146	/* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
1147	 * @param  date  Date - the date to get the week for
1148	 * @return  number - the number of the week within the year that contains this date
1149	 */
1150	iso8601Week: function( date ) {
1151		var time,
1152			checkDate = new Date( date.getTime() );
1153
1154		// Find Thursday of this week starting on Monday
1155		checkDate.setDate( checkDate.getDate() + 4 - ( checkDate.getDay() || 7 ) );
1156
1157		time = checkDate.getTime();
1158		checkDate.setMonth( 0 ); // Compare with Jan 1
1159		checkDate.setDate( 1 );
1160		return Math.floor( Math.round( ( time - checkDate ) / 86400000 ) / 7 ) + 1;
1161	},
1162
1163	/* Parse a string value into a date object.
1164	 * See formatDate below for the possible formats.
1165	 *
1166	 * @param  format string - the expected format of the date
1167	 * @param  value string - the date in the above format
1168	 * @param  settings Object - attributes include:
1169	 *					shortYearCutoff  number - the cutoff year for determining the century (optional)
1170	 *					dayNamesShort	string[7] - abbreviated names of the days from Sunday (optional)
1171	 *					dayNames		string[7] - names of the days from Sunday (optional)
1172	 *					monthNamesShort string[12] - abbreviated names of the months (optional)
1173	 *					monthNames		string[12] - names of the months (optional)
1174	 * @return  Date - the extracted date value or null if value is blank
1175	 */
1176	parseDate: function( format, value, settings ) {
1177		if ( format == null || value == null ) {
1178			throw "Invalid arguments";
1179		}
1180
1181		value = ( typeof value === "object" ? value.toString() : value + "" );
1182		if ( value === "" ) {
1183			return null;
1184		}
1185
1186		var iFormat, dim, extra,
1187			iValue = 0,
1188			shortYearCutoffTemp = ( settings ? settings.shortYearCutoff : null ) || this._defaults.shortYearCutoff,
1189			shortYearCutoff = ( typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp :
1190				new Date().getFullYear() % 100 + parseInt( shortYearCutoffTemp, 10 ) ),
1191			dayNamesShort = ( settings ? settings.dayNamesShort : null ) || this._defaults.dayNamesShort,
1192			dayNames = ( settings ? settings.dayNames : null ) || this._defaults.dayNames,
1193			monthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort,
1194			monthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames,
1195			year = -1,
1196			month = -1,
1197			day = -1,
1198			doy = -1,
1199			literal = false,
1200			date,
1201
1202			// Check whether a format character is doubled
1203			lookAhead = function( match ) {
1204				var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );
1205				if ( matches ) {
1206					iFormat++;
1207				}
1208				return matches;
1209			},
1210
1211			// Extract a number from the string value
1212			getNumber = function( match ) {
1213				var isDoubled = lookAhead( match ),
1214					size = ( match === "@" ? 14 : ( match === "!" ? 20 :
1215					( match === "y" && isDoubled ? 4 : ( match === "o" ? 3 : 2 ) ) ) ),
1216					minSize = ( match === "y" ? size : 1 ),
1217					digits = new RegExp( "^\\d{" + minSize + "," + size + "}" ),
1218					num = value.substring( iValue ).match( digits );
1219				if ( !num ) {
1220					throw "Missing number at position " + iValue;
1221				}
1222				iValue += num[ 0 ].length;
1223				return parseInt( num[ 0 ], 10 );
1224			},
1225
1226			// Extract a name from the string value and convert to an index
1227			getName = function( match, shortNames, longNames ) {
1228				var index = -1,
1229					names = $.map( lookAhead( match ) ? longNames : shortNames, function( v, k ) {
1230						return [ [ k, v ] ];
1231					} ).sort( function( a, b ) {
1232						return -( a[ 1 ].length - b[ 1 ].length );
1233					} );
1234
1235				$.each( names, function( i, pair ) {
1236					var name = pair[ 1 ];
1237					if ( value.substr( iValue, name.length ).toLowerCase() === name.toLowerCase() ) {
1238						index = pair[ 0 ];
1239						iValue += name.length;
1240						return false;
1241					}
1242				} );
1243				if ( index !== -1 ) {
1244					return index + 1;
1245				} else {
1246					throw "Unknown name at position " + iValue;
1247				}
1248			},
1249
1250			// Confirm that a literal character matches the string value
1251			checkLiteral = function() {
1252				if ( value.charAt( iValue ) !== format.charAt( iFormat ) ) {
1253					throw "Unexpected literal at position " + iValue;
1254				}
1255				iValue++;
1256			};
1257
1258		for ( iFormat = 0; iFormat < format.length; iFormat++ ) {
1259			if ( literal ) {
1260				if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) {
1261					literal = false;
1262				} else {
1263					checkLiteral();
1264				}
1265			} else {
1266				switch ( format.charAt( iFormat ) ) {
1267					case "d":
1268						day = getNumber( "d" );
1269						break;
1270					case "D":
1271						getName( "D", dayNamesShort, dayNames );
1272						break;
1273					case "o":
1274						doy = getNumber( "o" );
1275						break;
1276					case "m":
1277						month = getNumber( "m" );
1278						break;
1279					case "M":
1280						month = getName( "M", monthNamesShort, monthNames );
1281						break;
1282					case "y":
1283						year = getNumber( "y" );
1284						break;
1285					case "@":
1286						date = new Date( getNumber( "@" ) );
1287						year = date.getFullYear();
1288						month = date.getMonth() + 1;
1289						day = date.getDate();
1290						break;
1291					case "!":
1292						date = new Date( ( getNumber( "!" ) - this._ticksTo1970 ) / 10000 );
1293						year = date.getFullYear();
1294						month = date.getMonth() + 1;
1295						day = date.getDate();
1296						break;
1297					case "'":
1298						if ( lookAhead( "'" ) ) {
1299							checkLiteral();
1300						} else {
1301							literal = true;
1302						}
1303						break;
1304					default:
1305						checkLiteral();
1306				}
1307			}
1308		}
1309
1310		if ( iValue < value.length ) {
1311			extra = value.substr( iValue );
1312			if ( !/^\s+/.test( extra ) ) {
1313				throw "Extra/unparsed characters found in date: " + extra;
1314			}
1315		}
1316
1317		if ( year === -1 ) {
1318			year = new Date().getFullYear();
1319		} else if ( year < 100 ) {
1320			year += new Date().getFullYear() - new Date().getFullYear() % 100 +
1321				( year <= shortYearCutoff ? 0 : -100 );
1322		}
1323
1324		if ( doy > -1 ) {
1325			month = 1;
1326			day = doy;
1327			do {
1328				dim = this._getDaysInMonth( year, month - 1 );
1329				if ( day <= dim ) {
1330					break;
1331				}
1332				month++;
1333				day -= dim;
1334			} while ( true );
1335		}
1336
1337		date = this._daylightSavingAdjust( new Date( year, month - 1, day ) );
1338		if ( date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day ) {
1339			throw "Invalid date"; // E.g. 31/02/00
1340		}
1341		return date;
1342	},
1343
1344	/* Standard date formats. */
1345	ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601)
1346	COOKIE: "D, dd M yy",
1347	ISO_8601: "yy-mm-dd",
1348	RFC_822: "D, d M y",
1349	RFC_850: "DD, dd-M-y",
1350	RFC_1036: "D, d M y",
1351	RFC_1123: "D, d M yy",
1352	RFC_2822: "D, d M yy",
1353	RSS: "D, d M y", // RFC 822
1354	TICKS: "!",
1355	TIMESTAMP: "@",
1356	W3C: "yy-mm-dd", // ISO 8601
1357
1358	_ticksTo1970: ( ( ( 1970 - 1 ) * 365 + Math.floor( 1970 / 4 ) - Math.floor( 1970 / 100 ) +
1359		Math.floor( 1970 / 400 ) ) * 24 * 60 * 60 * 10000000 ),
1360
1361	/* Format a date object into a string value.
1362	 * The format can be combinations of the following:
1363	 * d  - day of month (no leading zero)
1364	 * dd - day of month (two digit)
1365	 * o  - day of year (no leading zeros)
1366	 * oo - day of year (three digit)
1367	 * D  - day name short
1368	 * DD - day name long
1369	 * m  - month of year (no leading zero)
1370	 * mm - month of year (two digit)
1371	 * M  - month name short
1372	 * MM - month name long
1373	 * y  - year (two digit)
1374	 * yy - year (four digit)
1375	 * @ - Unix timestamp (ms since 01/01/1970)
1376	 * ! - Windows ticks (100ns since 01/01/0001)
1377	 * "..." - literal text
1378	 * '' - single quote
1379	 *
1380	 * @param  format string - the desired format of the date
1381	 * @param  date Date - the date value to format
1382	 * @param  settings Object - attributes include:
1383	 *					dayNamesShort	string[7] - abbreviated names of the days from Sunday (optional)
1384	 *					dayNames		string[7] - names of the days from Sunday (optional)
1385	 *					monthNamesShort string[12] - abbreviated names of the months (optional)
1386	 *					monthNames		string[12] - names of the months (optional)
1387	 * @return  string - the date in the above format
1388	 */
1389	formatDate: function( format, date, settings ) {
1390		if ( !date ) {
1391			return "";
1392		}
1393
1394		var iFormat,
1395			dayNamesShort = ( settings ? settings.dayNamesShort : null ) || this._defaults.dayNamesShort,
1396			dayNames = ( settings ? settings.dayNames : null ) || this._defaults.dayNames,
1397			monthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort,
1398			monthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames,
1399
1400			// Check whether a format character is doubled
1401			lookAhead = function( match ) {
1402				var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );
1403				if ( matches ) {
1404					iFormat++;
1405				}
1406				return matches;
1407			},
1408
1409			// Format a number, with leading zero if necessary
1410			formatNumber = function( match, value, len ) {
1411				var num = "" + value;
1412				if ( lookAhead( match ) ) {
1413					while ( num.length < len ) {
1414						num = "0" + num;
1415					}
1416				}
1417				return num;
1418			},
1419
1420			// Format a name, short or long as requested
1421			formatName = function( match, value, shortNames, longNames ) {
1422				return ( lookAhead( match ) ? longNames[ value ] : shortNames[ value ] );
1423			},
1424			output = "",
1425			literal = false;
1426
1427		if ( date ) {
1428			for ( iFormat = 0; iFormat < format.length; iFormat++ ) {
1429				if ( literal ) {
1430					if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) {
1431						literal = false;
1432					} else {
1433						output += format.charAt( iFormat );
1434					}
1435				} else {
1436					switch ( format.charAt( iFormat ) ) {
1437						case "d":
1438							output += formatNumber( "d", date.getDate(), 2 );
1439							break;
1440						case "D":
1441							output += formatName( "D", date.getDay(), dayNamesShort, dayNames );
1442							break;
1443						case "o":
1444							output += formatNumber( "o",
1445								Math.round( ( new Date( date.getFullYear(), date.getMonth(), date.getDate() ).getTime() - new Date( date.getFullYear(), 0, 0 ).getTime() ) / 86400000 ), 3 );
1446							break;
1447						case "m":
1448							output += formatNumber( "m", date.getMonth() + 1, 2 );
1449							break;
1450						case "M":
1451							output += formatName( "M", date.getMonth(), monthNamesShort, monthNames );
1452							break;
1453						case "y":
1454							output += ( lookAhead( "y" ) ? date.getFullYear() :
1455								( date.getFullYear() % 100 < 10 ? "0" : "" ) + date.getFullYear() % 100 );
1456							break;
1457						case "@":
1458							output += date.getTime();
1459							break;
1460						case "!":
1461							output += date.getTime() * 10000 + this._ticksTo1970;
1462							break;
1463						case "'":
1464							if ( lookAhead( "'" ) ) {
1465								output += "'";
1466							} else {
1467								literal = true;
1468							}
1469							break;
1470						default:
1471							output += format.charAt( iFormat );
1472					}
1473				}
1474			}
1475		}
1476		return output;
1477	},
1478
1479	/* Extract all possible characters from the date format. */
1480	_possibleChars: function( format ) {
1481		var iFormat,
1482			chars = "",
1483			literal = false,
1484
1485			// Check whether a format character is doubled
1486			lookAhead = function( match ) {
1487				var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );
1488				if ( matches ) {
1489					iFormat++;
1490				}
1491				return matches;
1492			};
1493
1494		for ( iFormat = 0; iFormat < format.length; iFormat++ ) {
1495			if ( literal ) {
1496				if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) {
1497					literal = false;
1498				} else {
1499					chars += format.charAt( iFormat );
1500				}
1501			} else {
1502				switch ( format.charAt( iFormat ) ) {
1503					case "d": case "m": case "y": case "@":
1504						chars += "0123456789";
1505						break;
1506					case "D": case "M":
1507						return null; // Accept anything
1508					case "'":
1509						if ( lookAhead( "'" ) ) {
1510							chars += "'";
1511						} else {
1512							literal = true;
1513						}
1514						break;
1515					default:
1516						chars += format.charAt( iFormat );
1517				}
1518			}
1519		}
1520		return chars;
1521	},
1522
1523	/* Get a setting value, defaulting if necessary. */
1524	_get: function( inst, name ) {
1525		return inst.settings[ name ] !== undefined ?
1526			inst.settings[ name ] : this._defaults[ name ];
1527	},
1528
1529	/* Parse existing date and initialise date picker. */
1530	_setDateFromField: function( inst, noDefault ) {
1531		if ( inst.input.val() === inst.lastVal ) {
1532			return;
1533		}
1534
1535		var dateFormat = this._get( inst, "dateFormat" ),
1536			dates = inst.lastVal = inst.input ? inst.input.val() : null,
1537			defaultDate = this._getDefaultDate( inst ),
1538			date = defaultDate,
1539			settings = this._getFormatConfig( inst );
1540
1541		try {
1542			date = this.parseDate( dateFormat, dates, settings ) || defaultDate;
1543		} catch ( _err ) {
1544			dates = ( noDefault ? "" : dates );
1545		}
1546		inst.selectedDay = date.getDate();
1547		inst.drawMonth = inst.selectedMonth = date.getMonth();
1548		inst.drawYear = inst.selectedYear = date.getFullYear();
1549		inst.currentDay = ( dates ? date.getDate() : 0 );
1550		inst.currentMonth = ( dates ? date.getMonth() : 0 );
1551		inst.currentYear = ( dates ? date.getFullYear() : 0 );
1552		this._adjustInstDate( inst );
1553	},
1554
1555	/* Retrieve the default date shown on opening. */
1556	_getDefaultDate: function( inst ) {
1557		return this._restrictMinMax( inst,
1558			this._determineDate( inst, this._get( inst, "defaultDate" ), new Date() ) );
1559	},
1560
1561	/* A date may be specified as an exact value or a relative one. */
1562	_determineDate: function( inst, date, defaultDate ) {
1563		var offsetNumeric = function( offset ) {
1564				var date = new Date();
1565				date.setDate( date.getDate() + offset );
1566				return date;
1567			},
1568			offsetString = function( offset ) {
1569				try {
1570					return $.datepicker.parseDate( $.datepicker._get( inst, "dateFormat" ),
1571						offset, $.datepicker._getFormatConfig( inst ) );
1572				} catch ( _e ) {
1573
1574					// Ignore
1575				}
1576
1577				var date = ( offset.toLowerCase().match( /^c/ ) ?
1578					$.datepicker._getDate( inst ) : null ) || new Date(),
1579					year = date.getFullYear(),
1580					month = date.getMonth(),
1581					day = date.getDate(),
1582					pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,
1583					matches = pattern.exec( offset );
1584
1585				while ( matches ) {
1586					switch ( matches[ 2 ] || "d" ) {
1587						case "d" : case "D" :
1588							day += parseInt( matches[ 1 ], 10 ); break;
1589						case "w" : case "W" :
1590							day += parseInt( matches[ 1 ], 10 ) * 7; break;
1591						case "m" : case "M" :
1592							month += parseInt( matches[ 1 ], 10 );
1593							day = Math.min( day, $.datepicker._getDaysInMonth( year, month ) );
1594							break;
1595						case "y": case "Y" :
1596							year += parseInt( matches[ 1 ], 10 );
1597							day = Math.min( day, $.datepicker._getDaysInMonth( year, month ) );
1598							break;
1599					}
1600					matches = pattern.exec( offset );
1601				}
1602				return new Date( year, month, day );
1603			},
1604			newDate = ( date == null || date === "" ? defaultDate : ( typeof date === "string" ? offsetString( date ) :
1605				( typeof date === "number" ? ( isNaN( date ) ? defaultDate : offsetNumeric( date ) ) : new Date( date.getTime() ) ) ) );
1606
1607		newDate = ( newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate );
1608		if ( newDate ) {
1609			newDate.setHours( 0 );
1610			newDate.setMinutes( 0 );
1611			newDate.setSeconds( 0 );
1612			newDate.setMilliseconds( 0 );
1613		}
1614		return this._daylightSavingAdjust( newDate );
1615	},
1616
1617	/* Handle switch to/from daylight saving.
1618	 * Hours may be non-zero on daylight saving cut-over:
1619	 * > 12 when midnight changeover, but then cannot generate
1620	 * midnight datetime, so jump to 1AM, otherwise reset.
1621	 * @param  date  (Date) the date to check
1622	 * @return  (Date) the corrected date
1623	 */
1624	_daylightSavingAdjust: function( date ) {
1625		if ( !date ) {
1626			return null;
1627		}
1628		date.setHours( date.getHours() > 12 ? date.getHours() + 2 : 0 );
1629		return date;
1630	},
1631
1632	/* Set the date(s) directly. */
1633	_setDate: function( inst, date, noChange ) {
1634		var clear = !date,
1635			origMonth = inst.selectedMonth,
1636			origYear = inst.selectedYear,
1637			newDate = this._restrictMinMax( inst, this._determineDate( inst, date, new Date() ) );
1638
1639		inst.selectedDay = inst.currentDay = newDate.getDate();
1640		inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
1641		inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
1642		if ( ( origMonth !== inst.selectedMonth || origYear !== inst.selectedYear ) && !noChange ) {
1643			this._notifyChange( inst );
1644		}
1645		this._adjustInstDate( inst );
1646		if ( inst.input ) {
1647			inst.input.val( clear ? "" : this._formatDate( inst ) );
1648		}
1649	},
1650
1651	/* Retrieve the date(s) directly. */
1652	_getDate: function( inst ) {
1653		var startDate = ( !inst.currentYear || ( inst.input && inst.input.val() === "" ) ? null :
1654			this._daylightSavingAdjust( new Date(
1655			inst.currentYear, inst.currentMonth, inst.currentDay ) ) );
1656			return startDate;
1657	},
1658
1659	/* Attach the onxxx handlers.  These are declared statically so
1660	 * they work with static code transformers like Caja.
1661	 */
1662	_attachHandlers: function( inst ) {
1663		var stepMonths = this._get( inst, "stepMonths" ),
1664			id = "#" + inst.id.replace( /\\\\/g, "\\" );
1665		inst.dpDiv.find( "[data-handler]" ).map( function() {
1666			var handler = {
1667				prev: function() {
1668					$.datepicker._adjustDate( id, -stepMonths, "M" );
1669				},
1670				next: function() {
1671					$.datepicker._adjustDate( id, +stepMonths, "M" );
1672				},
1673				hide: function() {
1674					$.datepicker._hideDatepicker();
1675				},
1676				today: function() {
1677					$.datepicker._gotoToday( id );
1678				},
1679				selectDay: function() {
1680					$.datepicker._selectDay( id, +this.getAttribute( "data-month" ), +this.getAttribute( "data-year" ), this );
1681					return false;
1682				},
1683				selectMonth: function() {
1684					$.datepicker._selectMonthYear( id, this, "M" );
1685					return false;
1686				},
1687				selectYear: function() {
1688					$.datepicker._selectMonthYear( id, this, "Y" );
1689					return false;
1690				}
1691			};
1692			$( this ).on( this.getAttribute( "data-event" ), handler[ this.getAttribute( "data-handler" ) ] );
1693		} );
1694	},
1695
1696	/* Generate the HTML for the current state of the date picker. */
1697	_generateHTML: function( inst ) {
1698		var maxDraw, prevText, prev, nextText, next, currentText, gotoDate,
1699			controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin,
1700			monthNames, monthNamesShort, beforeShowDay, showOtherMonths,
1701			selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate,
1702			cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows,
1703			printDate, dRow, tbody, daySettings, otherMonth, unselectable,
1704			tempDate = new Date(),
1705			today = this._daylightSavingAdjust(
1706				new Date( tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate() ) ), // clear time
1707			isRTL = this._get( inst, "isRTL" ),
1708			showButtonPanel = this._get( inst, "showButtonPanel" ),
1709			hideIfNoPrevNext = this._get( inst, "hideIfNoPrevNext" ),
1710			navigationAsDateFormat = this._get( inst, "navigationAsDateFormat" ),
1711			numMonths = this._getNumberOfMonths( inst ),
1712			showCurrentAtPos = this._get( inst, "showCurrentAtPos" ),
1713			stepMonths = this._get( inst, "stepMonths" ),
1714			isMultiMonth = ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ),
1715			currentDate = this._daylightSavingAdjust( ( !inst.currentDay ? new Date( 9999, 9, 9 ) :
1716				new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) ),
1717			minDate = this._getMinMaxDate( inst, "min" ),
1718			maxDate = this._getMinMaxDate( inst, "max" ),
1719			drawMonth = inst.drawMonth - showCurrentAtPos,
1720			drawYear = inst.drawYear;
1721
1722		if ( drawMonth < 0 ) {
1723			drawMonth += 12;
1724			drawYear--;
1725		}
1726		if ( maxDate ) {
1727			maxDraw = this._daylightSavingAdjust( new Date( maxDate.getFullYear(),
1728				maxDate.getMonth() - ( numMonths[ 0 ] * numMonths[ 1 ] ) + 1, maxDate.getDate() ) );
1729			maxDraw = ( minDate && maxDraw < minDate ? minDate : maxDraw );
1730			while ( this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 ) ) > maxDraw ) {
1731				drawMonth--;
1732				if ( drawMonth < 0 ) {
1733					drawMonth = 11;
1734					drawYear--;
1735				}
1736			}
1737		}
1738		inst.drawMonth = drawMonth;
1739		inst.drawYear = drawYear;
1740
1741		prevText = this._get( inst, "prevText" );
1742		prevText = ( !navigationAsDateFormat ? prevText : this.formatDate( prevText,
1743			this._daylightSavingAdjust( new Date( drawYear, drawMonth - stepMonths, 1 ) ),
1744			this._getFormatConfig( inst ) ) );
1745
1746		if ( this._canAdjustMonth( inst, -1, drawYear, drawMonth ) ) {
1747			prev = $( "<a>" )
1748				.attr( {
1749					"class": "ui-datepicker-prev ui-corner-all",
1750					"data-handler": "prev",
1751					"data-event": "click",
1752					title: prevText
1753				} )
1754				.append(
1755					$( "<span>" )
1756						.addClass( "ui-icon ui-icon-circle-triangle-" +
1757							( isRTL ? "e" : "w" ) )
1758						.text( prevText )
1759				)[ 0 ].outerHTML;
1760		} else if ( hideIfNoPrevNext ) {
1761			prev = "";
1762		} else {
1763			prev = $( "<a>" )
1764				.attr( {
1765					"class": "ui-datepicker-prev ui-corner-all ui-state-disabled",
1766					title: prevText
1767				} )
1768				.append(
1769					$( "<span>" )
1770						.addClass( "ui-icon ui-icon-circle-triangle-" +
1771							( isRTL ? "e" : "w" ) )
1772						.text( prevText )
1773				)[ 0 ].outerHTML;
1774		}
1775
1776		nextText = this._get( inst, "nextText" );
1777		nextText = ( !navigationAsDateFormat ? nextText : this.formatDate( nextText,
1778			this._daylightSavingAdjust( new Date( drawYear, drawMonth + stepMonths, 1 ) ),
1779			this._getFormatConfig( inst ) ) );
1780
1781		if ( this._canAdjustMonth( inst, +1, drawYear, drawMonth ) ) {
1782			next = $( "<a>" )
1783				.attr( {
1784					"class": "ui-datepicker-next ui-corner-all",
1785					"data-handler": "next",
1786					"data-event": "click",
1787					title: nextText
1788				} )
1789				.append(
1790					$( "<span>" )
1791						.addClass( "ui-icon ui-icon-circle-triangle-" +
1792							( isRTL ? "w" : "e" ) )
1793						.text( nextText )
1794				)[ 0 ].outerHTML;
1795		} else if ( hideIfNoPrevNext ) {
1796			next = "";
1797		} else {
1798			next = $( "<a>" )
1799				.attr( {
1800					"class": "ui-datepicker-next ui-corner-all ui-state-disabled",
1801					title: nextText
1802				} )
1803				.append(
1804					$( "<span>" )
1805						.attr( "class", "ui-icon ui-icon-circle-triangle-" +
1806							( isRTL ? "w" : "e" ) )
1807						.text( nextText )
1808				)[ 0 ].outerHTML;
1809		}
1810
1811		currentText = this._get( inst, "currentText" );
1812		gotoDate = ( this._get( inst, "gotoCurrent" ) && inst.currentDay ? currentDate : today );
1813		currentText = ( !navigationAsDateFormat ? currentText :
1814			this.formatDate( currentText, gotoDate, this._getFormatConfig( inst ) ) );
1815
1816		controls = "";
1817		if ( !inst.inline ) {
1818			controls = $( "<button>" )
1819				.attr( {
1820					type: "button",
1821					"class": "ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all",
1822					"data-handler": "hide",
1823					"data-event": "click"
1824				} )
1825				.text( this._get( inst, "closeText" ) )[ 0 ].outerHTML;
1826		}
1827
1828		buttonPanel = "";
1829		if ( showButtonPanel ) {
1830			buttonPanel = $( "<div class='ui-datepicker-buttonpane ui-widget-content'>" )
1831				.append( isRTL ? controls : "" )
1832				.append( this._isInRange( inst, gotoDate ) ?
1833					$( "<button>" )
1834						.attr( {
1835							type: "button",
1836							"class": "ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all",
1837							"data-handler": "today",
1838							"data-event": "click"
1839						} )
1840						.text( currentText ) :
1841					"" )
1842				.append( isRTL ? "" : controls )[ 0 ].outerHTML;
1843		}
1844
1845		firstDay = parseInt( this._get( inst, "firstDay" ), 10 );
1846		firstDay = ( isNaN( firstDay ) ? 0 : firstDay );
1847
1848		showWeek = this._get( inst, "showWeek" );
1849		dayNames = this._get( inst, "dayNames" );
1850		dayNamesMin = this._get( inst, "dayNamesMin" );
1851		monthNames = this._get( inst, "monthNames" );
1852		monthNamesShort = this._get( inst, "monthNamesShort" );
1853		beforeShowDay = this._get( inst, "beforeShowDay" );
1854		showOtherMonths = this._get( inst, "showOtherMonths" );
1855		selectOtherMonths = this._get( inst, "selectOtherMonths" );
1856		defaultDate = this._getDefaultDate( inst );
1857		html = "";
1858
1859		for ( row = 0; row < numMonths[ 0 ]; row++ ) {
1860			group = "";
1861			this.maxRows = 4;
1862			for ( col = 0; col < numMonths[ 1 ]; col++ ) {
1863				selectedDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, inst.selectedDay ) );
1864				cornerClass = " ui-corner-all";
1865				calender = "";
1866				if ( isMultiMonth ) {
1867					calender += "<div class='ui-datepicker-group";
1868					if ( numMonths[ 1 ] > 1 ) {
1869						switch ( col ) {
1870							case 0: calender += " ui-datepicker-group-first";
1871								cornerClass = " ui-corner-" + ( isRTL ? "right" : "left" ); break;
1872							case numMonths[ 1 ] - 1: calender += " ui-datepicker-group-last";
1873								cornerClass = " ui-corner-" + ( isRTL ? "left" : "right" ); break;
1874							default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break;
1875						}
1876					}
1877					calender += "'>";
1878				}
1879				calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" +
1880					( /all|left/.test( cornerClass ) && row === 0 ? ( isRTL ? next : prev ) : "" ) +
1881					( /all|right/.test( cornerClass ) && row === 0 ? ( isRTL ? prev : next ) : "" ) +
1882					this._generateMonthYearHeader( inst, drawMonth, drawYear, minDate, maxDate,
1883					row > 0 || col > 0, monthNames, monthNamesShort ) + // draw month headers
1884					"</div><table class='ui-datepicker-calendar'><thead>" +
1885					"<tr>";
1886				thead = ( showWeek ? "<th class='ui-datepicker-week-col'>" + this._get( inst, "weekHeader" ) + "</th>" : "" );
1887				for ( dow = 0; dow < 7; dow++ ) { // days of the week
1888					day = ( dow + firstDay ) % 7;
1889					thead += "<th scope='col'" + ( ( dow + firstDay + 6 ) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "" ) + ">" +
1890						"<span title='" + dayNames[ day ] + "'>" + dayNamesMin[ day ] + "</span></th>";
1891				}
1892				calender += thead + "</tr></thead><tbody>";
1893				daysInMonth = this._getDaysInMonth( drawYear, drawMonth );
1894				if ( drawYear === inst.selectedYear && drawMonth === inst.selectedMonth ) {
1895					inst.selectedDay = Math.min( inst.selectedDay, daysInMonth );
1896				}
1897				leadDays = ( this._getFirstDayOfMonth( drawYear, drawMonth ) - firstDay + 7 ) % 7;
1898				curRows = Math.ceil( ( leadDays + daysInMonth ) / 7 ); // calculate the number of rows to generate
1899				numRows = ( isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows ); //If multiple months, use the higher number of rows (see #7043)
1900				this.maxRows = numRows;
1901				printDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 - leadDays ) );
1902				for ( dRow = 0; dRow < numRows; dRow++ ) { // create date picker rows
1903					calender += "<tr>";
1904					tbody = ( !showWeek ? "" : "<td class='ui-datepicker-week-col'>" +
1905						this._get( inst, "calculateWeek" )( printDate ) + "</td>" );
1906					for ( dow = 0; dow < 7; dow++ ) { // create date picker days
1907						daySettings = ( beforeShowDay ?
1908							beforeShowDay.apply( ( inst.input ? inst.input[ 0 ] : null ), [ printDate ] ) : [ true, "" ] );
1909						otherMonth = ( printDate.getMonth() !== drawMonth );
1910						unselectable = ( otherMonth && !selectOtherMonths ) || !daySettings[ 0 ] ||
1911							( minDate && printDate < minDate ) || ( maxDate && printDate > maxDate );
1912						tbody += "<td class='" +
1913							( ( dow + firstDay + 6 ) % 7 >= 5 ? " ui-datepicker-week-end" : "" ) + // highlight weekends
1914							( otherMonth ? " ui-datepicker-other-month" : "" ) + // highlight days from other months
1915							( ( printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent ) || // user pressed key
1916							( defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime() ) ?
1917
1918							// or defaultDate is current printedDate and defaultDate is selectedDate
1919							" " + this._dayOverClass : "" ) + // highlight selected day
1920							( unselectable ? " " + this._unselectableClass + " ui-state-disabled" : "" ) +  // highlight unselectable days
1921							( otherMonth && !showOtherMonths ? "" : " " + daySettings[ 1 ] + // highlight custom dates
1922							( printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "" ) + // highlight selected day
1923							( printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "" ) ) + "'" + // highlight today (if different)
1924							( ( !otherMonth || showOtherMonths ) && daySettings[ 2 ] ? " title='" + daySettings[ 2 ].replace( /'/g, "&#39;" ) + "'" : "" ) + // cell title
1925							( unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'" ) + ">" + // actions
1926							( otherMonth && !showOtherMonths ? "&#xa0;" : // display for other months
1927							( unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" +
1928							( printDate.getTime() === today.getTime() ? " ui-state-highlight" : "" ) +
1929							( printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "" ) + // highlight selected day
1930							( otherMonth ? " ui-priority-secondary" : "" ) + // distinguish dates from other months
1931							"' href='#' aria-current='" + ( printDate.getTime() === currentDate.getTime() ? "true" : "false" ) + // mark date as selected for screen reader
1932							"' data-date='" + printDate.getDate() + // store date as data
1933							"'>" + printDate.getDate() + "</a>" ) ) + "</td>"; // display selectable date
1934						printDate.setDate( printDate.getDate() + 1 );
1935						printDate = this._daylightSavingAdjust( printDate );
1936					}
1937					calender += tbody + "</tr>";
1938				}
1939				drawMonth++;
1940				if ( drawMonth > 11 ) {
1941					drawMonth = 0;
1942					drawYear++;
1943				}
1944				calender += "</tbody></table>" + ( isMultiMonth ? "</div>" +
1945							( ( numMonths[ 0 ] > 0 && col === numMonths[ 1 ] - 1 ) ? "<div class='ui-datepicker-row-break'></div>" : "" ) : "" );
1946				group += calender;
1947			}
1948			html += group;
1949		}
1950		html += buttonPanel;
1951		inst._keyEvent = false;
1952		return html;
1953	},
1954
1955	/* Generate the month and year header. */
1956	_generateMonthYearHeader: function( inst, drawMonth, drawYear, minDate, maxDate,
1957			secondary, monthNames, monthNamesShort ) {
1958
1959		var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear,
1960			changeMonth = this._get( inst, "changeMonth" ),
1961			changeYear = this._get( inst, "changeYear" ),
1962			showMonthAfterYear = this._get( inst, "showMonthAfterYear" ),
1963			selectMonthLabel = this._get( inst, "selectMonthLabel" ),
1964			selectYearLabel = this._get( inst, "selectYearLabel" ),
1965			html = "<div class='ui-datepicker-title'>",
1966			monthHtml = "";
1967
1968		// Month selection
1969		if ( secondary || !changeMonth ) {
1970			monthHtml += "<span class='ui-datepicker-month'>" + monthNames[ drawMonth ] + "</span>";
1971		} else {
1972			inMinYear = ( minDate && minDate.getFullYear() === drawYear );
1973			inMaxYear = ( maxDate && maxDate.getFullYear() === drawYear );
1974			monthHtml += "<select class='ui-datepicker-month' aria-label='" + selectMonthLabel + "' data-handler='selectMonth' data-event='change'>";
1975			for ( month = 0; month < 12; month++ ) {
1976				if ( ( !inMinYear || month >= minDate.getMonth() ) && ( !inMaxYear || month <= maxDate.getMonth() ) ) {
1977					monthHtml += "<option value='" + month + "'" +
1978						( month === drawMonth ? " selected='selected'" : "" ) +
1979						">" + monthNamesShort[ month ] + "</option>";
1980				}
1981			}
1982			monthHtml += "</select>";
1983		}
1984
1985		if ( !showMonthAfterYear ) {
1986			html += monthHtml + ( secondary || !( changeMonth && changeYear ) ? "&#xa0;" : "" );
1987		}
1988
1989		// Year selection
1990		if ( !inst.yearshtml ) {
1991			inst.yearshtml = "";
1992			if ( secondary || !changeYear ) {
1993				html += "<span class='ui-datepicker-year'>" + drawYear + "</span>";
1994			} else {
1995
1996				// determine range of years to display
1997				years = this._get( inst, "yearRange" ).split( ":" );
1998				thisYear = new Date().getFullYear();
1999				determineYear = function( value ) {
2000					var year = ( value.match( /c[+\-].*/ ) ? drawYear + parseInt( value.substring( 1 ), 10 ) :
2001						( value.match( /[+\-].*/ ) ? thisYear + parseInt( value, 10 ) :
2002						parseInt( value, 10 ) ) );
2003					return ( isNaN( year ) ? thisYear : year );
2004				};
2005				year = determineYear( years[ 0 ] );
2006				endYear = Math.max( year, determineYear( years[ 1 ] || "" ) );
2007				year = ( minDate ? Math.max( year, minDate.getFullYear() ) : year );
2008				endYear = ( maxDate ? Math.min( endYear, maxDate.getFullYear() ) : endYear );
2009				inst.yearshtml += "<select class='ui-datepicker-year' aria-label='" + selectYearLabel + "' data-handler='selectYear' data-event='change'>";
2010				for ( ; year <= endYear; year++ ) {
2011					inst.yearshtml += "<option value='" + year + "'" +
2012						( year === drawYear ? " selected='selected'" : "" ) +
2013						">" + year + "</option>";
2014				}
2015				inst.yearshtml += "</select>";
2016
2017				html += inst.yearshtml;
2018				inst.yearshtml = null;
2019			}
2020		}
2021
2022		html += this._get( inst, "yearSuffix" );
2023		if ( showMonthAfterYear ) {
2024			html += ( secondary || !( changeMonth && changeYear ) ? "&#xa0;" : "" ) + monthHtml;
2025		}
2026		html += "</div>"; // Close datepicker_header
2027		return html;
2028	},
2029
2030	/* Adjust one of the date sub-fields. */
2031	_adjustInstDate: function( inst, offset, period ) {
2032		var year = inst.selectedYear + ( period === "Y" ? offset : 0 ),
2033			month = inst.selectedMonth + ( period === "M" ? offset : 0 ),
2034			day = Math.min( inst.selectedDay, this._getDaysInMonth( year, month ) ) + ( period === "D" ? offset : 0 ),
2035			date = this._restrictMinMax( inst, this._daylightSavingAdjust( new Date( year, month, day ) ) );
2036
2037		inst.selectedDay = date.getDate();
2038		inst.drawMonth = inst.selectedMonth = date.getMonth();
2039		inst.drawYear = inst.selectedYear = date.getFullYear();
2040		if ( period === "M" || period === "Y" ) {
2041			this._notifyChange( inst );
2042		}
2043	},
2044
2045	/* Ensure a date is within any min/max bounds. */
2046	_restrictMinMax: function( inst, date ) {
2047		var minDate = this._getMinMaxDate( inst, "min" ),
2048			maxDate = this._getMinMaxDate( inst, "max" ),
2049			newDate = ( minDate && date < minDate ? minDate : date );
2050		return ( maxDate && newDate > maxDate ? maxDate : newDate );
2051	},
2052
2053	/* Notify change of month/year. */
2054	_notifyChange: function( inst ) {
2055		var onChange = this._get( inst, "onChangeMonthYear" );
2056		if ( onChange ) {
2057			onChange.apply( ( inst.input ? inst.input[ 0 ] : null ),
2058				[ inst.selectedYear, inst.selectedMonth + 1, inst ] );
2059		}
2060	},
2061
2062	/* Determine the number of months to show. */
2063	_getNumberOfMonths: function( inst ) {
2064		var numMonths = this._get( inst, "numberOfMonths" );
2065		return ( numMonths == null ? [ 1, 1 ] : ( typeof numMonths === "number" ? [ 1, numMonths ] : numMonths ) );
2066	},
2067
2068	/* Determine the current maximum date - ensure no time components are set. */
2069	_getMinMaxDate: function( inst, minMax ) {
2070		return this._determineDate( inst, this._get( inst, minMax + "Date" ), null );
2071	},
2072
2073	/* Find the number of days in a given month. */
2074	_getDaysInMonth: function( year, month ) {
2075		return 32 - this._daylightSavingAdjust( new Date( year, month, 32 ) ).getDate();
2076	},
2077
2078	/* Find the day of the week of the first of a month. */
2079	_getFirstDayOfMonth: function( year, month ) {
2080		return new Date( year, month, 1 ).getDay();
2081	},
2082
2083	/* Determines if we should allow a "next/prev" month display change. */
2084	_canAdjustMonth: function( inst, offset, curYear, curMonth ) {
2085		var numMonths = this._getNumberOfMonths( inst ),
2086			date = this._daylightSavingAdjust( new Date( curYear,
2087			curMonth + ( offset < 0 ? offset : numMonths[ 0 ] * numMonths[ 1 ] ), 1 ) );
2088
2089		if ( offset < 0 ) {
2090			date.setDate( this._getDaysInMonth( date.getFullYear(), date.getMonth() ) );
2091		}
2092		return this._isInRange( inst, date );
2093	},
2094
2095	/* Is the given date in the accepted range? */
2096	_isInRange: function( inst, date ) {
2097		var yearSplit, currentYear,
2098			minDate = this._getMinMaxDate( inst, "min" ),
2099			maxDate = this._getMinMaxDate( inst, "max" ),
2100			minYear = null,
2101			maxYear = null,
2102			years = this._get( inst, "yearRange" );
2103			if ( years ) {
2104				yearSplit = years.split( ":" );
2105				currentYear = new Date().getFullYear();
2106				minYear = parseInt( yearSplit[ 0 ], 10 );
2107				maxYear = parseInt( yearSplit[ 1 ], 10 );
2108				if ( yearSplit[ 0 ].match( /[+\-].*/ ) ) {
2109					minYear += currentYear;
2110				}
2111				if ( yearSplit[ 1 ].match( /[+\-].*/ ) ) {
2112					maxYear += currentYear;
2113				}
2114			}
2115
2116		return ( ( !minDate || date.getTime() >= minDate.getTime() ) &&
2117			( !maxDate || date.getTime() <= maxDate.getTime() ) &&
2118			( !minYear || date.getFullYear() >= minYear ) &&
2119			( !maxYear || date.getFullYear() <= maxYear ) );
2120	},
2121
2122	/* Provide the configuration settings for formatting/parsing. */
2123	_getFormatConfig: function( inst ) {
2124		var shortYearCutoff = this._get( inst, "shortYearCutoff" );
2125		shortYearCutoff = ( typeof shortYearCutoff !== "string" ? shortYearCutoff :
2126			new Date().getFullYear() % 100 + parseInt( shortYearCutoff, 10 ) );
2127		return { shortYearCutoff: shortYearCutoff,
2128			dayNamesShort: this._get( inst, "dayNamesShort" ), dayNames: this._get( inst, "dayNames" ),
2129			monthNamesShort: this._get( inst, "monthNamesShort" ), monthNames: this._get( inst, "monthNames" ) };
2130	},
2131
2132	/* Format the given date for display. */
2133	_formatDate: function( inst, day, month, year ) {
2134		if ( !day ) {
2135			inst.currentDay = inst.selectedDay;
2136			inst.currentMonth = inst.selectedMonth;
2137			inst.currentYear = inst.selectedYear;
2138		}
2139		var date = ( day ? ( typeof day === "object" ? day :
2140			this._daylightSavingAdjust( new Date( year, month, day ) ) ) :
2141			this._daylightSavingAdjust( new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) );
2142		return this.formatDate( this._get( inst, "dateFormat" ), date, this._getFormatConfig( inst ) );
2143	}
2144} );
2145
2146/*
2147 * Bind hover events for datepicker elements.
2148 * Done via delegate so the binding only occurs once in the lifetime of the parent div.
2149 * Global datepicker_instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
2150 */
2151function datepicker_bindHover( dpDiv ) {
2152	var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";
2153	return dpDiv.on( "mouseout", selector, function() {
2154			$( this ).removeClass( "ui-state-hover" );
2155			if ( this.className.indexOf( "ui-datepicker-prev" ) !== -1 ) {
2156				$( this ).removeClass( "ui-datepicker-prev-hover" );
2157			}
2158			if ( this.className.indexOf( "ui-datepicker-next" ) !== -1 ) {
2159				$( this ).removeClass( "ui-datepicker-next-hover" );
2160			}
2161		} )
2162		.on( "mouseover", selector, datepicker_handleMouseover );
2163}
2164
2165function datepicker_handleMouseover() {
2166	if ( !$.datepicker._isDisabledDatepicker( datepicker_instActive.inline ? datepicker_instActive.dpDiv.parent()[ 0 ] : datepicker_instActive.input[ 0 ] ) ) {
2167		$( this ).parents( ".ui-datepicker-calendar" ).find( "a" ).removeClass( "ui-state-hover" );
2168		$( this ).addClass( "ui-state-hover" );
2169		if ( this.className.indexOf( "ui-datepicker-prev" ) !== -1 ) {
2170			$( this ).addClass( "ui-datepicker-prev-hover" );
2171		}
2172		if ( this.className.indexOf( "ui-datepicker-next" ) !== -1 ) {
2173			$( this ).addClass( "ui-datepicker-next-hover" );
2174		}
2175	}
2176}
2177
2178/* jQuery extend now ignores nulls! */
2179function datepicker_extendRemove( target, props ) {
2180	$.extend( target, props );
2181	for ( var name in props ) {
2182		if ( props[ name ] == null ) {
2183			target[ name ] = props[ name ];
2184		}
2185	}
2186	return target;
2187}
2188
2189/* Invoke the datepicker functionality.
2190   @param  options  string - a command, optionally followed by additional parameters or
2191					Object - settings for attaching new datepicker functionality
2192   @return  jQuery object */
2193$.fn.datepicker = function( options ) {
2194
2195	/* Verify an empty collection wasn't passed - Fixes #6976 */
2196	if ( !this.length ) {
2197		return this;
2198	}
2199
2200	/* Initialise the date picker. */
2201	if ( !$.datepicker.initialized ) {
2202		$( document ).on( "mousedown", $.datepicker._checkExternalClick );
2203		$.datepicker.initialized = true;
2204	}
2205
2206	/* Append datepicker main container to body if not exist. */
2207	if ( $( "#" + $.datepicker._mainDivId ).length === 0 ) {
2208		$( "body" ).append( $.datepicker.dpDiv );
2209	}
2210
2211	var otherArgs = Array.prototype.slice.call( arguments, 1 );
2212	if ( typeof options === "string" && ( options === "isDisabled" || options === "getDate" || options === "widget" ) ) {
2213		return $.datepicker[ "_" + options + "Datepicker" ].
2214			apply( $.datepicker, [ this[ 0 ] ].concat( otherArgs ) );
2215	}
2216	if ( options === "option" && arguments.length === 2 && typeof arguments[ 1 ] === "string" ) {
2217		return $.datepicker[ "_" + options + "Datepicker" ].
2218			apply( $.datepicker, [ this[ 0 ] ].concat( otherArgs ) );
2219	}
2220	return this.each( function() {
2221		if ( typeof options === "string" ) {
2222			$.datepicker[ "_" + options + "Datepicker" ]
2223				.apply( $.datepicker, [ this ].concat( otherArgs ) );
2224		} else {
2225			$.datepicker._attachDatepicker( this, options );
2226		}
2227	} );
2228};
2229
2230$.datepicker = new Datepicker(); // singleton instance
2231$.datepicker.initialized = false;
2232$.datepicker.uuid = new Date().getTime();
2233$.datepicker.version = "1.14.2";
2234
2235return $.datepicker;
2236
2237} );

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.