jquery-timepicker-addon-rails 1.2.3 → 1.4.1

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