~openerp-dev/openerp-web/trunk-jquery1.9-ppa

« back to all changes in this revision

Viewing changes to addons/web/static/lib/jquery.ui.timepicker/js/jquery-ui-timepicker-addon.js

  • Committer: Prashant Panchal(OpenERP)
  • Date: 2014-04-16 09:24:51 UTC
  • Revision ID: ppa@tinyerp.com-20140416092451-outv36dahgip1860
[IMP] add jquery-migrate-1.1.1.j & jquery-1.9.1.js & change in web

Show diffs side-by-side

added added

removed removed

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