PageSourceSearch

https://www.nsktv.ru/bitrix/templates/gtrk_main/js/ui/jquery.ui.datepicker.js?141598962577451

js nsktv.ru collected 2026-10-01 10:43:06 UTC 77,451 bytes, 2,057 lines download raw bytes

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

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