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