Subversion Repositories Sites.obs-saisons.fr

Rev

Rev 40 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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