angelovcom.net

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

datepicker.js (80771B)


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