wp/wp-includes/js/jquery/ui/datepicker.js
changeset 18 be944660c56a
child 19 3d72ae0968f4
equal deleted inserted replaced
17:34716fd837a4 18:be944660c56a
       
     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 } ) );