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