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