PageSourceSearch

https://www.sunshinecoastskatingclub.ca/js/jquery-ui-timepicker-addon.js?1790193087

js sunshinecoastskatingclub.ca collected 2026-09-28 18:01:07 UTC 62,532 bytes, 1,901 lines download raw bytes

vendor: 6,204 bytes, lines 1-234
1/*
2 * jQuery timepicker addon
3 * By: Trent Richardson [http://trentrichardson.com]
4 * Version 1.1.1
5 * Last Modified: 11/07/2012
6 *
7 * Copyright 2012 Trent Richardson
8 * You may use this project under MIT or GPL licenses.
9 * http://trentrichardson.com/Impromptu/GPL-LICENSE.txt
10 * http://trentrichardson.com/Impromptu/MIT-LICENSE.txt
11 */
12
13/*jslint evil: true, white: false, undef: false, nomen: false */
14
15(function($) {
16
17	/*
18	* Lets not redefine timepicker, Prevent "Uncaught RangeError: Maximum call stack size exceeded"
19	*/
20	$.ui.timepicker = $.ui.timepicker || {};
21	if ($.ui.timepicker.version) {
22		return;
23	}
24
25	/*
26	* Extend jQueryUI, get it started with our version number
27	*/
28	$.extend($.ui, {
29		timepicker: {
30			version: "1.1.1"
31		}
32	});
33
34	/* 
35	* Timepicker manager.
36	* Use the singleton instance of this class, $.timepicker, to interact with the time picker.
37	* Settings for (groups of) time pickers are maintained in an instance object,
38	* allowing multiple different settings on the same page.
39	*/
40
41	function Timepicker() {
42		this.regional = []; // Available regional settings, indexed by language code
43		this.regional['eng'] = { // Default regional settings
44			currentText: 'Now',
45			closeText: 'Done',
46			amNames: ['AM', 'A'],
47			pmNames: ['PM', 'P'],
48			timeFormat: 'HH:mm',
49			timeSuffix: '',
50			timeOnlyTitle: 'Choose Time',
51			timeText: 'Time',
52			hourText: 'Hour',
53			minuteText: 'Minute',
54			secondText: 'Second',
55			millisecText: 'Millisecond',
56			timezoneText: 'Time Zone',
57			isRTL: false
58		};
59		this.regional['fre'] = {
60			timeOnlyTitle: 'Choisir une heure',
61			timeText: 'Heure',
62			hourText: 'Heures',
63			minuteText: 'Minutes',
64			secondText: 'Secondes',
65			millisecText: 'Millisecondes',
66			microsecText: 'Microsecondes',
67			timezoneText: 'Fuseau horaire',
68			currentText: 'Maintenant',
69			closeText: 'Terminé',
70			timeFormat: 'HH:mm',
71			timeSuffix: '',
72			amNames: ['AM', 'A'],
73			pmNames: ['PM', 'P'],
74			isRTL: false
75		};
76		this._defaults = { // Global defaults for all the datetime picker instances
77			showButtonPanel: true,
78			timeOnly: false,
79			showHour: true,
80			showMinute: true,
81			showSecond: false,
82			showMillisec: false,
83			showTimezone: false,
84			showTime: true,
85			stepHour: 1,
86			stepMinute: 1,
87			stepSecond: 1,
88			stepMillisec: 1,
89			hour: 0,
90			minute: 0,
91			second: 0,
92			millisec: 0,
93			timezone: null,
94			useLocalTimezone: false,
95			defaultTimezone: "+0000",
96			hourMin: 0,
97			minuteMin: 0,
98			secondMin: 0,
99			millisecMin: 0,
100			hourMax: 23,
101			minuteMax: 59,
102			secondMax: 59,
103			millisecMax: 999,
104			minDateTime: null,
105			maxDateTime: null,
106			onSelect: null,
107			hourGrid: 0,
108			minuteGrid: 0,
109			secondGrid: 0,
110			millisecGrid: 0,
111			alwaysSetTime: true,
112			separator: ' ',
113			altFieldTimeOnly: true,
114			altTimeFormat: null,
115			altSeparator: null,
116			altTimeSuffix: null,
117			pickerTimeFormat: null,
118			pickerTimeSuffix: null,
119			showTimepicker: true,
120			timezoneIso8601: false,
121			timezoneList: null,
122			addSliderAccess: false,
123			sliderAccessArgs: null,
124			controlType: 'slider',
125			defaultValue: null,
126			parse: 'strict'
127		};
128
129		$.extend(this._defaults, this.regional[lang]);
130	}
131
132	$.extend(Timepicker.prototype, {
133		$input: null,
134		$altInput: null,
135		$timeObj: null,
136		inst: null,
137		hour_slider: null,
138		minute_slider: null,
139		second_slider: null,
140		millisec_slider: null,
141		timezone_select: null,
142		hour: 0,
143		minute: 0,
144		second: 0,
145		millisec: 0,
146		timezone: null,
147		defaultTimezone: "+0000",
148		hourMinOriginal: null,
149		minuteMinOriginal: null,
150		secondMinOriginal: null,
151		millisecMinOriginal: null,
152		hourMaxOriginal: null,
153		minuteMaxOriginal: null,
154		secondMaxOriginal: null,
155		millisecMaxOriginal: null,
156		ampm: '',
157		formattedDate: '',
158		formattedTime: '',
159		formattedDateTime: '',
160		timezoneList: null,
161		units: ['hour','minute','second','millisec'],
162		control: null,
163
164		/* 
165		* Override the default settings for all instances of the time picker.
166		* @param  settings  object - the new settings to use as defaults (anonymous object)
167		* @return the manager object
168		*/
169		setDefaults: function(settings) {
170			extendRemove(this._defaults, settings || {});
171			return this;
172		},
173
174		/*
175		* Create a new Timepicker instance
176		*/
177		_newInst: function($input, o) {
178			var tp_inst = new Timepicker(),
179				inlineSettings = {},
180				fns = {},
181				overrides, i;
182
183			for (var attrName in this._defaults) {
184				if(this._defaults.hasOwnProperty(attrName)){
185					var attrValue = $input.attr('time:' + attrName);
186					if (attrValue) {
187						try {
188							inlineSettings[attrName] = eval(attrValue);
189						} catch (err) {
190							inlineSettings[attrName] = attrValue;
191						}
192					}
193				}
194			}
195			overrides = {
196				beforeShow: function (input, dp_inst) {
197					if ($.isFunction(tp_inst._defaults.evnts.beforeShow)) {
198						return tp_inst._defaults.evnts.beforeShow.call($input[0], input, dp_inst, tp_inst);
199					}
200				},
201				onChangeMonthYear: function (year, month, dp_inst) {
202					// Update the time as well : this prevents the time from disappearing from the $input field.
203					tp_inst._updateDateTime(dp_inst);
204					if ($.isFunction(tp_inst._defaults.evnts.onChangeMonthYear)) {
205						tp_inst._defaults.evnts.onChangeMonthYear.call($input[0], year, month, dp_inst, tp_inst);
206					}
207				},
208				onClose: function (dateText, dp_inst) {
209					if (tp_inst.timeDefined === true && $input.val() !== '') {
210						tp_inst._updateDateTime(dp_inst);
211					}
212					if ($.isFunction(tp_inst._defaults.evnts.onClose)) {
213						tp_inst._defaults.evnts.onClose.call($input[0], dateText, dp_inst, tp_inst);
214					}
215				}
216			};
217			for (i in overrides) {
218				if (overrides.hasOwnProperty(i)) {
219					fns[i] = o[i] || null;
220				}
221			}
222			tp_inst._defaults = $.extend({}, this._defaults, inlineSettings, o, overrides, {
223				evnts:fns,
224				timepicker: tp_inst // add timepicker as a property of datepicker: $.datepicker._get(dp_inst, 'timepicker');
225			});
226			tp_inst.amNames = $.map(tp_inst._defaults.amNames, function(val) {
227				return val.toUpperCase();
228			});
229			tp_inst.pmNames = $.map(tp_inst._defaults.pmNames, function(val) {
230				return val.toUpperCase();
231			});
232
233			// controlType is string - key to our this._controls
234			if(typeof(tp_inst._defaults.controlType) === 'string'){
235				if($.fn[tp_inst._defaults.controlType] === undefined){
236					tp_inst._defaults.controlType = 'select';
237				}
238				tp_inst.control = tp_inst._controls[tp_inst._defaults.controlType];
239			}
240			// controlType is an object and must implement create, options, value methods
241			else{ 
242				tp_inst.control = tp_inst._defaults.controlType;
243			}
244
245			if (tp_inst._defaults.timezoneList === null) {
246				var timezoneList = ['-1200', '-1100', '-1000', '-0930', '-0900', '-0800', '-0700', '-0600', '-0500', '-0430', '-0400', '-0330', '-0300', '-0200', '-0100', '+0000', 
247									'+0100', '+0200', '+0300', '+0330', '+0400', '+0430', '+0500', '+0530', '+0545', '+0600', '+0630', '+0700', '+0800', '+0845', '+0900', '+0930', 
248									'+1000', '+1030', '+1100', '+1130', '+1200', '+1245', '+1300', '+1400'];
249
250				if (tp_inst._defaults.timezoneIso8601) {
251					timezoneList = $.map(timezoneList, function(val) {
252						return val == '+0000' ? 'Z' : (val.substring(0, 3) + ':' + val.substring(3));
253					});
254				}
255				tp_inst._defaults.timezoneList = timezoneList;
256			}
257
258			tp_inst.timezone = tp_inst._defaults.timezone;
259			tp_inst.hour = tp_inst._defaults.hour;
260			tp_inst.minute = tp_inst._defaults.minute;
261			tp_inst.second = tp_inst._defaults.second;
262			tp_inst.millisec = tp_inst._defaults.millisec;
263			tp_inst.ampm = '';
264			tp_inst.$input = $input;
265
266			if (o.altField) {
267				tp_inst.$altInput = $(o.altField).css({
268					cursor: 'pointer'
269				}).focus(function() {
270					$input.trigger("focus");
271				});
272			}
273
274			if (tp_inst._defaults.minDate === 0 || tp_inst._defaults.minDateTime === 0) {
275				tp_inst._defaults.minDate = new Date();
276			}
277			if (tp_inst._defaults.maxDate === 0 || tp_inst._defaults.maxDateTime === 0) {
278				tp_inst._defaults.maxDate = new Date();
279			}
280
281			// datepicker needs minDate/maxDate, timepicker needs minDateTime/maxDateTime..
282			if (tp_inst._defaults.minDate !== undefined && tp_inst._defaults.minDate instanceof Date) {
283				tp_inst._defaults.minDateTime = new Date(tp_inst._defaults.minDate.getTime());
284			}
285			if (tp_inst._defaults.minDateTime !== undefined && tp_inst._defaults.minDateTime instanceof Date) {
286				tp_inst._defaults.minDate = new Date(tp_inst._defaults.minDateTime.getTime());
287			}
288			if (tp_inst._defaults.maxDate !== undefined && tp_inst._defaults.maxDate instanceof Date) {
289				tp_inst._defaults.maxDateTime = new Date(tp_inst._defaults.maxDate.getTime());
290			}
291			if (tp_inst._defaults.maxDateTime !== undefined && tp_inst._defaults.maxDateTime instanceof Date) {
292				tp_inst._defaults.maxDate = new Date(tp_inst._defaults.maxDateTime.getTime());
293			}
294			tp_inst.$input.bind('focus', function() {
295				tp_inst._onFocus();
296			});
297
298			return tp_inst;
299		},
300
301		/*
302		* add our sliders to the calendar
303		*/
304		_addTimePicker: function(dp_inst) {
305			var currDT = (this.$altInput && this._defaults.altFieldTimeOnly) ? this.$input.val() + ' ' + this.$altInput.val() : this.$input.val();
306
307			this.timeDefined = this._parseTime(currDT);
308			this._limitMinMaxDateTime(dp_inst, false);
309			this._injectTimePicker();
310		},
311
312		/*
313		* parse the time string from input value or _setTime
314		*/
315		_parseTime: function(timeString, withDate) {
316			if (!this.inst) {
317				this.inst = $.datepicker._getInst(this.$input[0]);
318			}
319
320			if (withDate || !this._defaults.timeOnly) {
321				var dp_dateFormat = $.datepicker._get(this.inst, 'dateFormat');
vendor: 14,783 bytes, lines 322-676
322				try {
323					var parseRes = parseDateTimeInternal(dp_dateFormat, this._defaults.timeFormat, timeString, $.datepicker._getFormatConfig(this.inst), this._defaults);
324					if (!parseRes.timeObj) {
325						return false;
326					}
327					$.extend(this, parseRes.timeObj);
328				} catch (err) {
329					$.datepicker.log("Error parsing the date/time string: " + err +
330									"\ndate/time string = " + timeString +
331									"\ntimeFormat = " + this._defaults.timeFormat +
332									"\ndateFormat = " + dp_dateFormat);
333					return false;
334				}
335				return true;
336			} else {
337				var timeObj = $.datepicker.parseTime(this._defaults.timeFormat, timeString, this._defaults);
338				if (!timeObj) {
339					return false;
340				}
341				$.extend(this, timeObj);
342				return true;
343			}
344		},
345
346		/*
347		* generate and inject html for timepicker into ui datepicker
348		*/
349		_injectTimePicker: function() {
350			var $dp = this.inst.dpDiv,
351				o = this.inst.settings,
352				tp_inst = this,
353				litem = '',
354				uitem = '',
355				max = {},
356				gridSize = {},
357				size = null;
358
359			// Prevent displaying twice
360			if ($dp.find("div.ui-timepicker-div").length === 0 && o.showTimepicker) {
361				var noDisplay = ' style="display:none;"',
362					html = '<div class="ui-timepicker-div'+ (o.isRTL? ' ui-timepicker-rtl' : '') +'"><dl>' + '<dt class="ui_tpicker_time_label"' + ((o.showTime) ? '' : noDisplay) + '>' + o.timeText + '</dt>' + 
363								'<dd class="ui_tpicker_time"' + ((o.showTime) ? '' : noDisplay) + '></dd>';
364
365				// Create the markup
366				for(var i=0,l=this.units.length; i<l; i++){
367					litem = this.units[i];
368					uitem = litem.substr(0,1).toUpperCase() + litem.substr(1);
369					// Added by Peter Medeiros:
370					// - Figure out what the hour/minute/second max should be based on the step values.
371					// - Example: if stepMinute is 15, then minMax is 45.
372					max[litem] = parseInt((o[litem+'Max'] - ((o[litem+'Max'] - o[litem+'Min']) % o['step'+uitem])), 10);
373					gridSize[litem] = 0;
374
375					html += '<dt class="ui_tpicker_'+ litem +'_label"' + ((o['show'+uitem]) ? '' : noDisplay) + '>' + o[litem +'Text'] + '</dt>' + 
376								'<dd class="ui_tpicker_'+ litem +'"><div class="ui_tpicker_'+ litem +'_slider"' + ((o['show'+uitem]) ? '' : noDisplay) + '></div>';
377
378					if (o['show'+uitem] && o[litem+'Grid'] > 0) {
379						html += '<div style="padding-left: 1px"><table class="ui-tpicker-grid-label"><tr>';
380
381						if(litem == 'hour'){
382							for (var h = o[litem+'Min']; h <= max[litem]; h += parseInt(o[litem+'Grid'], 10)) {
383								gridSize[litem]++;
384								var tmph = $.datepicker.formatTime(useAmpm(o.pickerTimeFormat || o.timeFormat)? 'hht':'HH', {hour:h}, o);									
385								html += '<td data-for="'+litem+'">' + tmph + '</td>';
386							}
387						}
388						else{
389							for (var m = o[litem+'Min']; m <= max[litem]; m += parseInt(o[litem+'Grid'], 10)) {
390								gridSize[litem]++;
391								html += '<td data-for="'+litem+'">' + ((m < 10) ? '0' : '') + m + '</td>';
392							}
393						}
394
395						html += '</tr></table></div>';
396					}
397					html += '</dd>';
398				}
399				
400				// Timezone
401				html += '<dt class="ui_tpicker_timezone_label"' + ((o.showTimezone) ? '' : noDisplay) + '>' + o.timezoneText + '</dt>';
402				html += '<dd class="ui_tpicker_timezone" ' + ((o.showTimezone) ? '' : noDisplay) + '></dd>';
403
404				// Create the elements from string
405				html += '</dl></div>';
406				var $tp = $(html);
407
408				// if we only want time picker...
409				if (o.timeOnly === true) {
410					$tp.prepend('<div class="ui-widget-header ui-helper-clearfix ui-corner-all">' + '<div class="ui-datepicker-title">' + o.timeOnlyTitle + '</div>' + '</div>');
411					$dp.find('.ui-datepicker-header, .ui-datepicker-calendar').hide();
412				}
413				
414				// add sliders, adjust grids, add events
415				for(var i=0,l=tp_inst.units.length; i<l; i++){
416					litem = tp_inst.units[i];
417					uitem = litem.substr(0,1).toUpperCase() + litem.substr(1);
418					
419					// add the slider
420					tp_inst[litem+'_slider'] = tp_inst.control.create(tp_inst, $tp.find('.ui_tpicker_'+litem+'_slider'), litem, tp_inst[litem], o[litem+'Min'], max[litem], o['step'+uitem]);
421
422					// adjust the grid and add click event
423					if (o['show'+uitem] && o[litem+'Grid'] > 0) {
424						size = 100 * gridSize[litem] * o[litem+'Grid'] / (max[litem] - o[litem+'Min']);
425						$tp.find('.ui_tpicker_'+litem+' table').css({
426							width: size + "%",
427							marginLeft: o.isRTL? '0' : ((size / (-2 * gridSize[litem])) + "%"),
428							marginRight: o.isRTL? ((size / (-2 * gridSize[litem])) + "%") : '0',
429							borderCollapse: 'collapse'
430						}).find("td").click(function(e){
431								var $t = $(this),
432									h = $t.html(),
433									n = parseInt(h.replace(/[^0-9]/g),10),
434									ap = h.replace(/[^apm]/ig),
435									f = $t.data('for'); // loses scope, so we use data-for
436
437								if(f == 'hour'){
438									if(ap.indexOf('p') !== -1 && n < 12){
439										n += 12;
440									}
441									else{
442										if(ap.indexOf('a') !== -1 && n === 12){
443											n = 0;
444										}
445									}
446								}
447								
448								tp_inst.control.value(tp_inst, tp_inst[f+'_slider'], litem, n);
449
450								tp_inst._onTimeChange();
451								tp_inst._onSelectHandler();
452							})
453						.css({
454								cursor: 'pointer',
455								width: (100 / gridSize[litem]) + '%',
456								textAlign: 'center',
457								overflow: 'hidden'
458							});
459					} // end if grid > 0
460				} // end for loop
461
462				// Add timezone options
463				this.timezone_select = $tp.find('.ui_tpicker_timezone').append('<select></select>').find("select");
464				$.fn.append.apply(this.timezone_select,
465				$.map(o.timezoneList, function(val, idx) {
466					return $("<option />").val(typeof val == "object" ? val.value : val).text(typeof val == "object" ? val.label : val);
467				}));
468				if (typeof(this.timezone) != "undefined" && this.timezone !== null && this.timezone !== "") {
469					var local_date = new Date(this.inst.selectedYear, this.inst.selectedMonth, this.inst.selectedDay, 12);
470					var local_timezone = $.timepicker.timeZoneOffsetString(local_date);
471					if (local_timezone == this.timezone) {
472						selectLocalTimeZone(tp_inst);
473					} else {
474						this.timezone_select.val(this.timezone);
475					}
476				} else {
477					if (typeof(this.hour) != "undefined" && this.hour !== null && this.hour !== "") {
478						this.timezone_select.val(o.defaultTimezone);
479					} else {
480						selectLocalTimeZone(tp_inst);
481					}
482				}
483				this.timezone_select.change(function() {
484					tp_inst._defaults.useLocalTimezone = false;
485					tp_inst._onTimeChange();
486				});
487				// End timezone options
488				
489				// inject timepicker into datepicker
490				var $buttonPanel = $dp.find('.ui-datepicker-buttonpane');
491				if ($buttonPanel.length) {
492					$buttonPanel.before($tp);
493				} else {
494					$dp.append($tp);
495				}
496
497				this.$timeObj = $tp.find('.ui_tpicker_time');
498
499				if (this.inst !== null) {
500					var timeDefined = this.timeDefined;
501					this._onTimeChange();
502					this.timeDefined = timeDefined;
503				}
504
505				// slideAccess integration: http://trentrichardson.com/2011/11/11/jquery-ui-sliders-and-touch-accessibility/
506				if (this._defaults.addSliderAccess) {
507					var sliderAccessArgs = this._defaults.sliderAccessArgs,
508						rtl = this._defaults.isRTL;
509					sliderAccessArgs.isRTL = rtl;
510						
511					setTimeout(function() { // fix for inline mode
512						if ($tp.find('.ui-slider-access').length === 0) {
513							$tp.find('.ui-slider:visible').sliderAccess(sliderAccessArgs);
514
515							// fix any grids since sliders are shorter
516							var sliderAccessWidth = $tp.find('.ui-slider-access:eq(0)').outerWidth(true);
517							if (sliderAccessWidth) {
518								$tp.find('table:visible').each(function() {
519									var $g = $(this),
520										oldWidth = $g.outerWidth(),
521										oldMarginLeft = $g.css(rtl? 'marginRight':'marginLeft').toString().replace('%', ''),
522										newWidth = oldWidth - sliderAccessWidth,
523										newMarginLeft = ((oldMarginLeft * newWidth) / oldWidth) + '%',
524										css = { width: newWidth, marginRight: 0, marginLeft: 0 };
525									css[rtl? 'marginRight':'marginLeft'] = newMarginLeft;
526									$g.css(css);
527								});
528							}
529						}
530					}, 10);
531				}
532				// end slideAccess integration
533
534			}
535		},
536
537		/*
538		* This function tries to limit the ability to go outside the
539		* min/max date range
540		*/
541		_limitMinMaxDateTime: function(dp_inst, adjustSliders) {
542			var o = this._defaults,
543				dp_date = new Date(dp_inst.selectedYear, dp_inst.selectedMonth, dp_inst.selectedDay);
544
545			if (!this._defaults.showTimepicker) {
546				return;
547			} // No time so nothing to check here
548
549			if ($.datepicker._get(dp_inst, 'minDateTime') !== null && $.datepicker._get(dp_inst, 'minDateTime') !== undefined && dp_date) {
550				var minDateTime = $.datepicker._get(dp_inst, 'minDateTime'),
551					minDateTimeDate = new Date(minDateTime.getFullYear(), minDateTime.getMonth(), minDateTime.getDate(), 0, 0, 0, 0);
552
553				if (this.hourMinOriginal === null || this.minuteMinOriginal === null || this.secondMinOriginal === null || this.millisecMinOriginal === null) {
554					this.hourMinOriginal = o.hourMin;
555					this.minuteMinOriginal = o.minuteMin;
556					this.secondMinOriginal = o.secondMin;
557					this.millisecMinOriginal = o.millisecMin;
558				}
559
560				if (dp_inst.settings.timeOnly || minDateTimeDate.getTime() == dp_date.getTime()) {
561					this._defaults.hourMin = minDateTime.getHours();
562					if (this.hour <= this._defaults.hourMin) {
563						this.hour = this._defaults.hourMin;
564						this._defaults.minuteMin = minDateTime.getMinutes();
565						if (this.minute <= this._defaults.minuteMin) {
566							this.minute = this._defaults.minuteMin;
567							this._defaults.secondMin = minDateTime.getSeconds();
568							if (this.second <= this._defaults.secondMin) {
569								this.second = this._defaults.secondMin;
570								this._defaults.millisecMin = minDateTime.getMilliseconds();
571							} else {
572								if (this.millisec < this._defaults.millisecMin) {
573									this.millisec = this._defaults.millisecMin;
574								}
575								this._defaults.millisecMin = this.millisecMinOriginal;
576							}
577						} else {
578							this._defaults.secondMin = this.secondMinOriginal;
579							this._defaults.millisecMin = this.millisecMinOriginal;
580						}
581					} else {
582						this._defaults.minuteMin = this.minuteMinOriginal;
583						this._defaults.secondMin = this.secondMinOriginal;
584						this._defaults.millisecMin = this.millisecMinOriginal;
585					}
586				} else {
587					this._defaults.hourMin = this.hourMinOriginal;
588					this._defaults.minuteMin = this.minuteMinOriginal;
589					this._defaults.secondMin = this.secondMinOriginal;
590					this._defaults.millisecMin = this.millisecMinOriginal;
591				}
592			}
593
594			if ($.datepicker._get(dp_inst, 'maxDateTime') !== null && $.datepicker._get(dp_inst, 'maxDateTime') !== undefined && dp_date) {
595				var maxDateTime = $.datepicker._get(dp_inst, 'maxDateTime'),
596					maxDateTimeDate = new Date(maxDateTime.getFullYear(), maxDateTime.getMonth(), maxDateTime.getDate(), 0, 0, 0, 0);
597
598				if (this.hourMaxOriginal === null || this.minuteMaxOriginal === null || this.secondMaxOriginal === null) {
599					this.hourMaxOriginal = o.hourMax;
600					this.minuteMaxOriginal = o.minuteMax;
601					this.secondMaxOriginal = o.secondMax;
602					this.millisecMaxOriginal = o.millisecMax;
603				}
604
605				if (dp_inst.settings.timeOnly || maxDateTimeDate.getTime() == dp_date.getTime()) {
606					this._defaults.hourMax = maxDateTime.getHours();
607					if (this.hour >= this._defaults.hourMax) {
608						this.hour = this._defaults.hourMax;
609						this._defaults.minuteMax = maxDateTime.getMinutes();
610						if (this.minute >= this._defaults.minuteMax) {
611							this.minute = this._defaults.minuteMax;
612							this._defaults.secondMax = maxDateTime.getSeconds();
613						} else if (this.second >= this._defaults.secondMax) {
614							this.second = this._defaults.secondMax;
615							this._defaults.millisecMax = maxDateTime.getMilliseconds();
616						} else {
617							if (this.millisec > this._defaults.millisecMax) {
618								this.millisec = this._defaults.millisecMax;
619							}
620							this._defaults.millisecMax = this.millisecMaxOriginal;
621						}
622					} else {
623						this._defaults.minuteMax = this.minuteMaxOriginal;
624						this._defaults.secondMax = this.secondMaxOriginal;
625						this._defaults.millisecMax = this.millisecMaxOriginal;
626					}
627				} else {
628					this._defaults.hourMax = this.hourMaxOriginal;
629					this._defaults.minuteMax = this.minuteMaxOriginal;
630					this._defaults.secondMax = this.secondMaxOriginal;
631					this._defaults.millisecMax = this.millisecMaxOriginal;
632				}
633			}
634
635			if (adjustSliders !== undefined && adjustSliders === true) {
636				var hourMax = parseInt((this._defaults.hourMax - ((this._defaults.hourMax - this._defaults.hourMin) % this._defaults.stepHour)), 10),
637					minMax = parseInt((this._defaults.minuteMax - ((this._defaults.minuteMax - this._defaults.minuteMin) % this._defaults.stepMinute)), 10),
638					secMax = parseInt((this._defaults.secondMax - ((this._defaults.secondMax - this._defaults.secondMin) % this._defaults.stepSecond)), 10),
639					millisecMax = parseInt((this._defaults.millisecMax - ((this._defaults.millisecMax - this._defaults.millisecMin) % this._defaults.stepMillisec)), 10);
640
641				if (this.hour_slider) {
642					this.control.options(this, this.hour_slider, 'hour', { min: this._defaults.hourMin, max: hourMax });
643					this.control.value(this, this.hour_slider, 'hour', this.hour);
644				}
645				if (this.minute_slider) {
646					this.control.options(this, this.minute_slider, 'minute', { min: this._defaults.minuteMin, max: minMax });
647					this.control.value(this, this.minute_slider, 'minute', this.minute);
648				}
649				if (this.second_slider) {
650					this.control.options(this, this.second_slider, 'second', { min: this._defaults.secondMin, max: secMax });
651					this.control.value(this, this.second_slider, 'second', this.second);
652				}
653				if (this.millisec_slider) {
654					this.control.options(this, this.millisec_slider, 'millisec', { min: this._defaults.millisecMin, max: millisecMax });
655					this.control.value(this, this.millisec_slider, 'millisec', this.millisec);
656				}
657			}
658
659		},
660
661		/*
662		* when a slider moves, set the internal time...
663		* on time change is also called when the time is updated in the text field
664		*/
665		_onTimeChange: function() {
666			var hour = (this.hour_slider) ? this.control.value(this, this.hour_slider, 'hour') : false,
667				minute = (this.minute_slider) ? this.control.value(this, this.minute_slider, 'minute') : false,
668				second = (this.second_slider) ? this.control.value(this, this.second_slider, 'second') : false,
669				millisec = (this.millisec_slider) ? this.control.value(this, this.millisec_slider, 'millisec') : false,
670				timezone = (this.timezone_select) ? this.timezone_select.val() : false,
671				o = this._defaults,
672				pickerTimeFormat = o.pickerTimeFormat || o.timeFormat,
673				pickerTimeSuffix = o.pickerTimeSuffix || o.timeSuffix;
674
675			if (typeof(hour) == 'object') {
676				hour = false;
677			}
678			if (typeof(minute) == 'object') {
679				minute = false;
680			}
681			if (typeof(second) == 'object') {
682				second = false;
683			}
684			if (typeof(millisec) == 'object') {
685				millisec = false;
686			}
687			if (typeof(timezone) == 'object') {
688				timezone = false;
689			}
690
691			if (hour !== false) {
692				hour = parseInt(hour, 10);
693			}
694			if (minute !== false) {
695				minute = parseInt(minute, 10);
696			}
697			if (second !== false) {
698				second = parseInt(second, 10);
699			}
700			if (millisec !== false) {
701				millisec = parseInt(millisec, 10);
702			}
703
704			var ampm = o[hour < 12 ? 'amNames' : 'pmNames'][0];
705
706			// If the update was done in the input field, the input field should not be updated.
707			// If the update was done using the sliders, update the input field.
708			var hasChanged = (hour != this.hour || minute != this.minute || second != this.second || millisec != this.millisec 
709								|| (this.ampm.length > 0 && (hour < 12) != ($.inArray(this.ampm.toUpperCase(), this.amNames) !== -1)) 
710								|| ((this.timezone === null && timezone != this.defaultTimezone) || (this.timezone !== null && timezone != this.timezone)));
711
712			if (hasChanged) {
713
714				if (hour !== false) {
715					this.hour = hour;
716				}
717				if (minute !== false) {
718					this.minute = minute;
719				}
720				if (second !== false) {
721					this.second = second;
722				}
723				if (millisec !== false) {
724					this.millisec = millisec;
725				}
726				if (timezone !== false) {
727					this.timezone = timezone;
728				}
729
730				if (!this.inst) {
731					this.inst = $.datepicker._getInst(this.$input[0]);
732				}
733
734				this._limitMinMaxDateTime(this.inst, true);
735			}
736			if (useAmpm(o.timeFormat)) {
737				this.ampm = ampm;
738			}
739
740			// Updates the time within the timepicker
741			this.formattedTime = $.datepicker.formatTime(o.timeFormat, this, o);
742			if (this.$timeObj) {
743				if(pickerTimeFormat === o.timeFormat){
744					this.$timeObj.text(this.formattedTime + pickerTimeSuffix);
745				}
746				else{
747					this.$timeObj.text($.datepicker.formatTime(pickerTimeFormat, this, o) + pickerTimeSuffix);
748				}
749			}
750
751			this.timeDefined = true;
752			if (hasChanged) {
753				this._updateDateTime();
754			}
755		},
756
757		/*
758		* call custom onSelect.
759		* bind to sliders slidestop, and grid click.
760		*/
761		_onSelectHandler: function() {
762			var onSelect = this._defaults.onSelect || this.inst.settings.onSelect;
763			var inputEl = this.$input ? this.$input[0] : null;
764			if (onSelect && inputEl) {
765				onSelect.apply(inputEl, [this.formattedDateTime, this]);
766			}
767		},
768
769		/*
770		* update our input with the new date time..
771		*/
772		_updateDateTime: function(dp_inst) {
773			dp_inst = this.inst || dp_inst;
774			var dt = $.datepicker._daylightSavingAdjust(new Date(dp_inst.selectedYear, dp_inst.selectedMonth, dp_inst.selectedDay)),
775				dateFmt = $.datepicker._get(dp_inst, 'dateFormat'),
776				formatCfg = $.datepicker._getFormatConfig(dp_inst),
777				timeAvailable = dt !== null && this.timeDefined;
778			this.formattedDate = $.datepicker.formatDate(dateFmt, (dt === null ? new Date() : dt), formatCfg);
779			var formattedDateTime = this.formattedDate;
780
781			/*
782			* remove following lines to force every changes in date picker to change the input value
783			* Bug descriptions: when an input field has a default value, and click on the field to pop up the date picker. 
784			* If the user manually empty the value in the input field, the date picker will never change selected value.
785			*/
786			//if (dp_inst.lastVal !== undefined && (dp_inst.lastVal.length > 0 && this.$input.val().length === 0)) {
787			//	return;
788			//}
789
790			if (this._defaults.timeOnly === true) {
791				formattedDateTime = this.formattedTime;
792			} else if (this._defaults.timeOnly !== true && (this._defaults.alwaysSetTime || timeAvailable)) {
793				formattedDateTime += this._defaults.separator + this.formattedTime + this._defaults.timeSuffix;
794			}
795
796			this.formattedDateTime = formattedDateTime;
797
798			if (!this._defaults.showTimepicker) {
799				this.$input.val(this.formattedDate);
800			} else if (this.$altInput && this._defaults.altFieldTimeOnly === true) {
801				this.$altInput.val(this.formattedTime);
802				this.$input.val(this.formattedDate);
803			} else if (this.$altInput) {
804				this.$input.val(formattedDateTime);
805				var altFormattedDateTime = '',
806					altSeparator = this._defaults.altSeparator ? this._defaults.altSeparator : this._defaults.separator,
807					altTimeSuffix = this._defaults.altTimeSuffix ? this._defaults.altTimeSuffix : this._defaults.timeSuffix;
808
809				if (this._defaults.altFormat) altFormattedDateTime = $.datepicker.formatDate(this._defaults.altFormat, (dt === null ? new Date() : dt), formatCfg);
810				else altFormattedDateTime = this.formattedDate;
811				if (altFormattedDateTime) altFormattedDateTime += altSeparator;
812				if (this._defaults.altTimeFormat) altFormattedDateTime += $.datepicker.formatTime(this._defaults.altTimeFormat, this, this._defaults) + altTimeSuffix;
813				else altFormattedDateTime += this.formattedTime + altTimeSuffix;
814				this.$altInput.val(altFormattedDateTime);
815			} else {
816				this.$input.val(formattedDateTime);
817			}
818
819			this.$input.trigger("change");
820		},
821
822		_onFocus: function() {
823			if (!this.$input.val() && this._defaults.defaultValue) {
824				this.$input.val(this._defaults.defaultValue);
825				var inst = $.datepicker._getInst(this.$input.get(0)),
826					tp_inst = $.datepicker._get(inst, 'timepicker');
827				if (tp_inst) {
828					if (tp_inst._defaults.timeOnly && (inst.input.val() != inst.lastVal)) {
829						try {
830							$.datepicker._updateDatepicker(inst);
831						} catch (err) {
832							$.datepicker.log(err);
833						}
834					}
835				}
836			}
837		},
838
839		/*
840		* Small abstraction to control types
841		* We can add more, just be sure to follow the pattern: create, options, value
842		*/
843		_controls: {
844			// slider methods
845			slider: {
846				create: function(tp_inst, obj, unit, val, min, max, step){
847					var rtl = tp_inst._defaults.isRTL; // if rtl go -60->0 instead of 0->60
848					return obj.prop('slide', null).slider({
849						orientation: "horizontal",
850						value: rtl? val*-1 : val,
851						min: rtl? max*-1 : min,
852						max: rtl? min*-1 : max,
853						step: step,
854						slide: function(event, ui) {
855							tp_inst.control.value(tp_inst, $(this), unit, rtl? ui.value*-1:ui.value);
856							tp_inst._onTimeChange();
857						},
858						stop: function(event, ui) {
859							tp_inst._onSelectHandler();
860						}
861					});	
862				},
863				options: function(tp_inst, obj, unit, opts, val){
864					if(tp_inst._defaults.isRTL){
865						if(typeof(opts) == 'string'){
866							if(opts == 'min' || opts == 'max'){
867								if(val !== undefined)
868									return obj.slider(opts, val*-1);
869								return Math.abs(obj.slider(opts));
870							}
871							return obj.slider(opts);
872						}
873						var min = opts.min, 
874							max = opts.max;
875						opts.min = opts.max = null;
876						if(min !== undefined)
877							opts.max = min * -1;
878						if(max !== undefined)
879							opts.min = max * -1;
880						return obj.slider(opts);
881					}
882					if(typeof(opts) == 'string' && val !== undefined)
883							return obj.slider(opts, val);
884					return obj.slider(opts);
885				},
886				value: function(tp_inst, obj, unit, val){
887					if(tp_inst._defaults.isRTL){
888						if(val !== undefined)
889							return obj.slider('value', val*-1);
890						return Math.abs(obj.slider('value'));
891					}
892					if(val !== undefined)
893						return obj.slider('value', val);
894					return obj.slider('value');
895				}
896			},
897			// select methods
898			select: {
899				create: function(tp_inst, obj, unit, val, min, max, step){
900					var sel = '<select class="ui-timepicker-select" data-unit="'+ unit +'" data-min="'+ min +'" data-max="'+ max +'" data-step="'+ step +'">',
901						ul = tp_inst._defaults.timeFormat.indexOf('t') !== -1? 'toLowerCase':'toUpperCase',
902						m = 0;
903
904					for(var i=min; i<=max; i+=step){						
905						sel += '<option value="'+ i +'"'+ (i==val? ' selected':'') +'>';
906						if(unit == 'hour' && useAmpm(tp_inst._defaults.pickerTimeFormat || tp_inst._defaults.timeFormat))
907							sel += $.datepicker.formatTime("hh TT", {hour:i}, tp_inst._defaults);
908						else if(unit == 'millisec' || i >= 10) sel += i;
909						else sel += '0'+ i.toString();
910						sel += '</option>';
911					}
912					sel += '</select>';
913
914					obj.children('select').remove();
915
916					$(sel).appendTo(obj).change(function(e){
917						tp_inst._onTimeChange();
918						tp_inst._onSelectHandler();
919					});
920
921					return obj;
922				},
923				options: function(tp_inst, obj, unit, opts, val){
924					var o = {},
925						$t = obj.children('select');
926					if(typeof(opts) == 'string'){
927						if(val === undefined)
928							return $t.data(opts);
929						o[opts] = val;	
930					}
931					else o = opts;
932					return tp_inst.control.create(tp_inst, obj, $t.data('unit'), $t.val(), o.min || $t.data('min'), o.max || $t.data('max'), o.step || $t.data('step'));
933				},
934				value: function(tp_inst, obj, unit, val){
935					var $t = obj.children('select');
936					if(val !== undefined)
937						return $t.val(val);
938					return $t.val();
939				}
940			}
941		} // end _controls
942
943	});
944
945	$.fn.extend({
946		/*
947		* shorthand just to use timepicker..
948		*/
949		timepicker: function(o) {
950			o = o || {};
951			var tmp_args = Array.prototype.slice.call(arguments);
952
953			if (typeof o == 'object') {
954				tmp_args[0] = $.extend(o, {
955					timeOnly: true
956				});
957			}
958
959			return $(this).each(function() {
960				$.fn.datetimepicker.apply($(this), tmp_args);
961			});
962		},
963
964		/*
965		* extend timepicker to datepicker
966		*/
967		datetimepicker: function(o) {
968			o = o || {};
969			var tmp_args = arguments;
970
971			if (typeof(o) == 'string') {
972				if (o == 'getDate') {
973					return $.fn.datepicker.apply($(this[0]), tmp_args);
974				} else {
975					return this.each(function() {
976						var $t = $(this);
977						$t.datepicker.apply($t, tmp_args);
978					});
979				}
980			} else {
981				return this.each(function() {
982					var $t = $(this);
983					$t.datepicker($.timepicker._newInst($t, o)._defaults);
984				});
985			}
986		}
987	});
988
989	/*
990	* Public Utility to parse date and time
991	*/
992	$.datepicker.parseDateTime = function(dateFormat, timeFormat, dateTimeString, dateSettings, timeSettings) {
993		var parseRes = parseDateTimeInternal(dateFormat, timeFormat, dateTimeString, dateSettings, timeSettings);
994		if (parseRes.timeObj) {
995			var t = parseRes.timeObj;
996			parseRes.date.setHours(t.hour, t.minute, t.second, t.millisec);
997		}
998
999		return parseRes.date;
1000	};
1001
1002	/*
1003	* Public utility to parse time
1004	*/
1005	$.datepicker.parseTime = function(timeFormat, timeString, options) {		
1006		var o = extendRemove(extendRemove({}, $.timepicker._defaults), options || {});
1007
1008		// Strict parse requires the timeString to match the timeFormat exactly
1009		var strictParse = function(f, s, o){
1010
1011			// pattern for standard and localized AM/PM markers
1012			var getPatternAmpm = function(amNames, pmNames) {
1013				var markers = [];
1014				if (amNames) {
1015					$.merge(markers, amNames);
1016				}
1017				if (pmNames) {
1018					$.merge(markers, pmNames);
1019				}
1020				markers = $.map(markers, function(val) {
1021					return val.replace(/[.*+?|()\[\]{}\\]/g, '\\$&');
1022				});
1023				return '(' + markers.join('|') + ')?';
1024			};
1025
1026			// figure out position of time elements.. cause js cant do named captures
1027			var getFormatPositions = function(timeFormat) {
1028				var finds = timeFormat.toLowerCase().match(/(h{1,2}|m{1,2}|s{1,2}|l{1}|t{1,2}|z|'.*?')/g),
1029					orders = {
1030						h: -1,
1031						m: -1,
1032						s: -1,
1033						l: -1,
1034						t: -1,
1035						z: -1
1036					};
1037
1038				if (finds) {
1039					for (var i = 0; i < finds.length; i++) {
1040						if (orders[finds[i].toString().charAt(0)] == -1) {
1041							orders[finds[i].toString().charAt(0)] = i + 1;
1042						}
1043					}
1044				}
1045				return orders;
1046			};
1047
1048			var regstr = '^' + f.toString()
1049					.replace(/([hH]{1,2}|mm?|ss?|[tT]{1,2}|[lz]|'.*?')/g, function (match) {
1050							switch (match.charAt(0).toLowerCase()) {
1051								case 'h': return '(\\d?\\d)';
1052								case 'm': return '(\\d?\\d)';
1053								case 's': return '(\\d?\\d)';
1054								case 'l': return '(\\d?\\d?\\d)';
1055								case 'z': return '(z|[-+]\\d\\d:?\\d\\d|\\S+)?';
1056								case 't': return getPatternAmpm(o.amNames, o.pmNames);
1057								default:    // literal escaped in quotes
1058									return '(' + match.replace(/\'/g, "").replace(/(\.|\$|\^|\\|\/|\(|\)|\[|\]|\?|\+|\*)/g, function (m) { return "\\" + m; }) + ')?';
1059							}
1060						})
1061					.replace(/\s/g, '\\s?') +
1062					o.timeSuffix + '$',
1063				order = getFormatPositions(f),
1064				ampm = '',
1065				treg;
1066
1067			treg = s.match(new RegExp(regstr, 'i'));
1068
1069			var resTime = {
1070				hour: 0,
1071				minute: 0,
1072				second: 0,
1073				millisec: 0
1074			};
1075
1076			if (treg) {
1077				if (order.t !== -1) {
1078					if (treg[order.t] === undefined || treg[order.t].length === 0) {
1079						ampm = '';
1080						resTime.ampm = '';
1081					} else {
1082						ampm = $.inArray(treg[order.t].toUpperCase(), o.amNames) !== -1 ? 'AM' : 'PM';
1083						resTime.ampm = o[ampm == 'AM' ? 'amNames' : 'pmNames'][0];
1084					}
1085				}
1086
1087				if (order.h !== -1) {
1088					if (ampm == 'AM' && treg[order.h] == '12') {
1089						resTime.hour = 0; // 12am = 0 hour
1090					} else {
1091						if (ampm == 'PM' && treg[order.h] != '12') {
1092							resTime.hour = parseInt(treg[order.h], 10) + 12; // 12pm = 12 hour, any other pm = hour + 12
1093						} else {
1094							resTime.hour = Number(treg[order.h]);
1095						}
1096					}
1097				}
1098
1099				if (order.m !== -1) {
1100					resTime.minute = Number(treg[order.m]);
1101				}
1102				if (order.s !== -1) {
1103					resTime.second = Number(treg[order.s]);
1104				}
1105				if (order.l !== -1) {
1106					resTime.millisec = Number(treg[order.l]);
1107				}
1108				if (order.z !== -1 && treg[order.z] !== undefined) {
1109					var tz = treg[order.z].toUpperCase();
1110					switch (tz.length) {
1111					case 1:
1112						// Z
1113						tz = o.timezoneIso8601 ? 'Z' : '+0000';
1114						break;
1115					case 5:
1116						// +hhmm
1117						if (o.timezoneIso8601) {
1118							tz = tz.substring(1) == '0000' ? 'Z' : tz.substring(0, 3) + ':' + tz.substring(3);
1119						}
1120						break;
1121					case 6:
1122						// +hh:mm
1123						if (!o.timezoneIso8601) {
1124							tz = tz == 'Z' || tz.substring(1) == '00:00' ? '+0000' : tz.replace(/:/, '');
1125						} else {
1126							if (tz.substring(1) == '00:00') {
1127								tz = 'Z';
1128							}
1129						}
1130						break;
1131					}
1132					resTime.timezone = tz;
1133				}
1134
1135
1136				return resTime;
1137			}
1138			return false;
1139		};// end strictParse
1140
1141		// First try JS Date, if that fails, use strictParse
1142		var looseParse = function(f,s,o){
1143			try{
1144				var d = new Date('2012-01-01 '+ s);
1145				return {
1146					hour: d.getHours(),
1147					minutes: d.getMinutes(),
1148					seconds: d.getSeconds(),
1149					millisec: d.getMilliseconds(),
1150					timezone: $.timepicker.timeZoneOffsetString(d)
1151				};
1152			}
1153			catch(err){
1154				try{
1155					return strictParse(f,s,o);
1156				}
1157				catch(err2){
1158					$.datepicker.log("Unable to parse \ntimeString: "+ s +"\ntimeFormat: "+ f);
1159				}				
1160			}
1161			return false;
1162		}; // end looseParse
1163		
1164		if(typeof o.parse === "function"){
1165			return o.parse(timeFormat, timeString, o)
1166		}
1167		if(o.parse === 'loose'){
1168			return looseParse(timeFormat, timeString, o);
1169		}
1170		return strictParse(timeFormat, timeString, o);
1171	};
1172
1173	/*
1174	* Public utility to format the time
1175	* format = string format of the time
1176	* time = a {}, not a Date() for timezones
1177	* options = essentially the regional[].. amNames, pmNames, ampm
1178	*/
1179	$.datepicker.formatTime = function(format, time, options) {
1180		options = options || {};
1181		options = $.extend({}, $.timepicker._defaults, options);
1182		time = $.extend({
1183			hour: 0,
1184			minute: 0,
1185			second: 0,
1186			millisec: 0,
1187			timezone: '+0000'
1188		}, time);
1189
1190		var tmptime = format,
1191			ampmName = options.amNames[0],
1192			hour = parseInt(time.hour, 10);
1193
1194		if (hour > 11) {
1195			ampmName = options.pmNames[0];
1196		}
1197
1198		tmptime = tmptime.replace(/(?:HH?|hh?|mm?|ss?|[tT]{1,2}|[lz]|('.*?'|".*?"))/g, function(match) {
1199		switch (match) {
1200			case 'HH':
1201				return ('0' + hour).slice(-2);
1202			case 'H':
1203				return hour;
1204			case 'hh':
1205				return ('0' + convert24to12(hour)).slice(-2);
1206			case 'h':
1207				return convert24to12(hour);
1208			case 'mm':
1209				return ('0' + time.minute).slice(-2);
1210			case 'm':
1211				return time.minute;
1212			case 'ss':
1213				return ('0' + time.second).slice(-2);
1214			case 's':
1215				return time.second;
1216			case 'l':
1217				return ('00' + time.millisec).slice(-3);
1218			case 'z':
1219				return time.timezone === null? options.defaultTimezone : time.timezone;
1220			case 'T': 
1221				return ampmName.charAt(0).toUpperCase();
1222			case 'TT': 
1223				return ampmName.toUpperCase();
1224			case 't':
1225				return ampmName.charAt(0).toLowerCase();
1226			case 'tt':
1227				return ampmName.toLowerCase();
1228			default:
1229				return match.replace(/\'/g, "") || "'";
1230			}
1231		});
1232
1233		tmptime = $.trim(tmptime);
1234		return tmptime;
1235	};
1236
1237	/*
1238	* the bad hack :/ override datepicker so it doesnt close on select
1239	// inspired: http://stackoverflow.com/questions/1252512/jquery-datepicker-prevent-closing-picker-when-clicking-a-date/1762378#1762378
1240	*/
1241	$.datepicker._base_selectDate = $.datepicker._selectDate;
1242	$.datepicker._selectDate = function(id, dateStr) {
1243		var inst = this._getInst($(id)[0]),
1244			tp_inst = this._get(inst, 'timepicker');
1245
1246		if (tp_inst) {
1247			tp_inst._limitMinMaxDateTime(inst, true);
1248			inst.inline = inst.stay_open = true;
1249			//This way the onSelect handler called from calendarpicker get the full dateTime
1250			this._base_selectDate(id, dateStr);
1251			inst.inline = inst.stay_open = false;
1252			this._notifyChange(inst);
1253			this._updateDatepicker(inst);
1254		} else {
1255			this._base_selectDate(id, dateStr);
1256		}
1257	};
1258
1259	/*
1260	* second bad hack :/ override datepicker so it triggers an event when changing the input field
1261	* and does not redraw the datepicker on every selectDate event
1262	*/
1263	$.datepicker._base_updateDatepicker = $.datepicker._updateDatepicker;
1264	$.datepicker._updateDatepicker = function(inst) {
1265
1266		// don't popup the datepicker if there is another instance already opened
1267		var input = inst.input[0];
1268		if ($.datepicker._curInst && $.datepicker._curInst != inst && $.datepicker._datepickerShowing && $.datepicker._lastInput != input) {
1269			return;
1270		}
1271
1272		if (typeof(inst.stay_open) !== 'boolean' || inst.stay_open === false) {
1273
1274			this._base_updateDatepicker(inst);
1275
1276			// Reload the time control when changing something in the input text field.
1277			var tp_inst = this._get(inst, 'timepicker');
1278			if (tp_inst) {
1279				tp_inst._addTimePicker(inst);
1280
vendor: 11,635 bytes, lines 1281-1642
1281				if (tp_inst._defaults.useLocalTimezone) { //checks daylight saving with the new date.
1282					var date = new Date(inst.selectedYear, inst.selectedMonth, inst.selectedDay, 12);
1283					selectLocalTimeZone(tp_inst, date);
1284					tp_inst._onTimeChange();
1285				}
1286			}
1287		}
1288	};
1289
1290	/*
1291	* third bad hack :/ override datepicker so it allows spaces and colon in the input field
1292	*/
1293	$.datepicker._base_doKeyPress = $.datepicker._doKeyPress;
1294	$.datepicker._doKeyPress = function(event) {
1295		var inst = $.datepicker._getInst(event.target),
1296			tp_inst = $.datepicker._get(inst, 'timepicker');
1297
1298		if (tp_inst) {
1299			if ($.datepicker._get(inst, 'constrainInput')) {
1300				var ampm = useAmpm(tp_inst._defaults.timeFormat),
1301					dateChars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat')),
1302					datetimeChars = tp_inst._defaults.timeFormat.toString()
1303											.replace(/[hms]/g, '')
1304											.replace(/TT/g, ampm ? 'APM' : '')
1305											.replace(/Tt/g, ampm ? 'AaPpMm' : '')
1306											.replace(/tT/g, ampm ? 'AaPpMm' : '')
1307											.replace(/T/g, ampm ? 'AP' : '')
1308											.replace(/tt/g, ampm ? 'apm' : '')
1309											.replace(/t/g, ampm ? 'ap' : '') + 
1310											" " + tp_inst._defaults.separator + 
1311											tp_inst._defaults.timeSuffix + 
1312											(tp_inst._defaults.showTimezone ? tp_inst._defaults.timezoneList.join('') : '') + 
1313											(tp_inst._defaults.amNames.join('')) + (tp_inst._defaults.pmNames.join('')) + 
1314											dateChars,
1315					chr = String.fromCharCode(event.charCode === undefined ? event.keyCode : event.charCode);
1316				return event.ctrlKey || (chr < ' ' || !dateChars || datetimeChars.indexOf(chr) > -1);
1317			}
1318		}
1319
1320		return $.datepicker._base_doKeyPress(event);
1321	};
1322
1323	/*
1324	* Fourth bad hack :/ override _updateAlternate function used in inline mode to init altField
1325	*/
1326	$.datepicker._base_updateAlternate = $.datepicker._updateAlternate;
1327	/* Update any alternate field to synchronise with the main field. */
1328	$.datepicker._updateAlternate = function(inst) {
1329		var tp_inst = this._get(inst, 'timepicker');
1330		if(tp_inst){
1331			var altField = tp_inst._defaults.altField;
1332			if (altField) { // update alternate field too
1333				var altFormat = tp_inst._defaults.altFormat || tp_inst._defaults.dateFormat,
1334					date = this._getDate(inst),
1335					formatCfg = $.datepicker._getFormatConfig(inst),
1336					altFormattedDateTime = '', 
1337					altSeparator = tp_inst._defaults.altSeparator ? tp_inst._defaults.altSeparator : tp_inst._defaults.separator, 
1338					altTimeSuffix = tp_inst._defaults.altTimeSuffix ? tp_inst._defaults.altTimeSuffix : tp_inst._defaults.timeSuffix,
1339					altTimeFormat = tp_inst._defaults.altTimeFormat !== null ? tp_inst._defaults.altTimeFormat : tp_inst._defaults.timeFormat;
1340				
1341				altFormattedDateTime += $.datepicker.formatTime(altTimeFormat, tp_inst, tp_inst._defaults) + altTimeSuffix;
1342				if(!tp_inst._defaults.timeOnly && !tp_inst._defaults.altFieldTimeOnly){
1343					if(tp_inst._defaults.altFormat)
1344						altFormattedDateTime = $.datepicker.formatDate(tp_inst._defaults.altFormat, (date === null ? new Date() : date), formatCfg) + altSeparator + altFormattedDateTime;
1345					else altFormattedDateTime = tp_inst.formattedDate + altSeparator + altFormattedDateTime;
1346				}
1347				$(altField).val(altFormattedDateTime);
1348			}
1349		}
1350		else{
1351			$.datepicker._base_updateAlternate(inst);
1352		}
1353	};
1354
1355	/*
1356	* Override key up event to sync manual input changes.
1357	*/
1358	$.datepicker._base_doKeyUp = $.datepicker._doKeyUp;
1359	$.datepicker._doKeyUp = function(event) {
1360		var inst = $.datepicker._getInst(event.target),
1361			tp_inst = $.datepicker._get(inst, 'timepicker');
1362
1363		if (tp_inst) {
1364			if (tp_inst._defaults.timeOnly && (inst.input.val() != inst.lastVal)) {
1365				try {
1366					$.datepicker._updateDatepicker(inst);
1367				} catch (err) {
1368					$.datepicker.log(err);
1369				}
1370			}
1371		}
1372
1373		return $.datepicker._base_doKeyUp(event);
1374	};
1375
1376	/*
1377	* override "Today" button to also grab the time.
1378	*/
1379	$.datepicker._base_gotoToday = $.datepicker._gotoToday;
1380	$.datepicker._gotoToday = function(id) {
1381		var inst = this._getInst($(id)[0]),
1382			$dp = inst.dpDiv;
1383		this._base_gotoToday(id);
1384		var tp_inst = this._get(inst, 'timepicker');
1385		selectLocalTimeZone(tp_inst);
1386		var now = new Date();
1387		this._setTime(inst, now);
1388		$('.ui-datepicker-today', $dp).click();
1389	};
1390
1391	/*
1392	* Disable & enable the Time in the datetimepicker
1393	*/
1394	$.datepicker._disableTimepickerDatepicker = function(target) {
1395		var inst = this._getInst(target);
1396		if (!inst) {
1397			return;
1398		}
1399
1400		var tp_inst = this._get(inst, 'timepicker');
1401		$(target).datepicker('getDate'); // Init selected[Year|Month|Day]
1402		if (tp_inst) {
1403			tp_inst._defaults.showTimepicker = false;
1404			tp_inst._updateDateTime(inst);
1405		}
1406	};
1407
1408	$.datepicker._enableTimepickerDatepicker = function(target) {
1409		var inst = this._getInst(target);
1410		if (!inst) {
1411			return;
1412		}
1413
1414		var tp_inst = this._get(inst, 'timepicker');
1415		$(target).datepicker('getDate'); // Init selected[Year|Month|Day]
1416		if (tp_inst) {
1417			tp_inst._defaults.showTimepicker = true;
1418			tp_inst._addTimePicker(inst); // Could be disabled on page load
1419			tp_inst._updateDateTime(inst);
1420		}
1421	};
1422
1423	/*
1424	* Create our own set time function
1425	*/
1426	$.datepicker._setTime = function(inst, date) {
1427		var tp_inst = this._get(inst, 'timepicker');
1428		if (tp_inst) {
1429			var defaults = tp_inst._defaults;
1430
1431			// calling _setTime with no date sets time to defaults
1432			tp_inst.hour = date ? date.getHours() : defaults.hour;
1433			tp_inst.minute = date ? date.getMinutes() : defaults.minute;
1434			tp_inst.second = date ? date.getSeconds() : defaults.second;
1435			tp_inst.millisec = date ? date.getMilliseconds() : defaults.millisec;
1436
1437			//check if within min/max times.. 
1438			tp_inst._limitMinMaxDateTime(inst, true);
1439
1440			tp_inst._onTimeChange();
1441			tp_inst._updateDateTime(inst);
1442		}
1443	};
1444
1445	/*
1446	* Create new public method to set only time, callable as $().datepicker('setTime', date)
1447	*/
1448	$.datepicker._setTimeDatepicker = function(target, date, withDate) {
1449		var inst = this._getInst(target);
1450		if (!inst) {
1451			return;
1452		}
1453
1454		var tp_inst = this._get(inst, 'timepicker');
1455
1456		if (tp_inst) {
1457			this._setDateFromField(inst);
1458			var tp_date;
1459			if (date) {
1460				if (typeof date == "string") {
1461					tp_inst._parseTime(date, withDate);
1462					tp_date = new Date();
1463					tp_date.setHours(tp_inst.hour, tp_inst.minute, tp_inst.second, tp_inst.millisec);
1464				} else {
1465					tp_date = new Date(date.getTime());
1466				}
1467				if (tp_date.toString() == 'Invalid Date') {
1468					tp_date = undefined;
1469				}
1470				this._setTime(inst, tp_date);
1471			}
1472		}
1473
1474	};
1475
1476	/*
1477	* override setDate() to allow setting time too within Date object
1478	*/
1479	$.datepicker._base_setDateDatepicker = $.datepicker._setDateDatepicker;
1480	$.datepicker._setDateDatepicker = function(target, date) {
1481		var inst = this._getInst(target);
1482		if (!inst) {
1483			return;
1484		}
1485
1486		var tp_date = (date instanceof Date) ? new Date(date.getTime()) : date;
1487
1488		this._updateDatepicker(inst);
1489		this._base_setDateDatepicker.apply(this, arguments);
1490		this._setTimeDatepicker(target, tp_date, true);
1491	};
1492
1493	/*
1494	* override getDate() to allow getting time too within Date object
1495	*/
1496	$.datepicker._base_getDateDatepicker = $.datepicker._getDateDatepicker;
1497	$.datepicker._getDateDatepicker = function(target, noDefault) {
1498		var inst = this._getInst(target);
1499		if (!inst) {
1500			return;
1501		}
1502
1503		var tp_inst = this._get(inst, 'timepicker');
1504
1505		if (tp_inst) {
1506			// if it hasn't yet been defined, grab from field
1507			if(inst.lastVal === undefined){
1508				this._setDateFromField(inst, noDefault);
1509			}
1510
1511			var date = this._getDate(inst);
1512			if (date && tp_inst._parseTime($(target).val(), tp_inst.timeOnly)) {
1513				date.setHours(tp_inst.hour, tp_inst.minute, tp_inst.second, tp_inst.millisec);
1514			}
1515			return date;
1516		}
1517		return this._base_getDateDatepicker(target, noDefault);
1518	};
1519
1520	/*
1521	* override parseDate() because UI 1.8.14 throws an error about "Extra characters"
1522	* An option in datapicker to ignore extra format characters would be nicer.
1523	*/
1524	$.datepicker._base_parseDate = $.datepicker.parseDate;
1525	$.datepicker.parseDate = function(format, value, settings) {
1526		var date;
1527		try {
1528			date = this._base_parseDate(format, value, settings);
1529		} catch (err) {
1530			// Hack!  The error message ends with a colon, a space, and
1531			// the "extra" characters.  We rely on that instead of
1532			// attempting to perfectly reproduce the parsing algorithm.
1533			date = this._base_parseDate(format, value.substring(0,value.length-(err.length-err.indexOf(':')-2)), settings);
1534			$.datepicker.log("Error parsing the date string: " + err + "\ndate string = " + value + "\ndate format = " + format);
1535		}
1536		return date;
1537	};
1538
1539	/*
1540	* override formatDate to set date with time to the input
1541	*/
1542	$.datepicker._base_formatDate = $.datepicker._formatDate;
1543	$.datepicker._formatDate = function(inst, day, month, year) {
1544		var tp_inst = this._get(inst, 'timepicker');
1545		if (tp_inst) {
1546			tp_inst._updateDateTime(inst);
1547			return tp_inst.$input.val();
1548		}
1549		return this._base_formatDate(inst);
1550	};
1551
1552	/*
1553	* override options setter to add time to maxDate(Time) and minDate(Time). MaxDate
1554	*/
1555	$.datepicker._base_optionDatepicker = $.datepicker._optionDatepicker;
1556	$.datepicker._optionDatepicker = function(target, name, value) {
1557		var inst = this._getInst(target),
1558			name_clone;
1559		if (!inst) {
1560			return null;
1561		}
1562
1563		var tp_inst = this._get(inst, 'timepicker');
1564		if (tp_inst) {
1565			var min = null,
1566				max = null,
1567				onselect = null,
1568				overrides = tp_inst._defaults.evnts,
1569				fns = {},
1570				prop;
1571			if (typeof name == 'string') { // if min/max was set with the string
1572				if (name === 'minDate' || name === 'minDateTime') {
1573					min = value;
1574				} else if (name === 'maxDate' || name === 'maxDateTime') {
1575					max = value;
1576				} else if (name === 'onSelect') {
1577					onselect = value;
1578				} else if (overrides.hasOwnProperty(name)) {
1579					if (typeof (value) === 'undefined') {
1580						return overrides[name];
1581					}
1582					fns[name] = value;
1583					name_clone = {}; //empty results in exiting function after overrides updated
1584				}
1585			} else if (typeof name == 'object') { //if min/max was set with the JSON
1586				if (name.minDate) {
1587					min = name.minDate;
1588				} else if (name.minDateTime) {
1589					min = name.minDateTime;
1590				} else if (name.maxDate) {
1591					max = name.maxDate;
1592				} else if (name.maxDateTime) {
1593					max = name.maxDateTime;
1594				}
1595				for (prop in overrides) {
1596					if (overrides.hasOwnProperty(prop) && name[prop]) {
1597						fns[prop] = name[prop];
1598					}
1599				}
1600			}
1601			for (prop in fns) {
1602				if (fns.hasOwnProperty(prop)) {
1603					overrides[prop] = fns[prop];
1604					if (!name_clone) { name_clone = $.extend({}, name);}
1605					delete name_clone[prop];
1606				}
1607			}
1608			if (name_clone && isEmptyObject(name_clone)) { return; }
1609			if (min) { //if min was set
1610				if (min === 0) {
1611					min = new Date();
1612				} else {
1613					min = new Date(min);
1614				}
1615				tp_inst._defaults.minDate = min;
1616				tp_inst._defaults.minDateTime = min;
1617			} else if (max) { //if max was set
1618				if (max === 0) {
1619					max = new Date();
1620				} else {
1621					max = new Date(max);
1622				}
1623				tp_inst._defaults.maxDate = max;
1624				tp_inst._defaults.maxDateTime = max;
1625			} else if (onselect) {
1626				tp_inst._defaults.onSelect = onselect;
1627			}
1628		}
1629		if (value === undefined) {
1630			return this._base_optionDatepicker.call($.datepicker, target, name);
1631		}
1632		return this._base_optionDatepicker.call($.datepicker, target, name_clone || name, value);
1633	};
1634	/*
1635	* jQuery isEmptyObject does not check hasOwnProperty - if someone has added to the object prototype,
1636	* it will return false for all objects
1637	*/
1638	var isEmptyObject = function(obj) {
1639		var prop;
1640		for (prop in obj) {
1641			if (obj.hasOwnProperty(obj)) {
1642				return false;
1643			}
1644		}
1645		return true;
1646	};
1647
1648	/*
1649	* jQuery extend now ignores nulls!
1650	*/
1651	var extendRemove = function(target, props) {
1652		$.extend(target, props);
1653		for (var name in props) {
1654			if (props[name] === null || props[name] === undefined) {
1655				target[name] = props[name];
1656			}
1657		}
1658		return target;
1659	};
1660
1661	/*
1662	* Determine by the time format if should use ampm
1663	* Returns true if should use ampm, false if not
1664	*/
1665	var useAmpm = function(timeFormat){
1666		return (timeFormat.indexOf('t') !== -1 && timeFormat.indexOf('h') !== -1);
1667	};
1668
1669	/*
1670	* Converts 24 hour format into 12 hour
1671	* Returns 12 hour without leading 0
1672	*/
1673	var convert24to12 = function(hour) {
1674		if (hour > 12) {
1675			hour = hour - 12;
1676		}
1677
1678		if (hour == 0) {
1679			hour = 12;
1680		}
1681
1682		return String(hour);
1683	};
1684
1685	/*
1686	* Splits datetime string into date ans time substrings.
1687	* Throws exception when date can't be parsed
1688	* Returns [dateString, timeString]
1689	*/
1690	var splitDateTime = function(dateFormat, dateTimeString, dateSettings, timeSettings) {
1691		try {
1692			// The idea is to get the number separator occurances in datetime and the time format requested (since time has 
1693			// fewer unknowns, mostly numbers and am/pm). We will use the time pattern to split.
1694			var separator = timeSettings && timeSettings.separator ? timeSettings.separator : $.timepicker._defaults.separator,
1695				format = timeSettings && timeSettings.timeFormat ? timeSettings.timeFormat : $.timepicker._defaults.timeFormat,
1696				timeParts = format.split(separator), // how many occurances of separator may be in our format?
1697				timePartsLen = timeParts.length,
1698				allParts = dateTimeString.split(separator),
1699				allPartsLen = allParts.length;
1700
1701			if (allPartsLen > 1) {
1702				return [
1703						allParts.splice(0,allPartsLen-timePartsLen).join(separator),
1704						allParts.splice(0,timePartsLen).join(separator)
1705					];
1706			}
1707
1708		} catch (err) {
1709			$.datepicker.log('Could not split the date from the time. Please check the following datetimepicker options' +
1710					"\nthrown error: " + err +
1711					"\ndateTimeString" + dateTimeString +
1712					"\ndateFormat = " + dateFormat +
1713					"\nseparator = " + timeSettings.separator +
1714					"\ntimeFormat = " + timeSettings.timeFormat);
1715
1716			if (err.indexOf(":") >= 0) {
1717				// Hack!  The error message ends with a colon, a space, and
1718				// the "extra" characters.  We rely on that instead of
1719				// attempting to perfectly reproduce the parsing algorithm.
1720				var dateStringLength = dateTimeString.length - (err.length - err.indexOf(':') - 2),
1721					timeString = dateTimeString.substring(dateStringLength);
1722
1723				return [$.trim(dateTimeString.substring(0, dateStringLength)), $.trim(dateTimeString.substring(dateStringLength))];
1724
1725			} else {
1726				throw err;
1727			}
1728		}
1729		return [dateTimeString, ''];
1730	};
1731
1732	/*
1733	* Internal function to parse datetime interval
1734	* Returns: {date: Date, timeObj: Object}, where
1735	*   date - parsed date without time (type Date)
1736	*   timeObj = {hour: , minute: , second: , millisec: } - parsed time. Optional
1737	*/
1738	var parseDateTimeInternal = function(dateFormat, timeFormat, dateTimeString, dateSettings, timeSettings) {
1739		var date;
1740		var splitRes = splitDateTime(dateFormat, dateTimeString, dateSettings, timeSettings);
1741		date = $.datepicker._base_parseDate(dateFormat, splitRes[0], dateSettings);
1742		if (splitRes[1] !== '') {
1743			var timeString = splitRes[1],
1744				parsedTime = $.datepicker.parseTime(timeFormat, timeString, timeSettings);
1745
1746			if (parsedTime === null) {
1747				throw 'Wrong time format';
1748			}
1749			return {
1750				date: date,
1751				timeObj: parsedTime
1752			};
1753		} else {
1754			return {
1755				date: date
1756			};
1757		}
1758	};
1759
1760	/*
1761	* Internal function to set timezone_select to the local timezone
1762	*/
1763	var selectLocalTimeZone = function(tp_inst, date) {
1764		if (tp_inst && tp_inst.timezone_select) {
1765			tp_inst._defaults.useLocalTimezone = true;
1766			var now = typeof date !== 'undefined' ? date : new Date();
1767			var tzoffset = $.timepicker.timeZoneOffsetString(now);
1768			if (tp_inst._defaults.timezoneIso8601) {
1769				tzoffset = tzoffset.substring(0, 3) + ':' + tzoffset.substring(3);
1770			}
1771			tp_inst.timezone_select.val(tzoffset);
1772		}
1773	};
1774
1775	/*
1776	* Create a Singleton Insance
1777	*/
1778	$.timepicker = new Timepicker();
1779
1780	/**
1781	 * Get the timezone offset as string from a date object (eg '+0530' for UTC+5.5)
1782	 * @param  date
1783	 * @return string
1784	 */
1785	$.timepicker.timeZoneOffsetString = function(date) {
1786		var off = date.getTimezoneOffset() * -1,
1787			minutes = off % 60,
1788			hours = (off - minutes) / 60;
1789		return (off >= 0 ? '+' : '-') + ('0' + (hours * 101).toString()).substr(-2) + ('0' + (minutes * 101).toString()).substr(-2);
1790	};
1791
1792	/**
1793	 * Calls `timepicker()` on the `startTime` and `endTime` elements, and configures them to
1794	 * enforce date range limits.
1795	 * n.b. The input value must be correctly formatted (reformatting is not supported)
1796	 * @param  Element startTime
1797	 * @param  Element endTime
1798	 * @param  obj options Options for the timepicker() call
1799	 * @return jQuery
1800	 */
1801	$.timepicker.timeRange = function(startTime, endTime, options) {
1802		return $.timepicker.handleRange('timepicker', startTime, endTime, options);
1803	};
1804
1805	/**
1806	 * Calls `datetimepicker` on the `startTime` and `endTime` elements, and configures them to
1807	 * enforce date range limits.
1808	 * @param  Element startTime
1809	 * @param  Element endTime
1810	 * @param  obj options Options for the `timepicker()` call. Also supports `reformat`,
1811	 *   a boolean value that can be used to reformat the input values to the `dateFormat`.
1812	 * @param  string method Can be used to specify the type of picker to be added
1813	 * @return jQuery
1814	 */
1815	$.timepicker.dateTimeRange = function(startTime, endTime, options) {
1816		$.timepicker.dateRange(startTime, endTime, options, 'datetimepicker');
1817	};
1818
1819	/**
1820	 * Calls `method` on the `startTime` and `endTime` elements, and configures them to
1821	 * enforce date range limits.
1822	 * @param  Element startTime
1823	 * @param  Element endTime
1824	 * @param  obj options Options for the `timepicker()` call. Also supports `reformat`,
1825	 *   a boolean value that can be used to reformat the input values to the `dateFormat`.
1826	 * @param  string method Can be used to specify the type of picker to be added
1827	 * @return jQuery
1828	 */
1829	$.timepicker.dateRange = function(startTime, endTime, options, method) {
1830		method = method || 'datepicker';
1831		$.timepicker.handleRange(method, startTime, endTime, options);
1832	};
1833
1834	/**
1835	 * Calls `method` on the `startTime` and `endTime` elements, and configures them to
1836	 * enforce date range limits.
1837	 * @param  string method Can be used to specify the type of picker to be added
1838	 * @param  Element startTime
1839	 * @param  Element endTime
1840	 * @param  obj options Options for the `timepicker()` call. Also supports `reformat`,
1841	 *   a boolean value that can be used to reformat the input values to the `dateFormat`.
1842	 * @return jQuery
1843	 */
1844	$.timepicker.handleRange = function(method, startTime, endTime, options) {
1845		$.fn[method].call(startTime, $.extend({
1846			onClose: function(dateText, inst) {
1847				checkDates(this, endTime, dateText);
1848			},
1849			onSelect: function(selectedDateTime) {
1850				selected(this, endTime, 'minDate');
1851			}
1852		}, options, options.start));
1853		$.fn[method].call(endTime, $.extend({
1854			onClose: function(dateText, inst) {
1855				checkDates(this, startTime, dateText);
1856			},
1857			onSelect: function(selectedDateTime) {
1858				selected(this, startTime, 'maxDate');
1859			}
1860		}, options, options.end));
1861		// timepicker doesn't provide access to its 'timeFormat' option, 
1862		// nor could I get datepicker.formatTime() to behave with times, so I
1863		// have disabled reformatting for timepicker
1864		if (method != 'timepicker' && options.reformat) {
1865			$([startTime, endTime]).each(function() {
1866				var format = $(this)[method].call($(this), 'option', 'dateFormat'),
1867					date = new Date($(this).val());
1868				if ($(this).val() && date) {
1869					$(this).val($.datepicker.formatDate(format, date));
1870				}
1871			});
1872		}
1873		checkDates(startTime, endTime, startTime.val());
1874
1875		function checkDates(changed, other, dateText) {
1876			if (other.val() && (new Date(startTime.val()) > new Date(endTime.val()))) {
1877				other.val(dateText);
1878			}
1879		}
1880		selected(startTime, endTime, 'minDate');
1881		selected(endTime, startTime, 'maxDate');
1882
1883		function selected(changed, other, option) {
1884			if (!$(changed).val()) {
1885				return;
1886			}
1887			var date = $(changed)[method].call($(changed), 'getDate');
1888			// timepicker doesn't implement 'getDate' and returns a jQuery
1889			if (date.getTime) {
1890				$(other)[method].call($(other), 'option', option, date);
1891			}
1892		}
1893		return $([startTime.get(0), endTime.get(0)]);
1894	};
1895
1896	/*
1897	* Keep up with the version
1898	*/
1899	$.timepicker.version = "1.1.1";
1900
1901})(jQuery);

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