PageSourceSearch

https://www.asia-p.co.jp/wp-content/plugins/wp-cleanfix/wpdk/asset…/timepicker/jquery.timepicker.js?ver=1.1.0

js asia-p.co.jp collected 2026-10-06 13:18:04 UTC 62,756 bytes, 1,886 lines download raw bytes

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