Best JavaScript code snippet using cypress
timepicker.js
Source:timepicker.js
1/*! jQuery Timepicker Addon - v1.6.1 - 2015-11-142 * http://trentrichardson.com/examples/timepicker3 * Copyright (c) 2015 Trent Richardson; Licensed MIT */4(function (factory) {5 if (typeof define === 'function' && define.amd) {6 define(['jquery', 'jquery-ui'], factory);7 } else {8 factory(jQuery);9 }10}(function ($) {11 /*12 * Lets not redefine timepicker, Prevent "Uncaught RangeError: Maximum call stack size exceeded"13 */14 $.ui.timepicker = $.ui.timepicker || {};15 if ($.ui.timepicker.version) {16 return;17 }18 /*19 * Extend jQueryUI, get it started with our version number20 */21 $.extend($.ui, {22 timepicker: {23 version: "1.6.1"24 }25 });26 /*27 * Timepicker manager.28 * Use the singleton instance of this class, $.timepicker, to interact with the time picker.29 * Settings for (groups of) time pickers are maintained in an instance object,30 * allowing multiple different settings on the same page.31 */32 var Timepicker = function () {33 this.regional = []; // Available regional settings, indexed by language code34 this.regional[''] = { // Default regional settings35 currentText: 'Now',36 closeText: 'Done',37 amNames: ['AM', 'A'],38 pmNames: ['PM', 'P'],39 timeFormat: 'HH:mm',40 timeSuffix: '',41 timeOnlyTitle: 'Choose Time',42 timeText: 'Time',43 hourText: 'Hour',44 minuteText: 'Minute',45 secondText: 'Second',46 millisecText: 'Millisecond',47 microsecText: 'Microsecond',48 timezoneText: 'Time Zone',49 isRTL: false50 };51 this._defaults = { // Global defaults for all the datetime picker instances52 showButtonPanel: true,53 timeOnly: false,54 timeOnlyShowDate: false,55 showHour: null,56 showMinute: null,57 showSecond: null,58 showMillisec: null,59 showMicrosec: null,60 showTimezone: null,61 showTime: true,62 stepHour: 1,63 stepMinute: 1,64 stepSecond: 1,65 stepMillisec: 1,66 stepMicrosec: 1,67 hour: 0,68 minute: 0,69 second: 0,70 millisec: 0,71 microsec: 0,72 timezone: null,73 hourMin: 0,74 minuteMin: 0,75 secondMin: 0,76 millisecMin: 0,77 microsecMin: 0,78 hourMax: 23,79 minuteMax: 59,80 secondMax: 59,81 millisecMax: 999,82 microsecMax: 999,83 minDateTime: null,84 maxDateTime: null,85 maxTime: null,86 minTime: null,87 onSelect: null,88 hourGrid: 0,89 minuteGrid: 0,90 secondGrid: 0,91 millisecGrid: 0,92 microsecGrid: 0,93 alwaysSetTime: true,94 separator: ' ',95 altFieldTimeOnly: true,96 altTimeFormat: null,97 altSeparator: null,98 altTimeSuffix: null,99 altRedirectFocus: true,100 pickerTimeFormat: null,101 pickerTimeSuffix: null,102 showTimepicker: true,103 timezoneList: null,104 addSliderAccess: false,105 sliderAccessArgs: null,106 controlType: 'slider',107 oneLine: false,108 defaultValue: null,109 parse: 'strict',110 afterInject: null111 };112 $.extend(this._defaults, this.regional['']);113 };114 $.extend(Timepicker.prototype, {115 $input: null,116 $altInput: null,117 $timeObj: null,118 inst: null,119 hour_slider: null,120 minute_slider: null,121 second_slider: null,122 millisec_slider: null,123 microsec_slider: null,124 timezone_select: null,125 maxTime: null,126 minTime: null,127 hour: 0,128 minute: 0,129 second: 0,130 millisec: 0,131 microsec: 0,132 timezone: null,133 hourMinOriginal: null,134 minuteMinOriginal: null,135 secondMinOriginal: null,136 millisecMinOriginal: null,137 microsecMinOriginal: null,138 hourMaxOriginal: null,139 minuteMaxOriginal: null,140 secondMaxOriginal: null,141 millisecMaxOriginal: null,142 microsecMaxOriginal: null,143 ampm: '',144 formattedDate: '',145 formattedTime: '',146 formattedDateTime: '',147 timezoneList: null,148 units: ['hour', 'minute', 'second', 'millisec', 'microsec'],149 support: {},150 control: null,151 /*152 * Override the default settings for all instances of the time picker.153 * @param {Object} settings object - the new settings to use as defaults (anonymous object)154 * @return {Object} the manager object155 */156 setDefaults: function (settings) {157 extendRemove(this._defaults, settings || {});158 return this;159 },160 /*161 * Create a new Timepicker instance162 */163 _newInst: function ($input, opts) {164 var tp_inst = new Timepicker(),165 inlineSettings = {},166 fns = {},167 overrides, i;168 for (var attrName in this._defaults) {169 if (this._defaults.hasOwnProperty(attrName)) {170 var attrValue = $input.attr('time:' + attrName);171 if (attrValue) {172 try {173 inlineSettings[attrName] = eval(attrValue);174 } catch (err) {175 inlineSettings[attrName] = attrValue;176 }177 }178 }179 }180 overrides = {181 beforeShow: function (input, dp_inst) {182 if ($.isFunction(tp_inst._defaults.evnts.beforeShow)) {183 return tp_inst._defaults.evnts.beforeShow.call($input[0], input, dp_inst, tp_inst);184 }185 },186 onChangeMonthYear: function (year, month, dp_inst) {187 // Update the time as well : this prevents the time from disappearing from the $input field.188 // tp_inst._updateDateTime(dp_inst);189 if ($.isFunction(tp_inst._defaults.evnts.onChangeMonthYear)) {190 tp_inst._defaults.evnts.onChangeMonthYear.call($input[0], year, month, dp_inst, tp_inst);191 }192 },193 onClose: function (dateText, dp_inst) {194 if (tp_inst.timeDefined === true && $input.val() !== '') {195 tp_inst._updateDateTime(dp_inst);196 }197 if ($.isFunction(tp_inst._defaults.evnts.onClose)) {198 tp_inst._defaults.evnts.onClose.call($input[0], dateText, dp_inst, tp_inst);199 }200 }201 };202 for (i in overrides) {203 if (overrides.hasOwnProperty(i)) {204 fns[i] = opts[i] || this._defaults[i] || null;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 // detect which units are supported218 tp_inst.support = detectSupport(219 tp_inst._defaults.timeFormat +220 (tp_inst._defaults.pickerTimeFormat ? tp_inst._defaults.pickerTimeFormat : '') +221 (tp_inst._defaults.altTimeFormat ? tp_inst._defaults.altTimeFormat : ''));222 // controlType is string - key to our this._controls223 if (typeof(tp_inst._defaults.controlType) === 'string') {224 if (tp_inst._defaults.controlType === 'slider' && typeof($.ui.slider) === 'undefined') {225 tp_inst._defaults.controlType = 'select';226 }227 tp_inst.control = tp_inst._controls[tp_inst._defaults.controlType];228 }229 // controlType is an object and must implement create, options, value methods230 else {231 tp_inst.control = tp_inst._defaults.controlType;232 }233 // prep the timezone options234 var timezoneList = [-720, -660, -600, -570, -540, -480, -420, -360, -300, -270, -240, -210, -180, -120, -60,235 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];236 if (tp_inst._defaults.timezoneList !== null) {237 timezoneList = tp_inst._defaults.timezoneList;238 }239 var tzl = timezoneList.length, tzi = 0, tzv = null;240 if (tzl > 0 && typeof timezoneList[0] !== 'object') {241 for (; tzi < tzl; tzi++) {242 tzv = timezoneList[tzi];243 timezoneList[tzi] = { value: tzv, label: $.timepicker.timezoneOffsetString(tzv, tp_inst.support.iso8601) };244 }245 }246 tp_inst._defaults.timezoneList = timezoneList;247 // set the default units248 tp_inst.timezone = tp_inst._defaults.timezone !== null ? $.timepicker.timezoneOffsetNumber(tp_inst._defaults.timezone) :249 ((new Date()).getTimezoneOffset() * -1);250 tp_inst.hour = tp_inst._defaults.hour < tp_inst._defaults.hourMin ? tp_inst._defaults.hourMin :251 tp_inst._defaults.hour > tp_inst._defaults.hourMax ? tp_inst._defaults.hourMax : tp_inst._defaults.hour;252 tp_inst.minute = tp_inst._defaults.minute < tp_inst._defaults.minuteMin ? tp_inst._defaults.minuteMin :253 tp_inst._defaults.minute > tp_inst._defaults.minuteMax ? tp_inst._defaults.minuteMax : tp_inst._defaults.minute;254 tp_inst.second = tp_inst._defaults.second < tp_inst._defaults.secondMin ? tp_inst._defaults.secondMin :255 tp_inst._defaults.second > tp_inst._defaults.secondMax ? tp_inst._defaults.secondMax : tp_inst._defaults.second;256 tp_inst.millisec = tp_inst._defaults.millisec < tp_inst._defaults.millisecMin ? tp_inst._defaults.millisecMin :257 tp_inst._defaults.millisec > tp_inst._defaults.millisecMax ? tp_inst._defaults.millisecMax : tp_inst._defaults.millisec;258 tp_inst.microsec = tp_inst._defaults.microsec < tp_inst._defaults.microsecMin ? tp_inst._defaults.microsecMin :259 tp_inst._defaults.microsec > tp_inst._defaults.microsecMax ? tp_inst._defaults.microsecMax : tp_inst._defaults.microsec;260 tp_inst.ampm = '';261 tp_inst.$input = $input;262 if (tp_inst._defaults.altField) {263 tp_inst.$altInput = $(tp_inst._defaults.altField);264 if (tp_inst._defaults.altRedirectFocus === true) {265 tp_inst.$altInput.css({266 cursor: 'pointer'267 }).focus(function () {268 $input.trigger("focus");269 });270 }271 }272 if (tp_inst._defaults.minDate === 0 || tp_inst._defaults.minDateTime === 0) {273 tp_inst._defaults.minDate = new Date();274 }275 if (tp_inst._defaults.maxDate === 0 || tp_inst._defaults.maxDateTime === 0) {276 tp_inst._defaults.maxDate = new Date();277 }278 // datepicker needs minDate/maxDate, timepicker needs minDateTime/maxDateTime..279 if (tp_inst._defaults.minDate !== undefined && tp_inst._defaults.minDate instanceof Date) {280 tp_inst._defaults.minDateTime = new Date(tp_inst._defaults.minDate.getTime());281 }282 if (tp_inst._defaults.minDateTime !== undefined && tp_inst._defaults.minDateTime instanceof Date) {283 tp_inst._defaults.minDate = new Date(tp_inst._defaults.minDateTime.getTime());284 }285 if (tp_inst._defaults.maxDate !== undefined && tp_inst._defaults.maxDate instanceof Date) {286 tp_inst._defaults.maxDateTime = new Date(tp_inst._defaults.maxDate.getTime());287 }288 if (tp_inst._defaults.maxDateTime !== undefined && tp_inst._defaults.maxDateTime instanceof Date) {289 tp_inst._defaults.maxDate = new Date(tp_inst._defaults.maxDateTime.getTime());290 }291 tp_inst.$input.bind('focus', function () {292 tp_inst._onFocus();293 });294 return tp_inst;295 },296 /*297 * add our sliders to the calendar298 */299 _addTimePicker: function (dp_inst) {300 var currDT = $.trim((this.$altInput && this._defaults.altFieldTimeOnly) ? this.$input.val() + ' ' + this.$altInput.val() : this.$input.val());301 this.timeDefined = this._parseTime(currDT);302 this._limitMinMaxDateTime(dp_inst, false);303 this._injectTimePicker();304 this._afterInject();305 },306 /*307 * parse the time string from input value or _setTime308 */309 _parseTime: function (timeString, withDate) {310 if (!this.inst) {311 this.inst = $.datepicker._getInst(this.$input[0]);312 }313 if (withDate || !this._defaults.timeOnly) {314 var dp_dateFormat = $.datepicker._get(this.inst, 'dateFormat');315 try {316 var parseRes = parseDateTimeInternal(dp_dateFormat, this._defaults.timeFormat, timeString, $.datepicker._getFormatConfig(this.inst), this._defaults);317 if (!parseRes.timeObj) {318 return false;319 }320 $.extend(this, parseRes.timeObj);321 } catch (err) {322 $.timepicker.log("Error parsing the date/time string: " + err +323 "\ndate/time string = " + timeString +324 "\ntimeFormat = " + this._defaults.timeFormat +325 "\ndateFormat = " + dp_dateFormat);326 return false;327 }328 return true;329 } else {330 var timeObj = $.datepicker.parseTime(this._defaults.timeFormat, timeString, this._defaults);331 if (!timeObj) {332 return false;333 }334 $.extend(this, timeObj);335 return true;336 }337 },338 /*339 * Handle callback option after injecting timepicker340 */341 _afterInject: function() {342 var o = this.inst.settings;343 if ($.isFunction(o.afterInject)) {344 o.afterInject.call(this);345 }346 },347 /*348 * generate and inject html for timepicker into ui datepicker349 */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 // Prevent displaying twice363 if ($dp.find("div.ui-timepicker-div").length === 0 && o.showTimepicker) {364 var noDisplay = ' ui_tpicker_unit_hide',365 html = '<div class="ui-timepicker-div' + (o.isRTL ? ' ui-timepicker-rtl' : '') + (o.oneLine && o.controlType === 'select' ? ' ui-timepicker-oneLine' : '') + '"><dl>' + '<dt class="ui_tpicker_time_label' + ((o.showTime) ? '' : noDisplay) + '">' + o.timeText + '</dt>' +366 '<dd class="ui_tpicker_time '+ ((o.showTime) ? '' : noDisplay) + '"><input class="ui_tpicker_time_input" ' + (o.timeInput ? '' : 'disabled') + '/></dd>';367 // Create the markup368 for (i = 0, l = this.units.length; i < l; i++) {369 litem = this.units[i];370 uitem = litem.substr(0, 1).toUpperCase() + litem.substr(1);371 show = o['show' + uitem] !== null ? o['show' + uitem] : this.support[litem];372 // Added by Peter Medeiros:373 // - Figure out what the hour/minute/second max should be based on the step values.374 // - Example: if stepMinute is 15, then minMax is 45.375 max[litem] = parseInt((o[litem + 'Max'] - ((o[litem + 'Max'] - o[litem + 'Min']) % o['step' + uitem])), 10);376 gridSize[litem] = 0;377 html += '<dt class="ui_tpicker_' + litem + '_label' + (show ? '' : noDisplay) + '">' + o[litem + 'Text'] + '</dt>' +378 '<dd class="ui_tpicker_' + litem + (show ? '' : noDisplay) + '"><div class="ui_tpicker_' + litem + '_slider' + (show ? '' : noDisplay) + '"></div>';379 if (show && o[litem + 'Grid'] > 0) {380 html += '<div style="padding-left: 1px"><table class="ui-tpicker-grid-label"><tr>';381 if (litem === 'hour') {382 for (var h = o[litem + 'Min']; h <= max[litem]; h += parseInt(o[litem + 'Grid'], 10)) {383 gridSize[litem]++;384 var tmph = $.datepicker.formatTime(this.support.ampm ? 'hht' : 'HH', {hour: h}, o);385 html += '<td data-for="' + litem + '">' + tmph + '</td>';386 }387 }388 else {389 for (var m = o[litem + 'Min']; m <= max[litem]; m += parseInt(o[litem + 'Grid'], 10)) {390 gridSize[litem]++;391 html += '<td data-for="' + litem + '">' + ((m < 10) ? '0' : '') + m + '</td>';392 }393 }394 html += '</tr></table></div>';395 }396 html += '</dd>';397 }398 // Timezone399 var showTz = o.showTimezone !== null ? o.showTimezone : this.support.timezone;400 html += '<dt class="ui_tpicker_timezone_label' + (showTz ? '' : noDisplay) + '">' + o.timezoneText + '</dt>';401 html += '<dd class="ui_tpicker_timezone' + (showTz ? '' : noDisplay) + '"></dd>';402 // Create the elements from string403 html += '</dl></div>';404 var $tp = $(html);405 // if we only want time picker...406 if (o.timeOnly === true) {407 $tp.prepend('<div class="ui-widget-header ui-helper-clearfix ui-corner-all">' + '<div class="ui-datepicker-title">' + o.timeOnlyTitle + '</div>' + '</div>');408 $dp.find('.ui-datepicker-header, .ui-datepicker-calendar').hide();409 }410 // add sliders, adjust grids, add events411 for (i = 0, l = tp_inst.units.length; i < l; i++) {412 litem = tp_inst.units[i];413 uitem = litem.substr(0, 1).toUpperCase() + litem.substr(1);414 show = o['show' + uitem] !== null ? o['show' + uitem] : this.support[litem];415 // add the slider416 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]);417 // adjust the grid and add click event418 if (show && o[litem + 'Grid'] > 0) {419 size = 100 * gridSize[litem] * o[litem + 'Grid'] / (max[litem] - o[litem + 'Min']);420 $tp.find('.ui_tpicker_' + litem + ' table').css({421 width: size + "%",422 marginLeft: o.isRTL ? '0' : ((size / (-2 * gridSize[litem])) + "%"),423 marginRight: o.isRTL ? ((size / (-2 * gridSize[litem])) + "%") : '0',424 borderCollapse: 'collapse'425 }).find("td").click(function (e) {426 var $t = $(this),427 h = $t.html(),428 n = parseInt(h.replace(/[^0-9]/g), 10),429 ap = h.replace(/[^apm]/ig),430 f = $t.data('for'); // loses scope, so we use data-for431 if (f === 'hour') {432 if (ap.indexOf('p') !== -1 && n < 12) {433 n += 12;434 }435 else {436 if (ap.indexOf('a') !== -1 && n === 12) {437 n = 0;438 }439 }440 }441 tp_inst.control.value(tp_inst, tp_inst[f + '_slider'], litem, n);442 tp_inst._onTimeChange();443 tp_inst._onSelectHandler();444 }).css({445 cursor: 'pointer',446 width: (100 / gridSize[litem]) + '%',447 textAlign: 'center',448 overflow: 'hidden'449 });450 } // end if grid > 0451 } // end for loop452 // Add timezone options453 this.timezone_select = $tp.find('.ui_tpicker_timezone').append('<select></select>').find("select");454 $.fn.append.apply(this.timezone_select,455 $.map(o.timezoneList, function (val, idx) {456 return $("<option />").val(typeof val === "object" ? val.value : val).text(typeof val === "object" ? val.label : val);457 }));458 if (typeof(this.timezone) !== "undefined" && this.timezone !== null && this.timezone !== "") {459 var local_timezone = (new Date(this.inst.selectedYear, this.inst.selectedMonth, this.inst.selectedDay, 12)).getTimezoneOffset() * -1;460 if (local_timezone === this.timezone) {461 selectLocalTimezone(tp_inst);462 } else {463 this.timezone_select.val(this.timezone);464 }465 } else {466 if (typeof(this.hour) !== "undefined" && this.hour !== null && this.hour !== "") {467 this.timezone_select.val(o.timezone);468 } else {469 selectLocalTimezone(tp_inst);470 }471 }472 this.timezone_select.change(function () {473 tp_inst._onTimeChange();474 tp_inst._onSelectHandler();475 tp_inst._afterInject();476 });477 // End timezone options478 // inject timepicker into datepicker479 var $buttonPanel = $dp.find('.ui-datepicker-buttonpane');480 if ($buttonPanel.length) {481 $buttonPanel.before($tp);482 } else {483 $dp.append($tp);484 }485 this.$timeObj = $tp.find('.ui_tpicker_time_input');486 this.$timeObj.change(function () {487 var timeFormat = tp_inst.inst.settings.timeFormat;488 var parsedTime = $.datepicker.parseTime(timeFormat, this.value);489 var update = new Date();490 if (parsedTime) {491 update.setHours(parsedTime.hour);492 update.setMinutes(parsedTime.minute);493 update.setSeconds(parsedTime.second);494 $.datepicker._setTime(tp_inst.inst, update);495 } else {496 this.value = tp_inst.formattedTime;497 this.blur();498 }499 });500 if (this.inst !== null) {501 var timeDefined = this.timeDefined;502 this._onTimeChange();503 this.timeDefined = timeDefined;504 }505 // slideAccess integration: http://trentrichardson.com/2011/11/11/jquery-ui-sliders-and-touch-accessibility/506 if (this._defaults.addSliderAccess) {507 var sliderAccessArgs = this._defaults.sliderAccessArgs,508 rtl = this._defaults.isRTL;509 sliderAccessArgs.isRTL = rtl;510 setTimeout(function () { // fix for inline mode511 if ($tp.find('.ui-slider-access').length === 0) {512 $tp.find('.ui-slider:visible').sliderAccess(sliderAccessArgs);513 // fix any grids since sliders are shorter514 var sliderAccessWidth = $tp.find('.ui-slider-access:eq(0)').outerWidth(true);515 if (sliderAccessWidth) {516 $tp.find('table:visible').each(function () {517 var $g = $(this),518 oldWidth = $g.outerWidth(),519 oldMarginLeft = $g.css(rtl ? 'marginRight' : 'marginLeft').toString().replace('%', ''),520 newWidth = oldWidth - sliderAccessWidth,521 newMarginLeft = ((oldMarginLeft * newWidth) / oldWidth) + '%',522 css = { width: newWidth, marginRight: 0, marginLeft: 0 };523 css[rtl ? 'marginRight' : 'marginLeft'] = newMarginLeft;524 $g.css(css);525 });526 }527 }528 }, 10);529 }530 // end slideAccess integration531 tp_inst._limitMinMaxDateTime(this.inst, true);532 }533 },534 /*535 * This function tries to limit the ability to go outside the536 * min/max date range537 */538 _limitMinMaxDateTime: function (dp_inst, adjustSliders) {539 var o = this._defaults,540 dp_date = new Date(dp_inst.selectedYear, dp_inst.selectedMonth, dp_inst.selectedDay);541 if (!this._defaults.showTimepicker) {542 return;543 } // No time so nothing to check here544 if ($.datepicker._get(dp_inst, 'minDateTime') !== null && $.datepicker._get(dp_inst, 'minDateTime') !== undefined && dp_date) {545 var minDateTime = $.datepicker._get(dp_inst, 'minDateTime'),546 minDateTimeDate = new Date(minDateTime.getFullYear(), minDateTime.getMonth(), minDateTime.getDate(), 0, 0, 0, 0);547 if (this.hourMinOriginal === null || this.minuteMinOriginal === null || this.secondMinOriginal === null || this.millisecMinOriginal === null || this.microsecMinOriginal === null) {548 this.hourMinOriginal = o.hourMin;549 this.minuteMinOriginal = o.minuteMin;550 this.secondMinOriginal = o.secondMin;551 this.millisecMinOriginal = o.millisecMin;552 this.microsecMinOriginal = o.microsecMin;553 }554 if (dp_inst.settings.timeOnly || minDateTimeDate.getTime() === dp_date.getTime()) {555 this._defaults.hourMin = minDateTime.getHours();556 if (this.hour <= this._defaults.hourMin) {557 this.hour = this._defaults.hourMin;558 this._defaults.minuteMin = minDateTime.getMinutes();559 if (this.minute <= this._defaults.minuteMin) {560 this.minute = this._defaults.minuteMin;561 this._defaults.secondMin = minDateTime.getSeconds();562 if (this.second <= this._defaults.secondMin) {563 this.second = this._defaults.secondMin;564 this._defaults.millisecMin = minDateTime.getMilliseconds();565 if (this.millisec <= this._defaults.millisecMin) {566 this.millisec = this._defaults.millisecMin;567 this._defaults.microsecMin = minDateTime.getMicroseconds();568 } else {569 if (this.microsec < this._defaults.microsecMin) {570 this.microsec = this._defaults.microsecMin;571 }572 this._defaults.microsecMin = this.microsecMinOriginal;573 }574 } else {575 this._defaults.millisecMin = this.millisecMinOriginal;576 this._defaults.microsecMin = this.microsecMinOriginal;577 }578 } else {579 this._defaults.secondMin = this.secondMinOriginal;580 this._defaults.millisecMin = this.millisecMinOriginal;581 this._defaults.microsecMin = this.microsecMinOriginal;582 }583 } else {584 this._defaults.minuteMin = this.minuteMinOriginal;585 this._defaults.secondMin = this.secondMinOriginal;586 this._defaults.millisecMin = this.millisecMinOriginal;587 this._defaults.microsecMin = this.microsecMinOriginal;588 }589 } else {590 this._defaults.hourMin = this.hourMinOriginal;591 this._defaults.minuteMin = this.minuteMinOriginal;592 this._defaults.secondMin = this.secondMinOriginal;593 this._defaults.millisecMin = this.millisecMinOriginal;594 this._defaults.microsecMin = this.microsecMinOriginal;595 }596 }597 if ($.datepicker._get(dp_inst, 'maxDateTime') !== null && $.datepicker._get(dp_inst, 'maxDateTime') !== undefined && dp_date) {598 var maxDateTime = $.datepicker._get(dp_inst, 'maxDateTime'),599 maxDateTimeDate = new Date(maxDateTime.getFullYear(), maxDateTime.getMonth(), maxDateTime.getDate(), 0, 0, 0, 0);600 if (this.hourMaxOriginal === null || this.minuteMaxOriginal === null || this.secondMaxOriginal === null || this.millisecMaxOriginal === null) {601 this.hourMaxOriginal = o.hourMax;602 this.minuteMaxOriginal = o.minuteMax;603 this.secondMaxOriginal = o.secondMax;604 this.millisecMaxOriginal = o.millisecMax;605 this.microsecMaxOriginal = o.microsecMax;606 }607 if (dp_inst.settings.timeOnly || maxDateTimeDate.getTime() === dp_date.getTime()) {608 this._defaults.hourMax = maxDateTime.getHours();609 if (this.hour >= this._defaults.hourMax) {610 this.hour = this._defaults.hourMax;611 this._defaults.minuteMax = maxDateTime.getMinutes();612 if (this.minute >= this._defaults.minuteMax) {613 this.minute = this._defaults.minuteMax;614 this._defaults.secondMax = maxDateTime.getSeconds();615 if (this.second >= this._defaults.secondMax) {616 this.second = this._defaults.secondMax;617 this._defaults.millisecMax = maxDateTime.getMilliseconds();618 if (this.millisec >= this._defaults.millisecMax) {619 this.millisec = this._defaults.millisecMax;620 this._defaults.microsecMax = maxDateTime.getMicroseconds();621 } else {622 if (this.microsec > this._defaults.microsecMax) {623 this.microsec = this._defaults.microsecMax;624 }625 this._defaults.microsecMax = this.microsecMaxOriginal;626 }627 } else {628 this._defaults.millisecMax = this.millisecMaxOriginal;629 this._defaults.microsecMax = this.microsecMaxOriginal;630 }631 } else {632 this._defaults.secondMax = this.secondMaxOriginal;633 this._defaults.millisecMax = this.millisecMaxOriginal;634 this._defaults.microsecMax = this.microsecMaxOriginal;635 }636 } else {637 this._defaults.minuteMax = this.minuteMaxOriginal;638 this._defaults.secondMax = this.secondMaxOriginal;639 this._defaults.millisecMax = this.millisecMaxOriginal;640 this._defaults.microsecMax = this.microsecMaxOriginal;641 }642 } else {643 this._defaults.hourMax = this.hourMaxOriginal;644 this._defaults.minuteMax = this.minuteMaxOriginal;645 this._defaults.secondMax = this.secondMaxOriginal;646 this._defaults.millisecMax = this.millisecMaxOriginal;647 this._defaults.microsecMax = this.microsecMaxOriginal;648 }649 }650 if (dp_inst.settings.minTime!==null) {651 var tempMinTime=new Date("01/01/1970 " + dp_inst.settings.minTime);652 if (this.hour<tempMinTime.getHours()) {653 this.hour=this._defaults.hourMin=tempMinTime.getHours();654 this.minute=this._defaults.minuteMin=tempMinTime.getMinutes();655 } else if (this.hour===tempMinTime.getHours() && this.minute<tempMinTime.getMinutes()) {656 this.minute=this._defaults.minuteMin=tempMinTime.getMinutes();657 } else {658 if (this._defaults.hourMin<tempMinTime.getHours()) {659 this._defaults.hourMin=tempMinTime.getHours();660 this._defaults.minuteMin=tempMinTime.getMinutes();661 } else if (this._defaults.hourMin===tempMinTime.getHours()===this.hour && this._defaults.minuteMin<tempMinTime.getMinutes()) {662 this._defaults.minuteMin=tempMinTime.getMinutes();663 } else {664 this._defaults.minuteMin=0;665 }666 }667 }668 if (dp_inst.settings.maxTime!==null) {669 var tempMaxTime=new Date("01/01/1970 " + dp_inst.settings.maxTime);670 if (this.hour>tempMaxTime.getHours()) {671 this.hour=this._defaults.hourMax=tempMaxTime.getHours();672 this.minute=this._defaults.minuteMax=tempMaxTime.getMinutes();673 } else if (this.hour===tempMaxTime.getHours() && this.minute>tempMaxTime.getMinutes()) {674 this.minute=this._defaults.minuteMax=tempMaxTime.getMinutes();675 } else {676 if (this._defaults.hourMax>tempMaxTime.getHours()) {677 this._defaults.hourMax=tempMaxTime.getHours();678 this._defaults.minuteMax=tempMaxTime.getMinutes();679 } else if (this._defaults.hourMax===tempMaxTime.getHours()===this.hour && this._defaults.minuteMax>tempMaxTime.getMinutes()) {680 this._defaults.minuteMax=tempMaxTime.getMinutes();681 } else {682 this._defaults.minuteMax=59;683 }684 }685 }686 if (adjustSliders !== undefined && adjustSliders === true) {687 var hourMax = parseInt((this._defaults.hourMax - ((this._defaults.hourMax - this._defaults.hourMin) % this._defaults.stepHour)), 10),688 minMax = parseInt((this._defaults.minuteMax - ((this._defaults.minuteMax - this._defaults.minuteMin) % this._defaults.stepMinute)), 10),689 secMax = parseInt((this._defaults.secondMax - ((this._defaults.secondMax - this._defaults.secondMin) % this._defaults.stepSecond)), 10),690 millisecMax = parseInt((this._defaults.millisecMax - ((this._defaults.millisecMax - this._defaults.millisecMin) % this._defaults.stepMillisec)), 10),691 microsecMax = parseInt((this._defaults.microsecMax - ((this._defaults.microsecMax - this._defaults.microsecMin) % this._defaults.stepMicrosec)), 10);692 if (this.hour_slider) {693 this.control.options(this, this.hour_slider, 'hour', { min: this._defaults.hourMin, max: hourMax, step: this._defaults.stepHour });694 this.control.value(this, this.hour_slider, 'hour', this.hour - (this.hour % this._defaults.stepHour));695 }696 if (this.minute_slider) {697 this.control.options(this, this.minute_slider, 'minute', { min: this._defaults.minuteMin, max: minMax, step: this._defaults.stepMinute });698 this.control.value(this, this.minute_slider, 'minute', this.minute - (this.minute % this._defaults.stepMinute));699 }700 if (this.second_slider) {701 this.control.options(this, this.second_slider, 'second', { min: this._defaults.secondMin, max: secMax, step: this._defaults.stepSecond });702 this.control.value(this, this.second_slider, 'second', this.second - (this.second % this._defaults.stepSecond));703 }704 if (this.millisec_slider) {705 this.control.options(this, this.millisec_slider, 'millisec', { min: this._defaults.millisecMin, max: millisecMax, step: this._defaults.stepMillisec });706 this.control.value(this, this.millisec_slider, 'millisec', this.millisec - (this.millisec % this._defaults.stepMillisec));707 }708 if (this.microsec_slider) {709 this.control.options(this, this.microsec_slider, 'microsec', { min: this._defaults.microsecMin, max: microsecMax, step: this._defaults.stepMicrosec });710 this.control.value(this, this.microsec_slider, 'microsec', this.microsec - (this.microsec % this._defaults.stepMicrosec));711 }712 }713 },714 /*715 * when a slider moves, set the internal time...716 * on time change is also called when the time is updated in the text field717 */718 _onTimeChange: function () {719 if (!this._defaults.showTimepicker) {720 return;721 }722 var hour = (this.hour_slider) ? this.control.value(this, this.hour_slider, 'hour') : false,723 minute = (this.minute_slider) ? this.control.value(this, this.minute_slider, 'minute') : false,724 second = (this.second_slider) ? this.control.value(this, this.second_slider, 'second') : false,725 millisec = (this.millisec_slider) ? this.control.value(this, this.millisec_slider, 'millisec') : false,726 microsec = (this.microsec_slider) ? this.control.value(this, this.microsec_slider, 'microsec') : false,727 timezone = (this.timezone_select) ? this.timezone_select.val() : false,728 o = this._defaults,729 pickerTimeFormat = o.pickerTimeFormat || o.timeFormat,730 pickerTimeSuffix = o.pickerTimeSuffix || o.timeSuffix;731 if (typeof(hour) === 'object') {732 hour = false;733 }734 if (typeof(minute) === 'object') {735 minute = false;736 }737 if (typeof(second) === 'object') {738 second = false;739 }740 if (typeof(millisec) === 'object') {741 millisec = false;742 }743 if (typeof(microsec) === 'object') {744 microsec = false;745 }746 if (typeof(timezone) === 'object') {747 timezone = false;748 }749 if (hour !== false) {750 hour = parseInt(hour, 10);751 }752 if (minute !== false) {753 minute = parseInt(minute, 10);754 }755 if (second !== false) {756 second = parseInt(second, 10);757 }758 if (millisec !== false) {759 millisec = parseInt(millisec, 10);760 }761 if (microsec !== false) {762 microsec = parseInt(microsec, 10);763 }764 if (timezone !== false) {765 timezone = timezone.toString();766 }767 var ampm = o[hour < 12 ? 'amNames' : 'pmNames'][0];768 // If the update was done in the input field, the input field should not be updated.769 // If the update was done using the sliders, update the input field.770 var hasChanged = (771 hour !== parseInt(this.hour,10) || // sliders should all be numeric772 minute !== parseInt(this.minute,10) ||773 second !== parseInt(this.second,10) ||774 millisec !== parseInt(this.millisec,10) ||775 microsec !== parseInt(this.microsec,10) ||776 (this.ampm.length > 0 && (hour < 12) !== ($.inArray(this.ampm.toUpperCase(), this.amNames) !== -1)) ||777 (this.timezone !== null && timezone !== this.timezone.toString()) // could be numeric or "EST" format, so use toString()778 );779 if (hasChanged) {780 if (hour !== false) {781 this.hour = hour;782 }783 if (minute !== false) {784 this.minute = minute;785 }786 if (second !== false) {787 this.second = second;788 }789 if (millisec !== false) {790 this.millisec = millisec;791 }792 if (microsec !== false) {793 this.microsec = microsec;794 }795 if (timezone !== false) {796 this.timezone = timezone;797 }798 if (!this.inst) {799 this.inst = $.datepicker._getInst(this.$input[0]);800 }801 this._limitMinMaxDateTime(this.inst, true);802 }803 if (this.support.ampm) {804 this.ampm = ampm;805 }806 // Updates the time within the timepicker807 this.formattedTime = $.datepicker.formatTime(o.timeFormat, this, o);808 if (this.$timeObj) {809 var sPos = this.$timeObj[0].selectionStart;810 var ePos = this.$timeObj[0].selectionEnd;811 if (pickerTimeFormat === o.timeFormat) {812 this.$timeObj.val(this.formattedTime + pickerTimeSuffix);813 }814 else {815 this.$timeObj.val($.datepicker.formatTime(pickerTimeFormat, this, o) + pickerTimeSuffix);816 }817 this.$timeObj[0].setSelectionRange(sPos, ePos);818 }819 this.timeDefined = true;820 if (hasChanged) {821 this._updateDateTime();822 //this.$input.focus(); // may automatically open the picker on setDate823 }824 },825 /*826 * call custom onSelect.827 * bind to sliders slidestop, and grid click.828 */829 _onSelectHandler: function () {830 var onSelect = this._defaults.onSelect || this.inst.settings.onSelect;831 var inputEl = this.$input ? this.$input[0] : null;832 if (onSelect && inputEl) {833 onSelect.apply(inputEl, [this.formattedDateTime, this]);834 }835 },836 /*837 * update our input with the new date time..838 */839 _updateDateTime: function (dp_inst) {840 dp_inst = this.inst || dp_inst;841 var dtTmp = (dp_inst.currentYear > 0?842 new Date(dp_inst.currentYear, dp_inst.currentMonth, dp_inst.currentDay) :843 new Date(dp_inst.selectedYear, dp_inst.selectedMonth, dp_inst.selectedDay)),844 dt = $.datepicker._daylightSavingAdjust(dtTmp),845 //dt = $.datepicker._daylightSavingAdjust(new Date(dp_inst.selectedYear, dp_inst.selectedMonth, dp_inst.selectedDay)),846 //dt = $.datepicker._daylightSavingAdjust(new Date(dp_inst.currentYear, dp_inst.currentMonth, dp_inst.currentDay)),847 dateFmt = $.datepicker._get(dp_inst, 'dateFormat'),848 formatCfg = $.datepicker._getFormatConfig(dp_inst),849 timeAvailable = dt !== null && this.timeDefined;850 this.formattedDate = $.datepicker.formatDate(dateFmt, (dt === null ? new Date() : dt), formatCfg);851 var formattedDateTime = this.formattedDate;852 // if a slider was changed but datepicker doesn't have a value yet, set it853 if (dp_inst.lastVal === "") {854 dp_inst.currentYear = dp_inst.selectedYear;855 dp_inst.currentMonth = dp_inst.selectedMonth;856 dp_inst.currentDay = dp_inst.selectedDay;857 }858 /*859 * remove following lines to force every changes in date picker to change the input value860 * Bug descriptions: when an input field has a default value, and click on the field to pop up the date picker.861 * If the user manually empty the value in the input field, the date picker will never change selected value.862 */863 //if (dp_inst.lastVal !== undefined && (dp_inst.lastVal.length > 0 && this.$input.val().length === 0)) {864 // return;865 //}866 if (this._defaults.timeOnly === true && this._defaults.timeOnlyShowDate === false) {867 formattedDateTime = this.formattedTime;868 } else if ((this._defaults.timeOnly !== true && (this._defaults.alwaysSetTime || timeAvailable)) || (this._defaults.timeOnly === true && this._defaults.timeOnlyShowDate === true)) {869 formattedDateTime += this._defaults.separator + this.formattedTime + this._defaults.timeSuffix;870 }871 this.formattedDateTime = formattedDateTime;872 if (!this._defaults.showTimepicker) {873 this.$input.val(this.formattedDate);874 } else if (this.$altInput && this._defaults.timeOnly === false && this._defaults.altFieldTimeOnly === true) {875 this.$altInput.val(this.formattedTime);876 this.$input.val(this.formattedDate);877 } else if (this.$altInput) {878 this.$input.val(formattedDateTime);879 var altFormattedDateTime = '',880 altSeparator = this._defaults.altSeparator !== null ? this._defaults.altSeparator : this._defaults.separator,881 altTimeSuffix = this._defaults.altTimeSuffix !== null ? this._defaults.altTimeSuffix : this._defaults.timeSuffix;882 if (!this._defaults.timeOnly) {883 if (this._defaults.altFormat) {884 altFormattedDateTime = $.datepicker.formatDate(this._defaults.altFormat, (dt === null ? new Date() : dt), formatCfg);885 }886 else {887 altFormattedDateTime = this.formattedDate;888 }889 if (altFormattedDateTime) {890 altFormattedDateTime += altSeparator;891 }892 }893 if (this._defaults.altTimeFormat !== null) {894 altFormattedDateTime += $.datepicker.formatTime(this._defaults.altTimeFormat, this, this._defaults) + altTimeSuffix;895 }896 else {897 altFormattedDateTime += this.formattedTime + altTimeSuffix;898 }899 this.$altInput.val(altFormattedDateTime);900 } else {901 this.$input.val(formattedDateTime);902 }903 this.$input.trigger("change");904 },905 _onFocus: function () {906 if (!this.$input.val() && this._defaults.defaultValue) {907 this.$input.val(this._defaults.defaultValue);908 var inst = $.datepicker._getInst(this.$input.get(0)),909 tp_inst = $.datepicker._get(inst, 'timepicker');910 if (tp_inst) {911 if (tp_inst._defaults.timeOnly && (inst.input.val() !== inst.lastVal)) {912 try {913 $.datepicker._updateDatepicker(inst);914 } catch (err) {915 $.timepicker.log(err);916 }917 }918 }919 }920 },921 /*922 * Small abstraction to control types923 * We can add more, just be sure to follow the pattern: create, options, value924 */925 _controls: {926 // slider methods927 slider: {928 create: function (tp_inst, obj, unit, val, min, max, step) {929 var rtl = tp_inst._defaults.isRTL; // if rtl go -60->0 instead of 0->60930 return obj.prop('slide', null).slider({931 orientation: "horizontal",932 value: rtl ? val * -1 : val,933 min: rtl ? max * -1 : min,934 max: rtl ? min * -1 : max,935 step: step,936 slide: function (event, ui) {937 tp_inst.control.value(tp_inst, $(this), unit, rtl ? ui.value * -1 : ui.value);938 tp_inst._onTimeChange();939 },940 stop: function (event, ui) {941 tp_inst._onSelectHandler();942 }943 });944 },945 options: function (tp_inst, obj, unit, opts, val) {946 if (tp_inst._defaults.isRTL) {947 if (typeof(opts) === 'string') {948 if (opts === 'min' || opts === 'max') {949 if (val !== undefined) {950 return obj.slider(opts, val * -1);951 }952 return Math.abs(obj.slider(opts));953 }954 return obj.slider(opts);955 }956 var min = opts.min,957 max = opts.max;958 opts.min = opts.max = null;959 if (min !== undefined) {960 opts.max = min * -1;961 }962 if (max !== undefined) {963 opts.min = max * -1;964 }965 return obj.slider(opts);966 }967 if (typeof(opts) === 'string' && val !== undefined) {968 return obj.slider(opts, val);969 }970 return obj.slider(opts);971 },972 value: function (tp_inst, obj, unit, val) {973 if (tp_inst._defaults.isRTL) {974 if (val !== undefined) {975 return obj.slider('value', val * -1);976 }977 return Math.abs(obj.slider('value'));978 }979 if (val !== undefined) {980 return obj.slider('value', val);981 }982 return obj.slider('value');983 }984 },985 // select methods986 select: {987 create: function (tp_inst, obj, unit, val, min, max, step) {988 var sel = '<select class="ui-timepicker-select ui-state-default ui-corner-all" data-unit="' + unit + '" data-min="' + min + '" data-max="' + max + '" data-step="' + step + '">',989 format = tp_inst._defaults.pickerTimeFormat || tp_inst._defaults.timeFormat;990 for (var i = min; i <= max; i += step) {991 sel += '<option value="' + i + '"' + (i === val ? ' selected' : '') + '>';992 if (unit === 'hour') {993 sel += $.datepicker.formatTime($.trim(format.replace(/[^ht ]/ig, '')), {hour: i}, tp_inst._defaults);994 }995 else if (unit === 'millisec' || unit === 'microsec' || i >= 10) { sel += i; }996 else {sel += '0' + i.toString(); }997 sel += '</option>';998 }999 sel += '</select>';1000 obj.children('select').remove();1001 $(sel).appendTo(obj).change(function (e) {1002 tp_inst._onTimeChange();1003 tp_inst._onSelectHandler();1004 tp_inst._afterInject();1005 });1006 return obj;1007 },1008 options: function (tp_inst, obj, unit, opts, val) {1009 var o = {},1010 $t = obj.children('select');1011 if (typeof(opts) === 'string') {1012 if (val === undefined) {1013 return $t.data(opts);1014 }1015 o[opts] = val;1016 }1017 else { o = opts; }1018 return tp_inst.control.create(tp_inst, obj, $t.data('unit'), $t.val(), o.min>=0 ? o.min : $t.data('min'), o.max || $t.data('max'), o.step || $t.data('step'));1019 },1020 value: function (tp_inst, obj, unit, val) {1021 var $t = obj.children('select');1022 if (val !== undefined) {1023 return $t.val(val);1024 }1025 return $t.val();1026 }1027 }1028 } // end _controls1029 });1030 $.fn.extend({1031 /*1032 * shorthand just to use timepicker.1033 */1034 timepicker: function (o) {1035 o = o || {};1036 var tmp_args = Array.prototype.slice.call(arguments);1037 if (typeof o === 'object') {1038 tmp_args[0] = $.extend(o, {1039 timeOnly: true1040 });1041 }1042 return $(this).each(function () {1043 $.fn.datetimepicker.apply($(this), tmp_args);1044 });1045 },1046 /*1047 * extend timepicker to datepicker1048 */1049 datetimepicker: function (o) {1050 o = o || {};1051 var tmp_args = arguments;1052 if (typeof(o) === 'string') {1053 if (o === 'getDate' || (o === 'option' && tmp_args.length === 2 && typeof (tmp_args[1]) === 'string')) {1054 return $.fn.datepicker.apply($(this[0]), tmp_args);1055 } else {1056 return this.each(function () {1057 var $t = $(this);1058 $t.datepicker.apply($t, tmp_args);1059 });1060 }1061 } else {1062 return this.each(function () {1063 var $t = $(this);1064 $t.datepicker($.timepicker._newInst($t, o)._defaults);1065 });1066 }1067 }1068 });1069 /*1070 * Public Utility to parse date and time1071 */1072 $.datepicker.parseDateTime = function (dateFormat, timeFormat, dateTimeString, dateSettings, timeSettings) {1073 var parseRes = parseDateTimeInternal(dateFormat, timeFormat, dateTimeString, dateSettings, timeSettings);1074 if (parseRes.timeObj) {1075 var t = parseRes.timeObj;1076 parseRes.date.setHours(t.hour, t.minute, t.second, t.millisec);1077 parseRes.date.setMicroseconds(t.microsec);1078 }1079 return parseRes.date;1080 };1081 /*1082 * Public utility to parse time1083 */1084 $.datepicker.parseTime = function (timeFormat, timeString, options) {1085 var o = extendRemove(extendRemove({}, $.timepicker._defaults), options || {}),1086 iso8601 = (timeFormat.replace(/\'.*?\'/g, '').indexOf('Z') !== -1);1087 // Strict parse requires the timeString to match the timeFormat exactly1088 var strictParse = function (f, s, o) {1089 // pattern for standard and localized AM/PM markers1090 var getPatternAmpm = function (amNames, pmNames) {1091 var markers = [];1092 if (amNames) {1093 $.merge(markers, amNames);1094 }1095 if (pmNames) {1096 $.merge(markers, pmNames);1097 }1098 markers = $.map(markers, function (val) {1099 return val.replace(/[.*+?|()\[\]{}\\]/g, '\\$&');1100 });1101 return '(' + markers.join('|') + ')?';1102 };1103 // figure out position of time elements.. cause js cant do named captures1104 var getFormatPositions = function (timeFormat) {1105 var finds = timeFormat.toLowerCase().match(/(h{1,2}|m{1,2}|s{1,2}|l{1}|c{1}|t{1,2}|z|'.*?')/g),1106 orders = {1107 h: -1,1108 m: -1,1109 s: -1,1110 l: -1,1111 c: -1,1112 t: -1,1113 z: -11114 };1115 if (finds) {1116 for (var i = 0; i < finds.length; i++) {1117 if (orders[finds[i].toString().charAt(0)] === -1) {1118 orders[finds[i].toString().charAt(0)] = i + 1;1119 }1120 }1121 }1122 return orders;1123 };1124 var regstr = '^' + f.toString()1125 .replace(/([hH]{1,2}|mm?|ss?|[tT]{1,2}|[zZ]|[lc]|'.*?')/g, function (match) {1126 var ml = match.length;1127 switch (match.charAt(0).toLowerCase()) {1128 case 'h':1129 return ml === 1 ? '(\\d?\\d)' : '(\\d{' + ml + '})';1130 case 'm':1131 return ml === 1 ? '(\\d?\\d)' : '(\\d{' + ml + '})';1132 case 's':1133 return ml === 1 ? '(\\d?\\d)' : '(\\d{' + ml + '})';1134 case 'l':1135 return '(\\d?\\d?\\d)';1136 case 'c':1137 return '(\\d?\\d?\\d)';1138 case 'z':1139 return '(z|[-+]\\d\\d:?\\d\\d|\\S+)?';1140 case 't':1141 return getPatternAmpm(o.amNames, o.pmNames);1142 default: // literal escaped in quotes1143 return '(' + match.replace(/\'/g, "").replace(/(\.|\$|\^|\\|\/|\(|\)|\[|\]|\?|\+|\*)/g, function (m) { return "\\" + m; }) + ')?';1144 }1145 })1146 .replace(/\s/g, '\\s?') +1147 o.timeSuffix + '$',1148 order = getFormatPositions(f),1149 ampm = '',1150 treg;1151 treg = s.match(new RegExp(regstr, 'i'));1152 var resTime = {1153 hour: 0,1154 minute: 0,1155 second: 0,1156 millisec: 0,1157 microsec: 01158 };1159 if (treg) {1160 if (order.t !== -1) {1161 if (treg[order.t] === undefined || treg[order.t].length === 0) {1162 ampm = '';1163 resTime.ampm = '';1164 } else {1165 ampm = $.inArray(treg[order.t].toUpperCase(), $.map(o.amNames, function (x,i) { return x.toUpperCase(); })) !== -1 ? 'AM' : 'PM';1166 resTime.ampm = o[ampm === 'AM' ? 'amNames' : 'pmNames'][0];1167 }1168 }1169 if (order.h !== -1) {1170 if (ampm === 'AM' && treg[order.h] === '12') {1171 resTime.hour = 0; // 12am = 0 hour1172 } else {1173 if (ampm === 'PM' && treg[order.h] !== '12') {1174 resTime.hour = parseInt(treg[order.h], 10) + 12; // 12pm = 12 hour, any other pm = hour + 121175 } else {1176 resTime.hour = Number(treg[order.h]);1177 }1178 }1179 }1180 if (order.m !== -1) {1181 resTime.minute = Number(treg[order.m]);1182 }1183 if (order.s !== -1) {1184 resTime.second = Number(treg[order.s]);1185 }1186 if (order.l !== -1) {1187 resTime.millisec = Number(treg[order.l]);1188 }1189 if (order.c !== -1) {1190 resTime.microsec = Number(treg[order.c]);1191 }1192 if (order.z !== -1 && treg[order.z] !== undefined) {1193 resTime.timezone = $.timepicker.timezoneOffsetNumber(treg[order.z]);1194 }1195 return resTime;1196 }1197 return false;1198 };// end strictParse1199 // First try JS Date, if that fails, use strictParse1200 var looseParse = function (f, s, o) {1201 try {1202 var d = new Date('2012-01-01 ' + s);1203 if (isNaN(d.getTime())) {1204 d = new Date('2012-01-01T' + s);1205 if (isNaN(d.getTime())) {1206 d = new Date('01/01/2012 ' + s);1207 if (isNaN(d.getTime())) {1208 throw "Unable to parse time with native Date: " + s;1209 }1210 }1211 }1212 return {1213 hour: d.getHours(),1214 minute: d.getMinutes(),1215 second: d.getSeconds(),1216 millisec: d.getMilliseconds(),1217 microsec: d.getMicroseconds(),1218 timezone: d.getTimezoneOffset() * -11219 };1220 }1221 catch (err) {1222 try {1223 return strictParse(f, s, o);1224 }1225 catch (err2) {1226 $.timepicker.log("Unable to parse \ntimeString: " + s + "\ntimeFormat: " + f);1227 }1228 }1229 return false;1230 }; // end looseParse1231 if (typeof o.parse === "function") {1232 return o.parse(timeFormat, timeString, o);1233 }1234 if (o.parse === 'loose') {1235 return looseParse(timeFormat, timeString, o);1236 }1237 return strictParse(timeFormat, timeString, o);1238 };1239 /**1240 * Public utility to format the time1241 * @param {string} format format of the time1242 * @param {Object} time Object not a Date for timezones1243 * @param {Object} [options] essentially the regional[].. amNames, pmNames, ampm1244 * @returns {string} the formatted time1245 */1246 $.datepicker.formatTime = function (format, time, options) {1247 options = options || {};1248 options = $.extend({}, $.timepicker._defaults, options);1249 time = $.extend({1250 hour: 0,1251 minute: 0,1252 second: 0,1253 millisec: 0,1254 microsec: 0,1255 timezone: null1256 }, time);1257 var tmptime = format,1258 ampmName = options.amNames[0],1259 hour = parseInt(time.hour, 10);1260 if (hour > 11) {1261 ampmName = options.pmNames[0];1262 }1263 tmptime = tmptime.replace(/(?:HH?|hh?|mm?|ss?|[tT]{1,2}|[zZ]|[lc]|'.*?')/g, function (match) {1264 switch (match) {1265 case 'HH':1266 return ('0' + hour).slice(-2);1267 case 'H':1268 return hour;1269 case 'hh':1270 return ('0' + convert24to12(hour)).slice(-2);1271 case 'h':1272 return convert24to12(hour);1273 case 'mm':1274 return ('0' + time.minute).slice(-2);1275 case 'm':1276 return time.minute;1277 case 'ss':1278 return ('0' + time.second).slice(-2);1279 case 's':1280 return time.second;1281 case 'l':1282 return ('00' + time.millisec).slice(-3);1283 case 'c':1284 return ('00' + time.microsec).slice(-3);1285 case 'z':1286 return $.timepicker.timezoneOffsetString(time.timezone === null ? options.timezone : time.timezone, false);1287 case 'Z':1288 return $.timepicker.timezoneOffsetString(time.timezone === null ? options.timezone : time.timezone, true);1289 case 'T':1290 return ampmName.charAt(0).toUpperCase();1291 case 'TT':1292 return ampmName.toUpperCase();1293 case 't':1294 return ampmName.charAt(0).toLowerCase();1295 case 'tt':1296 return ampmName.toLowerCase();1297 default:1298 return match.replace(/'/g, "");1299 }1300 });1301 return tmptime;1302 };1303 /*1304 * the bad hack :/ override datepicker so it doesn't close on select1305 // inspired: http://stackoverflow.com/questions/1252512/jquery-datepicker-prevent-closing-picker-when-clicking-a-date/1762378#17623781306 */1307 $.datepicker._base_selectDate = $.datepicker._selectDate;1308 $.datepicker._selectDate = function (id, dateStr) {1309 var inst = this._getInst($(id)[0]),1310 tp_inst = this._get(inst, 'timepicker'),1311 was_inline;1312 if (tp_inst && inst.settings.showTimepicker) {1313 tp_inst._limitMinMaxDateTime(inst, true);1314 was_inline = inst.inline;1315 inst.inline = inst.stay_open = true;1316 //This way the onSelect handler called from calendarpicker get the full dateTime1317 this._base_selectDate(id, dateStr);1318 inst.inline = was_inline;1319 inst.stay_open = false;1320 this._notifyChange(inst);1321 this._updateDatepicker(inst);1322 } else {1323 this._base_selectDate(id, dateStr);1324 }1325 };1326 /*1327 * second bad hack :/ override datepicker so it triggers an event when changing the input field1328 * and does not redraw the datepicker on every selectDate event1329 */1330 $.datepicker._base_updateDatepicker = $.datepicker._updateDatepicker;1331 $.datepicker._updateDatepicker = function (inst) {1332 // don't popup the datepicker if there is another instance already opened1333 var input = inst.input[0];1334 if ($.datepicker._curInst && $.datepicker._curInst !== inst && $.datepicker._datepickerShowing && $.datepicker._lastInput !== input) {1335 return;1336 }1337 if (typeof(inst.stay_open) !== 'boolean' || inst.stay_open === false) {1338 this._base_updateDatepicker(inst);1339 // Reload the time control when changing something in the input text field.1340 var tp_inst = this._get(inst, 'timepicker');1341 if (tp_inst) {1342 tp_inst._addTimePicker(inst);1343 }1344 }1345 };1346 /*1347 * third bad hack :/ override datepicker so it allows spaces and colon in the input field1348 */1349 $.datepicker._base_doKeyPress = $.datepicker._doKeyPress;1350 $.datepicker._doKeyPress = function (event) {1351 var inst = $.datepicker._getInst(event.target),1352 tp_inst = $.datepicker._get(inst, 'timepicker');1353 if (tp_inst) {1354 if ($.datepicker._get(inst, 'constrainInput')) {1355 var ampm = tp_inst.support.ampm,1356 tz = tp_inst._defaults.showTimezone !== null ? tp_inst._defaults.showTimezone : tp_inst.support.timezone,1357 dateChars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat')),1358 datetimeChars = tp_inst._defaults.timeFormat.toString()1359 .replace(/[hms]/g, '')1360 .replace(/TT/g, ampm ? 'APM' : '')1361 .replace(/Tt/g, ampm ? 'AaPpMm' : '')1362 .replace(/tT/g, ampm ? 'AaPpMm' : '')1363 .replace(/T/g, ampm ? 'AP' : '')1364 .replace(/tt/g, ampm ? 'apm' : '')1365 .replace(/t/g, ampm ? 'ap' : '') +1366 " " + tp_inst._defaults.separator +1367 tp_inst._defaults.timeSuffix +1368 (tz ? tp_inst._defaults.timezoneList.join('') : '') +1369 (tp_inst._defaults.amNames.join('')) + (tp_inst._defaults.pmNames.join('')) +1370 dateChars,1371 chr = String.fromCharCode(event.charCode === undefined ? event.keyCode : event.charCode);1372 return event.ctrlKey || (chr < ' ' || !dateChars || datetimeChars.indexOf(chr) > -1);1373 }1374 }1375 return $.datepicker._base_doKeyPress(event);1376 };1377 /*1378 * Fourth bad hack :/ override _updateAlternate function used in inline mode to init altField1379 * Update any alternate field to synchronise with the main field.1380 */1381 $.datepicker._base_updateAlternate = $.datepicker._updateAlternate;1382 $.datepicker._updateAlternate = function (inst) {1383 var tp_inst = this._get(inst, 'timepicker');1384 if (tp_inst) {1385 var altField = tp_inst._defaults.altField;1386 if (altField) { // update alternate field too1387 var altFormat = tp_inst._defaults.altFormat || tp_inst._defaults.dateFormat,1388 date = this._getDate(inst),1389 formatCfg = $.datepicker._getFormatConfig(inst),1390 altFormattedDateTime = '',1391 altSeparator = tp_inst._defaults.altSeparator ? tp_inst._defaults.altSeparator : tp_inst._defaults.separator,1392 altTimeSuffix = tp_inst._defaults.altTimeSuffix ? tp_inst._defaults.altTimeSuffix : tp_inst._defaults.timeSuffix,1393 altTimeFormat = tp_inst._defaults.altTimeFormat !== null ? tp_inst._defaults.altTimeFormat : tp_inst._defaults.timeFormat;1394 altFormattedDateTime += $.datepicker.formatTime(altTimeFormat, tp_inst, tp_inst._defaults) + altTimeSuffix;1395 if (!tp_inst._defaults.timeOnly && !tp_inst._defaults.altFieldTimeOnly && date !== null) {1396 if (tp_inst._defaults.altFormat) {1397 altFormattedDateTime = $.datepicker.formatDate(tp_inst._defaults.altFormat, date, formatCfg) + altSeparator + altFormattedDateTime;1398 }1399 else {1400 altFormattedDateTime = tp_inst.formattedDate + altSeparator + altFormattedDateTime;1401 }1402 }1403 $(altField).val( inst.input.val() ? altFormattedDateTime : "");1404 }1405 }1406 else {1407 $.datepicker._base_updateAlternate(inst);1408 }1409 };1410 /*1411 * Override key up event to sync manual input changes.1412 */1413 $.datepicker._base_doKeyUp = $.datepicker._doKeyUp;1414 $.datepicker._doKeyUp = function (event) {1415 var inst = $.datepicker._getInst(event.target),1416 tp_inst = $.datepicker._get(inst, 'timepicker');1417 if (tp_inst) {1418 if (tp_inst._defaults.timeOnly && (inst.input.val() !== inst.lastVal)) {1419 try {1420 $.datepicker._updateDatepicker(inst);1421 } catch (err) {1422 $.timepicker.log(err);1423 }1424 }1425 }1426 return $.datepicker._base_doKeyUp(event);1427 };1428 /*1429 * override "Today" button to also grab the time and set it to input field.1430 */1431 $.datepicker._base_gotoToday = $.datepicker._gotoToday;1432 $.datepicker._gotoToday = function (id) {1433 var inst = this._getInst($(id)[0]);1434 this._base_gotoToday(id);1435 var tp_inst = this._get(inst, 'timepicker');1436 var tzoffset = $.timepicker.timezoneOffsetNumber(tp_inst.timezone);1437 var now = new Date();1438 now.setMinutes(now.getMinutes() + now.getTimezoneOffset() + tzoffset);1439 this._setTime(inst, now);1440 this._setDate(inst, now);1441 tp_inst._onSelectHandler();1442 };1443 /*1444 * Disable & enable the Time in the datetimepicker1445 */1446 $.datepicker._disableTimepickerDatepicker = function (target) {1447 var inst = this._getInst(target);1448 if (!inst) {1449 return;1450 }1451 var tp_inst = this._get(inst, 'timepicker');1452 $(target).datepicker('getDate'); // Init selected[Year|Month|Day]1453 if (tp_inst) {1454 inst.settings.showTimepicker = false;1455 tp_inst._defaults.showTimepicker = false;1456 tp_inst._updateDateTime(inst);1457 }1458 };1459 $.datepicker._enableTimepickerDatepicker = function (target) {1460 var inst = this._getInst(target);1461 if (!inst) {1462 return;1463 }1464 var tp_inst = this._get(inst, 'timepicker');1465 $(target).datepicker('getDate'); // Init selected[Year|Month|Day]1466 if (tp_inst) {1467 inst.settings.showTimepicker = true;1468 tp_inst._defaults.showTimepicker = true;1469 tp_inst._addTimePicker(inst); // Could be disabled on page load1470 tp_inst._updateDateTime(inst);1471 }1472 };1473 /*1474 * Create our own set time function1475 */1476 $.datepicker._setTime = function (inst, date) {1477 var tp_inst = this._get(inst, 'timepicker');1478 if (tp_inst) {1479 var defaults = tp_inst._defaults;1480 // calling _setTime with no date sets time to defaults1481 tp_inst.hour = date ? date.getHours() : defaults.hour;1482 tp_inst.minute = date ? date.getMinutes() : defaults.minute;1483 tp_inst.second = date ? date.getSeconds() : defaults.second;1484 tp_inst.millisec = date ? date.getMilliseconds() : defaults.millisec;1485 tp_inst.microsec = date ? date.getMicroseconds() : defaults.microsec;1486 //check if within min/max times..1487 tp_inst._limitMinMaxDateTime(inst, true);1488 tp_inst._onTimeChange();1489 tp_inst._updateDateTime(inst);1490 }1491 };1492 /*1493 * Create new public method to set only time, callable as $().datepicker('setTime', date)1494 */1495 $.datepicker._setTimeDatepicker = function (target, date, withDate) {1496 var inst = this._getInst(target);1497 if (!inst) {1498 return;1499 }1500 var tp_inst = this._get(inst, 'timepicker');1501 if (tp_inst) {1502 this._setDateFromField(inst);1503 var tp_date;1504 if (date) {1505 if (typeof date === "string") {1506 tp_inst._parseTime(date, withDate);1507 tp_date = new Date();1508 tp_date.setHours(tp_inst.hour, tp_inst.minute, tp_inst.second, tp_inst.millisec);1509 tp_date.setMicroseconds(tp_inst.microsec);1510 } else {1511 tp_date = new Date(date.getTime());1512 tp_date.setMicroseconds(date.getMicroseconds());1513 }1514 if (tp_date.toString() === 'Invalid Date') {1515 tp_date = undefined;1516 }1517 this._setTime(inst, tp_date);1518 }1519 }1520 };1521 /*1522 * override setDate() to allow setting time too within Date object1523 */1524 $.datepicker._base_setDateDatepicker = $.datepicker._setDateDatepicker;1525 $.datepicker._setDateDatepicker = function (target, _date) {1526 var inst = this._getInst(target);1527 var date = _date;1528 if (!inst) {1529 return;1530 }1531 if (typeof(_date) === 'string') {1532 date = new Date(_date);1533 if (!date.getTime()) {1534 this._base_setDateDatepicker.apply(this, arguments);1535 date = $(target).datepicker('getDate');1536 }1537 }1538 var tp_inst = this._get(inst, 'timepicker');1539 var tp_date;1540 if (date instanceof Date) {1541 tp_date = new Date(date.getTime());1542 tp_date.setMicroseconds(date.getMicroseconds());1543 } else {1544 tp_date = date;1545 }1546 // This is important if you are using the timezone option, javascript's Date1547 // object will only return the timezone offset for the current locale, so we1548 // adjust it accordingly. If not using timezone option this won't matter..1549 // If a timezone is different in tp, keep the timezone as is1550 if (tp_inst && tp_date) {1551 // look out for DST if tz wasn't specified1552 if (!tp_inst.support.timezone && tp_inst._defaults.timezone === null) {1553 tp_inst.timezone = tp_date.getTimezoneOffset() * -1;1554 }1555 date = $.timepicker.timezoneAdjust(date, tp_inst.timezone);1556 tp_date = $.timepicker.timezoneAdjust(tp_date, tp_inst.timezone);1557 }1558 this._updateDatepicker(inst);1559 this._base_setDateDatepicker.apply(this, arguments);1560 this._setTimeDatepicker(target, tp_date, true);1561 };1562 /*1563 * override getDate() to allow getting time too within Date object1564 */1565 $.datepicker._base_getDateDatepicker = $.datepicker._getDateDatepicker;1566 $.datepicker._getDateDatepicker = function (target, noDefault) {1567 var inst = this._getInst(target);1568 if (!inst) {1569 return;1570 }1571 var tp_inst = this._get(inst, 'timepicker');1572 if (tp_inst) {1573 // if it hasn't yet been defined, grab from field1574 if (inst.lastVal === undefined) {1575 this._setDateFromField(inst, noDefault);1576 }1577 var date = this._getDate(inst);1578 var currDT = $.trim((tp_inst.$altInput && tp_inst._defaults.altFieldTimeOnly) ? tp_inst.$input.val() + ' ' + tp_inst.$altInput.val() : tp_inst.$input.val());1579 if (date && tp_inst._parseTime(currDT, !inst.settings.timeOnly)) {1580 date.setHours(tp_inst.hour, tp_inst.minute, tp_inst.second, tp_inst.millisec);1581 date.setMicroseconds(tp_inst.microsec);1582 // This is important if you are using the timezone option, javascript's Date1583 // object will only return the timezone offset for the current locale, so we1584 // adjust it accordingly. If not using timezone option this won't matter..1585 if (tp_inst.timezone != null) {1586 // look out for DST if tz wasn't specified1587 if (!tp_inst.support.timezone && tp_inst._defaults.timezone === null) {1588 tp_inst.timezone = date.getTimezoneOffset() * -1;1589 }1590 date = $.timepicker.timezoneAdjust(date, tp_inst.timezone);1591 }1592 }1593 return date;1594 }1595 return this._base_getDateDatepicker(target, noDefault);1596 };1597 /*1598 * override parseDate() because UI 1.8.14 throws an error about "Extra characters"1599 * An option in datapicker to ignore extra format characters would be nicer.1600 */1601 $.datepicker._base_parseDate = $.datepicker.parseDate;1602 $.datepicker.parseDate = function (format, value, settings) {1603 var date;1604 try {1605 date = this._base_parseDate(format, value, settings);1606 } catch (err) {1607 // Hack! The error message ends with a colon, a space, and1608 // the "extra" characters. We rely on that instead of1609 // attempting to perfectly reproduce the parsing algorithm.1610 if (err.indexOf(":") >= 0) {1611 date = this._base_parseDate(format, value.substring(0, value.length - (err.length - err.indexOf(':') - 2)), settings);1612 $.timepicker.log("Error parsing the date string: " + err + "\ndate string = " + value + "\ndate format = " + format);1613 } else {1614 throw err;1615 }1616 }1617 return date;1618 };1619 /*1620 * override formatDate to set date with time to the input1621 */1622 $.datepicker._base_formatDate = $.datepicker._formatDate;1623 $.datepicker._formatDate = function (inst, day, month, year) {1624 var tp_inst = this._get(inst, 'timepicker');1625 if (tp_inst) {1626 tp_inst._updateDateTime(inst);1627 return tp_inst.$input.val();1628 }1629 return this._base_formatDate(inst);1630 };1631 /*1632 * override options setter to add time to maxDate(Time) and minDate(Time). MaxDate1633 */1634 $.datepicker._base_optionDatepicker = $.datepicker._optionDatepicker;1635 $.datepicker._optionDatepicker = function (target, name, value) {1636 var inst = this._getInst(target),1637 name_clone;1638 if (!inst) {1639 return null;1640 }1641 var tp_inst = this._get(inst, 'timepicker');1642 if (tp_inst) {1643 var min = null,1644 max = null,1645 onselect = null,1646 overrides = tp_inst._defaults.evnts,1647 fns = {},1648 prop,1649 ret,1650 oldVal,1651 $target;1652 if (typeof name === 'string') { // if min/max was set with the string1653 if (name === 'minDate' || name === 'minDateTime') {1654 min = value;1655 } else if (name === 'maxDate' || name === 'maxDateTime') {1656 max = value;1657 } else if (name === 'onSelect') {1658 onselect = value;1659 } else if (overrides.hasOwnProperty(name)) {1660 if (typeof (value) === 'undefined') {1661 return overrides[name];1662 }1663 fns[name] = value;1664 name_clone = {}; //empty results in exiting function after overrides updated1665 }1666 } else if (typeof name === 'object') { //if min/max was set with the JSON1667 if (name.minDate) {1668 min = name.minDate;1669 } else if (name.minDateTime) {1670 min = name.minDateTime;1671 } else if (name.maxDate) {1672 max = name.maxDate;1673 } else if (name.maxDateTime) {1674 max = name.maxDateTime;1675 }1676 for (prop in overrides) {1677 if (overrides.hasOwnProperty(prop) && name[prop]) {1678 fns[prop] = name[prop];1679 }1680 }1681 }1682 for (prop in fns) {1683 if (fns.hasOwnProperty(prop)) {1684 overrides[prop] = fns[prop];1685 if (!name_clone) { name_clone = $.extend({}, name); }1686 delete name_clone[prop];1687 }1688 }1689 if (name_clone && isEmptyObject(name_clone)) { return; }1690 if (min) { //if min was set1691 if (min === 0) {1692 min = new Date();1693 } else {1694 min = new Date(min);1695 }1696 tp_inst._defaults.minDate = min;1697 tp_inst._defaults.minDateTime = min;1698 } else if (max) { //if max was set1699 if (max === 0) {1700 max = new Date();1701 } else {1702 max = new Date(max);1703 }1704 tp_inst._defaults.maxDate = max;1705 tp_inst._defaults.maxDateTime = max;1706 } else if (onselect) {1707 tp_inst._defaults.onSelect = onselect;1708 }1709 // Datepicker will override our date when we call _base_optionDatepicker when1710 // calling minDate/maxDate, so we will first grab the value, call1711 // _base_optionDatepicker, then set our value back.1712 if(min || max){1713 $target = $(target);1714 oldVal = $target.datetimepicker('getDate');1715 ret = this._base_optionDatepicker.call($.datepicker, target, name_clone || name, value);1716 $target.datetimepicker('setDate', oldVal);1717 return ret;1718 }1719 }1720 if (value === undefined) {1721 return this._base_optionDatepicker.call($.datepicker, target, name);1722 }1723 return this._base_optionDatepicker.call($.datepicker, target, name_clone || name, value);1724 };1725 /*1726 * jQuery isEmptyObject does not check hasOwnProperty - if someone has added to the object prototype,1727 * it will return false for all objects1728 */1729 var isEmptyObject = function (obj) {1730 var prop;1731 for (prop in obj) {1732 if (obj.hasOwnProperty(prop)) {1733 return false;1734 }1735 }1736 return true;1737 };1738 /*1739 * jQuery extend now ignores nulls!1740 */1741 var extendRemove = function (target, props) {1742 $.extend(target, props);1743 for (var name in props) {1744 if (props[name] === null || props[name] === undefined) {1745 target[name] = props[name];1746 }1747 }1748 return target;1749 };1750 /*1751 * Determine by the time format which units are supported1752 * Returns an object of booleans for each unit1753 */1754 var detectSupport = function (timeFormat) {1755 var tf = timeFormat.replace(/'.*?'/g, '').toLowerCase(), // removes literals1756 isIn = function (f, t) { // does the format contain the token?1757 return f.indexOf(t) !== -1 ? true : false;1758 };1759 return {1760 hour: isIn(tf, 'h'),1761 minute: isIn(tf, 'm'),1762 second: isIn(tf, 's'),1763 millisec: isIn(tf, 'l'),1764 microsec: isIn(tf, 'c'),1765 timezone: isIn(tf, 'z'),1766 ampm: isIn(tf, 't') && isIn(timeFormat, 'h'),1767 iso8601: isIn(timeFormat, 'Z')1768 };1769 };1770 /*1771 * Converts 24 hour format into 12 hour1772 * Returns 12 hour without leading 01773 */1774 var convert24to12 = function (hour) {1775 hour %= 12;1776 if (hour === 0) {1777 hour = 12;1778 }1779 return String(hour);1780 };1781 var computeEffectiveSetting = function (settings, property) {1782 return settings && settings[property] ? settings[property] : $.timepicker._defaults[property];1783 };1784 /*1785 * Splits datetime string into date and time substrings.1786 * Throws exception when date can't be parsed1787 * Returns {dateString: dateString, timeString: timeString}1788 */1789 var splitDateTime = function (dateTimeString, timeSettings) {1790 // The idea is to get the number separator occurrences in datetime and the time format requested (since time has1791 // fewer unknowns, mostly numbers and am/pm). We will use the time pattern to split.1792 var separator = computeEffectiveSetting(timeSettings, 'separator'),1793 format = computeEffectiveSetting(timeSettings, 'timeFormat'),1794 timeParts = format.split(separator), // how many occurrences of separator may be in our format?1795 timePartsLen = timeParts.length,1796 allParts = dateTimeString.split(separator),1797 allPartsLen = allParts.length;1798 if (allPartsLen > 1) {1799 return {1800 dateString: allParts.splice(0, allPartsLen - timePartsLen).join(separator),1801 timeString: allParts.splice(0, timePartsLen).join(separator)1802 };1803 }1804 return {1805 dateString: dateTimeString,1806 timeString: ''1807 };1808 };1809 /*1810 * Internal function to parse datetime interval1811 * Returns: {date: Date, timeObj: Object}, where1812 * date - parsed date without time (type Date)1813 * timeObj = {hour: , minute: , second: , millisec: , microsec: } - parsed time. Optional1814 */1815 var parseDateTimeInternal = function (dateFormat, timeFormat, dateTimeString, dateSettings, timeSettings) {1816 var date,1817 parts,1818 parsedTime;1819 parts = splitDateTime(dateTimeString, timeSettings);1820 date = $.datepicker._base_parseDate(dateFormat, parts.dateString, dateSettings);1821 if (parts.timeString === '') {1822 return {1823 date: date1824 };1825 }1826 parsedTime = $.datepicker.parseTime(timeFormat, parts.timeString, timeSettings);1827 if (!parsedTime) {1828 throw 'Wrong time format';1829 }1830 return {1831 date: date,1832 timeObj: parsedTime1833 };1834 };1835 /*1836 * Internal function to set timezone_select to the local timezone1837 */1838 var selectLocalTimezone = function (tp_inst, date) {1839 if (tp_inst && tp_inst.timezone_select) {1840 var now = date || new Date();1841 tp_inst.timezone_select.val(-now.getTimezoneOffset());1842 }1843 };1844 /*1845 * Create a Singleton Instance1846 */1847 $.timepicker = new Timepicker();1848 /**1849 * Get the timezone offset as string from a date object (eg '+0530' for UTC+5.5)1850 * @param {number} tzMinutes if not a number, less than -720 (-1200), or greater than 840 (+1400) this value is returned1851 * @param {boolean} iso8601 if true formats in accordance to iso8601 "+12:45"1852 * @return {string}1853 */1854 $.timepicker.timezoneOffsetString = function (tzMinutes, iso8601) {1855 if (isNaN(tzMinutes) || tzMinutes > 840 || tzMinutes < -720) {1856 return tzMinutes;1857 }1858 var off = tzMinutes,1859 minutes = off % 60,1860 hours = (off - minutes) / 60,1861 iso = iso8601 ? ':' : '',1862 tz = (off >= 0 ? '+' : '-') + ('0' + Math.abs(hours)).slice(-2) + iso + ('0' + Math.abs(minutes)).slice(-2);1863 if (tz === '+00:00') {1864 return 'Z';1865 }1866 return tz;1867 };1868 /**1869 * Get the number in minutes that represents a timezone string1870 * @param {string} tzString formatted like "+0500", "-1245", "Z"1871 * @return {number} the offset minutes or the original string if it doesn't match expectations1872 */1873 $.timepicker.timezoneOffsetNumber = function (tzString) {1874 var normalized = tzString.toString().replace(':', ''); // excuse any iso8601, end up with "+1245"1875 if (normalized.toUpperCase() === 'Z') { // if iso8601 with Z, its 0 minute offset1876 return 0;1877 }1878 if (!/^(\-|\+)\d{4}$/.test(normalized)) { // possibly a user defined tz, so just give it back1879 return tzString;1880 }1881 return ((normalized.substr(0, 1) === '-' ? -1 : 1) * // plus or minus1882 ((parseInt(normalized.substr(1, 2), 10) * 60) + // hours (converted to minutes)1883 parseInt(normalized.substr(3, 2), 10))); // minutes1884 };1885 /**1886 * No way to set timezone in js Date, so we must adjust the minutes to compensate. (think setDate, getDate)1887 * @param {Date} date1888 * @param {string} toTimezone formatted like "+0500", "-1245"1889 * @return {Date}1890 */1891 $.timepicker.timezoneAdjust = function (date, toTimezone) {1892 var toTz = $.timepicker.timezoneOffsetNumber(toTimezone);1893 if (!isNaN(toTz)) {1894 date.setMinutes(date.getMinutes() + -date.getTimezoneOffset() - toTz);1895 }1896 return date;1897 };1898 /**1899 * Calls `timepicker()` on the `startTime` and `endTime` elements, and configures them to1900 * enforce date range limits.1901 * n.b. The input value must be correctly formatted (reformatting is not supported)1902 * @param {Element} startTime1903 * @param {Element} endTime1904 * @param {Object} options Options for the timepicker() call1905 * @return {jQuery}1906 */1907 $.timepicker.timeRange = function (startTime, endTime, options) {1908 return $.timepicker.handleRange('timepicker', startTime, endTime, options);1909 };1910 /**1911 * Calls `datetimepicker` on the `startTime` and `endTime` elements, and configures them to1912 * enforce date range limits.1913 * @param {Element} startTime1914 * @param {Element} endTime1915 * @param {Object} options Options for the `timepicker()` call. Also supports `reformat`,1916 * a boolean value that can be used to reformat the input values to the `dateFormat`.1917 * @param {string} method Can be used to specify the type of picker to be added1918 * @return {jQuery}1919 */1920 $.timepicker.datetimeRange = function (startTime, endTime, options) {1921 $.timepicker.handleRange('datetimepicker', startTime, endTime, options);1922 };1923 /**1924 * Calls `datepicker` on the `startTime` and `endTime` elements, and configures them to1925 * enforce date range limits.1926 * @param {Element} startTime1927 * @param {Element} endTime1928 * @param {Object} options Options for the `timepicker()` call. Also supports `reformat`,1929 * a boolean value that can be used to reformat the input values to the `dateFormat`.1930 * @return {jQuery}1931 */1932 $.timepicker.dateRange = function (startTime, endTime, options) {1933 $.timepicker.handleRange('datepicker', startTime, endTime, options);1934 };1935 /**1936 * Calls `method` on the `startTime` and `endTime` elements, and configures them to1937 * enforce date range limits.1938 * @param {string} method Can be used to specify the type of picker to be added1939 * @param {Element} startTime1940 * @param {Element} endTime1941 * @param {Object} options Options for the `timepicker()` call. Also supports `reformat`,1942 * a boolean value that can be used to reformat the input values to the `dateFormat`.1943 * @return {jQuery}1944 */1945 $.timepicker.handleRange = function (method, startTime, endTime, options) {1946 options = $.extend({}, {1947 minInterval: 0, // min allowed interval in milliseconds1948 maxInterval: 0, // max allowed interval in milliseconds1949 start: {}, // options for start picker1950 end: {} // options for end picker1951 }, options);1952 // for the mean time this fixes an issue with calling getDate with timepicker()1953 var timeOnly = false;1954 if(method === 'timepicker'){1955 timeOnly = true;1956 method = 'datetimepicker';1957 }1958 function checkDates(changed, other) {1959 var startdt = startTime[method]('getDate'),1960 enddt = endTime[method]('getDate'),1961 changeddt = changed[method]('getDate');1962 if (startdt !== null) {1963 var minDate = new Date(startdt.getTime()),1964 maxDate = new Date(startdt.getTime());1965 minDate.setMilliseconds(minDate.getMilliseconds() + options.minInterval);1966 maxDate.setMilliseconds(maxDate.getMilliseconds() + options.maxInterval);1967 if (options.minInterval > 0 && minDate > enddt) { // minInterval check1968 endTime[method]('setDate', minDate);1969 }1970 else if (options.maxInterval > 0 && maxDate < enddt) { // max interval check1971 endTime[method]('setDate', maxDate);1972 }1973 else if (startdt > enddt) {1974 other[method]('setDate', changeddt);1975 }1976 }1977 }1978 function selected(changed, other, option) {1979 if (!changed.val()) {1980 return;1981 }1982 var date = changed[method].call(changed, 'getDate');1983 if (date !== null && options.minInterval > 0) {1984 if (option === 'minDate') {1985 date.setMilliseconds(date.getMilliseconds() + options.minInterval);1986 }1987 if (option === 'maxDate') {1988 date.setMilliseconds(date.getMilliseconds() - options.minInterval);1989 }1990 }1991 if (date.getTime) {1992 other[method].call(other, 'option', option, date);1993 }1994 }1995 $.fn[method].call(startTime, $.extend({1996 timeOnly: timeOnly,1997 onClose: function (dateText, inst) {1998 checkDates($(this), endTime);1999 },2000 onSelect: function (selectedDateTime) {2001 selected($(this), endTime, 'minDate');2002 }2003 }, options, options.start));2004 $.fn[method].call(endTime, $.extend({2005 timeOnly: timeOnly,2006 onClose: function (dateText, inst) {2007 checkDates($(this), startTime);2008 },2009 onSelect: function (selectedDateTime) {2010 selected($(this), startTime, 'maxDate');2011 }2012 }, options, options.end));2013 checkDates(startTime, endTime);2014 selected(startTime, endTime, 'minDate');2015 selected(endTime, startTime, 'maxDate');2016 return $([startTime.get(0), endTime.get(0)]);2017 };2018 /**2019 * Log error or data to the console during error or debugging2020 * @param {Object} err pass any type object to log to the console during error or debugging2021 * @return {void}2022 */2023 $.timepicker.log = function () {2024 if (window.console) {2025 window.console.log.apply(window.console, Array.prototype.slice.call(arguments));2026 }2027 };2028 /*2029 * Add util object to allow access to private methods for testability.2030 */2031 $.timepicker._util = {2032 _extendRemove: extendRemove,2033 _isEmptyObject: isEmptyObject,2034 _convert24to12: convert24to12,2035 _detectSupport: detectSupport,2036 _selectLocalTimezone: selectLocalTimezone,2037 _computeEffectiveSetting: computeEffectiveSetting,2038 _splitDateTime: splitDateTime,2039 _parseDateTimeInternal: parseDateTimeInternal2040 };2041 /*2042 * Microsecond support2043 */2044 if (!Date.prototype.getMicroseconds) {2045 Date.prototype.microseconds = 0;2046 Date.prototype.getMicroseconds = function () { return this.microseconds; };2047 Date.prototype.setMicroseconds = function (m) {2048 this.setMilliseconds(this.getMilliseconds() + Math.floor(m / 1000));2049 this.microseconds = m % 1000;2050 return this;2051 };2052 }2053 /*2054 * Keep up with the version2055 */2056 $.timepicker.version = "1.6.1";...
jquery.timepicker.js
Source:jquery.timepicker.js
1/*! jQuery Timepicker Addon - v1.5.5 - 2015-05-242* http://trentrichardson.com/examples/timepicker3* Copyright (c) 2015 Trent Richardson; Licensed MIT */4(function (factory) {5 if (typeof define === 'function' && define.amd) {6 define(['jquery', 'jquery.ui'], factory);7 } else {8 factory(jQuery);9 }10}(function ($) {1112 /*13 * Lets not redefine timepicker, Prevent "Uncaught RangeError: Maximum call stack size exceeded"14 */15 $.ui.timepicker = $.ui.timepicker || {};16 if ($.ui.timepicker.version) {17 return;18 }1920 /*21 * Extend jQueryUI, get it started with our version number22 */23 $.extend($.ui, {24 timepicker: {25 version: "1.5.5"26 }27 });2829 /* 30 * Timepicker manager.31 * Use the singleton instance of this class, $.timepicker, to interact with the time picker.32 * Settings for (groups of) time pickers are maintained in an instance object,33 * allowing multiple different settings on the same page.34 */35 var Timepicker = function () {36 this.regional = []; // Available regional settings, indexed by language code37 this.regional[''] = { // Default regional settings38 currentText: 'Now',39 closeText: 'Done',40 amNames: ['AM', 'A'],41 pmNames: ['PM', 'P'],42 timeFormat: 'HH:mm',43 timeSuffix: '',44 timeOnlyTitle: 'Choose Time',45 timeText: 'Time',46 hourText: 'Hour',47 minuteText: 'Minute',48 secondText: 'Second',49 millisecText: 'Millisecond',50 microsecText: 'Microsecond',51 timezoneText: 'Time Zone',52 isRTL: false53 };54 this._defaults = { // Global defaults for all the datetime picker instances55 showButtonPanel: true,56 timeOnly: false,57 timeOnlyShowDate: false,58 showHour: null,59 showMinute: null,60 showSecond: null,61 showMillisec: null,62 showMicrosec: null,63 showTimezone: null,64 showTime: true,65 stepHour: 1,66 stepMinute: 1,67 stepSecond: 1,68 stepMillisec: 1,69 stepMicrosec: 1,70 hour: 0,71 minute: 0,72 second: 0,73 millisec: 0,74 microsec: 0,75 timezone: null,76 hourMin: 0,77 minuteMin: 0,78 secondMin: 0,79 millisecMin: 0,80 microsecMin: 0,81 hourMax: 23,82 minuteMax: 59,83 secondMax: 59,84 millisecMax: 999,85 microsecMax: 999,86 minDateTime: null,87 maxDateTime: null,88 maxTime: null,89 minTime: null,90 onSelect: null,91 hourGrid: 0,92 minuteGrid: 0,93 secondGrid: 0,94 millisecGrid: 0,95 microsecGrid: 0,96 alwaysSetTime: true,97 separator: ' ',98 altFieldTimeOnly: true,99 altTimeFormat: null,100 altSeparator: null,101 altTimeSuffix: null,102 altRedirectFocus: true,103 pickerTimeFormat: null,104 pickerTimeSuffix: null,105 showTimepicker: true,106 timezoneList: null,107 addSliderAccess: false,108 sliderAccessArgs: null,109 controlType: 'slider',110 oneLine: false,111 defaultValue: null,112 parse: 'strict',113 afterInject: null114 };115 $.extend(this._defaults, this.regional['']);116 };117118 $.extend(Timepicker.prototype, {119 $input: null,120 $altInput: null,121 $timeObj: null,122 inst: null,123 hour_slider: null,124 minute_slider: null,125 second_slider: null,126 millisec_slider: null,127 microsec_slider: null,128 timezone_select: null,129 maxTime: null,130 minTime: null,131 hour: 0,132 minute: 0,133 second: 0,134 millisec: 0,135 microsec: 0,136 timezone: null,137 hourMinOriginal: null,138 minuteMinOriginal: null,139 secondMinOriginal: null,140 millisecMinOriginal: null,141 microsecMinOriginal: null,142 hourMaxOriginal: null,143 minuteMaxOriginal: null,144 secondMaxOriginal: null,145 millisecMaxOriginal: null,146 microsecMaxOriginal: null,147 ampm: '',148 formattedDate: '',149 formattedTime: '',150 formattedDateTime: '',151 timezoneList: null,152 units: ['hour', 'minute', 'second', 'millisec', 'microsec'],153 support: {},154 control: null,155156 /* 157 * Override the default settings for all instances of the time picker.158 * @param {Object} settings object - the new settings to use as defaults (anonymous object)159 * @return {Object} the manager object160 */161 setDefaults: function (settings) {162 extendRemove(this._defaults, settings || {});163 return this;164 },165166 /*167 * Create a new Timepicker instance168 */169 _newInst: function ($input, opts) {170 var tp_inst = new Timepicker(),171 inlineSettings = {},172 fns = {},173 overrides, i;174175 for (var attrName in this._defaults) {176 if (this._defaults.hasOwnProperty(attrName)) {177 var attrValue = $input.attr('time:' + attrName);178 if (attrValue) {179 try {180 inlineSettings[attrName] = eval(attrValue);181 } catch (err) {182 inlineSettings[attrName] = attrValue;183 }184 }185 }186 }187188 overrides = {189 beforeShow: function (input, dp_inst) {190 if ($.isFunction(tp_inst._defaults.evnts.beforeShow)) {191 return tp_inst._defaults.evnts.beforeShow.call($input[0], input, dp_inst, tp_inst);192 }193 },194 onChangeMonthYear: function (year, month, dp_inst) {195 // Update the time as well : this prevents the time from disappearing from the $input field.196 // tp_inst._updateDateTime(dp_inst);197 if ($.isFunction(tp_inst._defaults.evnts.onChangeMonthYear)) {198 tp_inst._defaults.evnts.onChangeMonthYear.call($input[0], year, month, dp_inst, tp_inst);199 }200 },201 onClose: function (dateText, dp_inst) {202 if (tp_inst.timeDefined === true && $input.val() !== '') {203 tp_inst._updateDateTime(dp_inst);204 }205 if ($.isFunction(tp_inst._defaults.evnts.onClose)) {206 tp_inst._defaults.evnts.onClose.call($input[0], dateText, dp_inst, tp_inst);207 }208 }209 };210 for (i in overrides) {211 if (overrides.hasOwnProperty(i)) {212 fns[i] = opts[i] || this._defaults[i] || null;213 }214 }215216 tp_inst._defaults = $.extend({}, this._defaults, inlineSettings, opts, overrides, {217 evnts: fns,218 timepicker: tp_inst // add timepicker as a property of datepicker: $.datepicker._get(dp_inst, 'timepicker');219 });220 tp_inst.amNames = $.map(tp_inst._defaults.amNames, function (val) {221 return val.toUpperCase();222 });223 tp_inst.pmNames = $.map(tp_inst._defaults.pmNames, function (val) {224 return val.toUpperCase();225 });226227 // detect which units are supported228 tp_inst.support = detectSupport(229 tp_inst._defaults.timeFormat + 230 (tp_inst._defaults.pickerTimeFormat ? tp_inst._defaults.pickerTimeFormat : '') +231 (tp_inst._defaults.altTimeFormat ? tp_inst._defaults.altTimeFormat : ''));232233 // controlType is string - key to our this._controls234 if (typeof(tp_inst._defaults.controlType) === 'string') {235 if (tp_inst._defaults.controlType === 'slider' && typeof($.ui.slider) === 'undefined') {236 tp_inst._defaults.controlType = 'select';237 }238 tp_inst.control = tp_inst._controls[tp_inst._defaults.controlType];239 }240 // controlType is an object and must implement create, options, value methods241 else {242 tp_inst.control = tp_inst._defaults.controlType;243 }244245 // prep the timezone options246 var timezoneList = [-720, -660, -600, -570, -540, -480, -420, -360, -300, -270, -240, -210, -180, -120, -60,247 0, 60, 120, 180, 210, 240, 270, 300, 330, 345, 360, 390, 420, 480, 525, 540, 570, 600, 630, 660, 690, 720, 765, 780, 840];248 if (tp_inst._defaults.timezoneList !== null) {249 timezoneList = tp_inst._defaults.timezoneList;250 }251 var tzl = timezoneList.length, tzi = 0, tzv = null;252 if (tzl > 0 && typeof timezoneList[0] !== 'object') {253 for (; tzi < tzl; tzi++) {254 tzv = timezoneList[tzi];255 timezoneList[tzi] = { value: tzv, label: $.timepicker.timezoneOffsetString(tzv, tp_inst.support.iso8601) };256 }257 }258 tp_inst._defaults.timezoneList = timezoneList;259260 // set the default units261 tp_inst.timezone = tp_inst._defaults.timezone !== null ? $.timepicker.timezoneOffsetNumber(tp_inst._defaults.timezone) :262 ((new Date()).getTimezoneOffset() * -1);263 tp_inst.hour = tp_inst._defaults.hour < tp_inst._defaults.hourMin ? tp_inst._defaults.hourMin :264 tp_inst._defaults.hour > tp_inst._defaults.hourMax ? tp_inst._defaults.hourMax : tp_inst._defaults.hour;265 tp_inst.minute = tp_inst._defaults.minute < tp_inst._defaults.minuteMin ? tp_inst._defaults.minuteMin :266 tp_inst._defaults.minute > tp_inst._defaults.minuteMax ? tp_inst._defaults.minuteMax : tp_inst._defaults.minute;267 tp_inst.second = tp_inst._defaults.second < tp_inst._defaults.secondMin ? tp_inst._defaults.secondMin :268 tp_inst._defaults.second > tp_inst._defaults.secondMax ? tp_inst._defaults.secondMax : tp_inst._defaults.second;269 tp_inst.millisec = tp_inst._defaults.millisec < tp_inst._defaults.millisecMin ? tp_inst._defaults.millisecMin :270 tp_inst._defaults.millisec > tp_inst._defaults.millisecMax ? tp_inst._defaults.millisecMax : tp_inst._defaults.millisec;271 tp_inst.microsec = tp_inst._defaults.microsec < tp_inst._defaults.microsecMin ? tp_inst._defaults.microsecMin :272 tp_inst._defaults.microsec > tp_inst._defaults.microsecMax ? tp_inst._defaults.microsecMax : tp_inst._defaults.microsec;273 tp_inst.ampm = '';274 tp_inst.$input = $input;275276 if (tp_inst._defaults.altField) {277 tp_inst.$altInput = $(tp_inst._defaults.altField);278 if (tp_inst._defaults.altRedirectFocus === true) {279 tp_inst.$altInput.css({280 cursor: 'pointer'281 }).focus(function () {282 $input.trigger("focus");283 });284 }285 }286287 if (tp_inst._defaults.minDate === 0 || tp_inst._defaults.minDateTime === 0) {288 tp_inst._defaults.minDate = new Date();289 }290 if (tp_inst._defaults.maxDate === 0 || tp_inst._defaults.maxDateTime === 0) {291 tp_inst._defaults.maxDate = new Date();292 }293294 // datepicker needs minDate/maxDate, timepicker needs minDateTime/maxDateTime..295 if (tp_inst._defaults.minDate !== undefined && tp_inst._defaults.minDate instanceof Date) {296 tp_inst._defaults.minDateTime = new Date(tp_inst._defaults.minDate.getTime());297 }298 if (tp_inst._defaults.minDateTime !== undefined && tp_inst._defaults.minDateTime instanceof Date) {299 tp_inst._defaults.minDate = new Date(tp_inst._defaults.minDateTime.getTime());300 }301 if (tp_inst._defaults.maxDate !== undefined && tp_inst._defaults.maxDate instanceof Date) {302 tp_inst._defaults.maxDateTime = new Date(tp_inst._defaults.maxDate.getTime());303 }304 if (tp_inst._defaults.maxDateTime !== undefined && tp_inst._defaults.maxDateTime instanceof Date) {305 tp_inst._defaults.maxDate = new Date(tp_inst._defaults.maxDateTime.getTime());306 }307 tp_inst.$input.bind('focus', function () {308 tp_inst._onFocus();309 });310311 return tp_inst;312 },313314 /*315 * add our sliders to the calendar316 */317 _addTimePicker: function (dp_inst) {318 var currDT = $.trim((this.$altInput && this._defaults.altFieldTimeOnly) ? this.$input.val() + ' ' + this.$altInput.val() : this.$input.val());319320 this.timeDefined = this._parseTime(currDT);321 this._limitMinMaxDateTime(dp_inst, false);322 this._injectTimePicker();323 this._afterInject();324 },325326 /*327 * parse the time string from input value or _setTime328 */329 _parseTime: function (timeString, withDate) {330 if (!this.inst) {331 this.inst = $.datepicker._getInst(this.$input[0]);332 }333334 if (withDate || !this._defaults.timeOnly) {335 var dp_dateFormat = $.datepicker._get(this.inst, 'dateFormat');336 try {337 var parseRes = parseDateTimeInternal(dp_dateFormat, this._defaults.timeFormat, timeString, $.datepicker._getFormatConfig(this.inst), this._defaults);338 if (!parseRes.timeObj) {339 return false;340 }341 $.extend(this, parseRes.timeObj);342 } catch (err) {343 $.timepicker.log("Error parsing the date/time string: " + err +344 "\ndate/time string = " + timeString +345 "\ntimeFormat = " + this._defaults.timeFormat +346 "\ndateFormat = " + dp_dateFormat);347 return false;348 }349 return true;350 } else {351 var timeObj = $.datepicker.parseTime(this._defaults.timeFormat, timeString, this._defaults);352 if (!timeObj) {353 return false;354 }355 $.extend(this, timeObj);356 return true;357 }358 },359360 /*361 * Handle callback option after injecting timepicker362 */363 _afterInject: function() {364 var o = this.inst.settings;365 if ($.isFunction(o.afterInject)) {366 o.afterInject.call(this);367 }368 },369370 /*371 * generate and inject html for timepicker into ui datepicker372 */373 _injectTimePicker: function () {374 var $dp = this.inst.dpDiv,375 o = this.inst.settings,376 tp_inst = this,377 litem = '',378 uitem = '',379 show = null,380 max = {},381 gridSize = {},382 size = null,383 i = 0,384 l = 0;385386 // Prevent displaying twice387 if ($dp.find("div.ui-timepicker-div").length === 0 && o.showTimepicker) {388 var noDisplay = ' ui_tpicker_unit_hide',389 html = '<div class="ui-timepicker-div' + (o.isRTL ? ' ui-timepicker-rtl' : '') + (o.oneLine && o.controlType === 'select' ? ' ui-timepicker-oneLine' : '') + '"><dl>' + '<dt class="ui_tpicker_time_label' + ((o.showTime) ? '' : noDisplay) + '">' + o.timeText + '</dt>' +390 '<dd class="ui_tpicker_time '+ ((o.showTime) ? '' : noDisplay) + '"></dd>';391392 // Create the markup393 for (i = 0, l = this.units.length; i < l; i++) {394 litem = this.units[i];395 uitem = litem.substr(0, 1).toUpperCase() + litem.substr(1);396 show = o['show' + uitem] !== null ? o['show' + uitem] : this.support[litem];397398 // Added by Peter Medeiros:399 // - Figure out what the hour/minute/second max should be based on the step values.400 // - Example: if stepMinute is 15, then minMax is 45.401 max[litem] = parseInt((o[litem + 'Max'] - ((o[litem + 'Max'] - o[litem + 'Min']) % o['step' + uitem])), 10);402 gridSize[litem] = 0;403404 html += '<dt class="ui_tpicker_' + litem + '_label' + (show ? '' : noDisplay) + '">' + o[litem + 'Text'] + '</dt>' +405 '<dd class="ui_tpicker_' + litem + (show ? '' : noDisplay) + '"><div class="ui_tpicker_' + litem + '_slider' + (show ? '' : noDisplay) + '"></div>';406407 if (show && o[litem + 'Grid'] > 0) {408 html += '<div style="padding-left: 1px"><table class="ui-tpicker-grid-label"><tr>';409410 if (litem === 'hour') {411 for (var h = o[litem + 'Min']; h <= max[litem]; h += parseInt(o[litem + 'Grid'], 10)) {412 gridSize[litem]++;413 var tmph = $.datepicker.formatTime(this.support.ampm ? 'hht' : 'HH', {hour: h}, o);414 html += '<td data-for="' + litem + '">' + tmph + '</td>';415 }416 }417 else {418 for (var m = o[litem + 'Min']; m <= max[litem]; m += parseInt(o[litem + 'Grid'], 10)) {419 gridSize[litem]++;420 html += '<td data-for="' + litem + '">' + ((m < 10) ? '0' : '') + m + '</td>';421 }422 }423424 html += '</tr></table></div>';425 }426 html += '</dd>';427 }428 429 // Timezone430 var showTz = o.showTimezone !== null ? o.showTimezone : this.support.timezone;431 html += '<dt class="ui_tpicker_timezone_label' + (showTz ? '' : noDisplay) + '">' + o.timezoneText + '</dt>';432 html += '<dd class="ui_tpicker_timezone' + (showTz ? '' : noDisplay) + '"></dd>';433434 // Create the elements from string435 html += '</dl></div>';436 var $tp = $(html);437438 // if we only want time picker...439 if (o.timeOnly === true) {440 $tp.prepend('<div class="ui-widget-header ui-helper-clearfix ui-corner-all">' + '<div class="ui-datepicker-title">' + o.timeOnlyTitle + '</div>' + '</div>');441 $dp.find('.ui-datepicker-header, .ui-datepicker-calendar').hide();442 }443 444 // add sliders, adjust grids, add events445 for (i = 0, l = tp_inst.units.length; i < l; i++) {446 litem = tp_inst.units[i];447 uitem = litem.substr(0, 1).toUpperCase() + litem.substr(1);448 show = o['show' + uitem] !== null ? o['show' + uitem] : this.support[litem];449450 // add the slider451 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]);452453 // adjust the grid and add click event454 if (show && o[litem + 'Grid'] > 0) {455 size = 100 * gridSize[litem] * o[litem + 'Grid'] / (max[litem] - o[litem + 'Min']);456 $tp.find('.ui_tpicker_' + litem + ' table').css({457 width: size + "%",458 marginLeft: o.isRTL ? '0' : ((size / (-2 * gridSize[litem])) + "%"),459 marginRight: o.isRTL ? ((size / (-2 * gridSize[litem])) + "%") : '0',460 borderCollapse: 'collapse'461 }).find("td").click(function (e) {462 var $t = $(this),463 h = $t.html(),464 n = parseInt(h.replace(/[^0-9]/g), 10),465 ap = h.replace(/[^apm]/ig),466 f = $t.data('for'); // loses scope, so we use data-for467468 if (f === 'hour') {469 if (ap.indexOf('p') !== -1 && n < 12) {470 n += 12;471 }472 else {473 if (ap.indexOf('a') !== -1 && n === 12) {474 n = 0;475 }476 }477 }478 479 tp_inst.control.value(tp_inst, tp_inst[f + '_slider'], litem, n);480481 tp_inst._onTimeChange();482 tp_inst._onSelectHandler();483 }).css({484 cursor: 'pointer',485 width: (100 / gridSize[litem]) + '%',486 textAlign: 'center',487 overflow: 'hidden'488 });489 } // end if grid > 0490 } // end for loop491492 // Add timezone options493 this.timezone_select = $tp.find('.ui_tpicker_timezone').append('<select></select>').find("select");494 $.fn.append.apply(this.timezone_select,495 $.map(o.timezoneList, function (val, idx) {496 return $("<option />").val(typeof val === "object" ? val.value : val).text(typeof val === "object" ? val.label : val);497 }));498 if (typeof(this.timezone) !== "undefined" && this.timezone !== null && this.timezone !== "") {499 var local_timezone = (new Date(this.inst.selectedYear, this.inst.selectedMonth, this.inst.selectedDay, 12)).getTimezoneOffset() * -1;500 if (local_timezone === this.timezone) {501 selectLocalTimezone(tp_inst);502 } else {503 this.timezone_select.val(this.timezone);504 }505 } else {506 if (typeof(this.hour) !== "undefined" && this.hour !== null && this.hour !== "") {507 this.timezone_select.val(o.timezone);508 } else {509 selectLocalTimezone(tp_inst);510 }511 }512 this.timezone_select.change(function () {513 tp_inst._onTimeChange();514 tp_inst._onSelectHandler();515 tp_inst._afterInject();516 });517 // End timezone options518 519 // inject timepicker into datepicker520 var $buttonPanel = $dp.find('.ui-datepicker-buttonpane');521 if ($buttonPanel.length) {522 $buttonPanel.before($tp);523 } else {524 $dp.append($tp);525 }526527 this.$timeObj = $tp.find('.ui_tpicker_time');528529 if (this.inst !== null) {530 var timeDefined = this.timeDefined;531 this._onTimeChange();532 this.timeDefined = timeDefined;533 }534535 // slideAccess integration: http://trentrichardson.com/2011/11/11/jquery-ui-sliders-and-touch-accessibility/536 if (this._defaults.addSliderAccess) {537 var sliderAccessArgs = this._defaults.sliderAccessArgs,538 rtl = this._defaults.isRTL;539 sliderAccessArgs.isRTL = rtl;540 541 setTimeout(function () { // fix for inline mode542 if ($tp.find('.ui-slider-access').length === 0) {543 $tp.find('.ui-slider:visible').sliderAccess(sliderAccessArgs);544545 // fix any grids since sliders are shorter546 var sliderAccessWidth = $tp.find('.ui-slider-access:eq(0)').outerWidth(true);547 if (sliderAccessWidth) {548 $tp.find('table:visible').each(function () {549 var $g = $(this),550 oldWidth = $g.outerWidth(),551 oldMarginLeft = $g.css(rtl ? 'marginRight' : 'marginLeft').toString().replace('%', ''),552 newWidth = oldWidth - sliderAccessWidth,553 newMarginLeft = ((oldMarginLeft * newWidth) / oldWidth) + '%',554 css = { width: newWidth, marginRight: 0, marginLeft: 0 };555 css[rtl ? 'marginRight' : 'marginLeft'] = newMarginLeft;556 $g.css(css);557 });558 }559 }560 }, 10);561 }562 // end slideAccess integration563564 tp_inst._limitMinMaxDateTime(this.inst, true);565 }566 },567568 /*569 * This function tries to limit the ability to go outside the570 * min/max date range571 */572 _limitMinMaxDateTime: function (dp_inst, adjustSliders) {573 var o = this._defaults,574 dp_date = new Date(dp_inst.selectedYear, dp_inst.selectedMonth, dp_inst.selectedDay);575576 if (!this._defaults.showTimepicker) {577 return;578 } // No time so nothing to check here579580 if ($.datepicker._get(dp_inst, 'minDateTime') !== null && $.datepicker._get(dp_inst, 'minDateTime') !== undefined && dp_date) {581 var minDateTime = $.datepicker._get(dp_inst, 'minDateTime'),582 minDateTimeDate = new Date(minDateTime.getFullYear(), minDateTime.getMonth(), minDateTime.getDate(), 0, 0, 0, 0);583584 if (this.hourMinOriginal === null || this.minuteMinOriginal === null || this.secondMinOriginal === null || this.millisecMinOriginal === null || this.microsecMinOriginal === null) {585 this.hourMinOriginal = o.hourMin;586 this.minuteMinOriginal = o.minuteMin;587 this.secondMinOriginal = o.secondMin;588 this.millisecMinOriginal = o.millisecMin;589 this.microsecMinOriginal = o.microsecMin;590 }591592 if (dp_inst.settings.timeOnly || minDateTimeDate.getTime() === dp_date.getTime()) {593 this._defaults.hourMin = minDateTime.getHours();594 if (this.hour <= this._defaults.hourMin) {595 this.hour = this._defaults.hourMin;596 this._defaults.minuteMin = minDateTime.getMinutes();597 if (this.minute <= this._defaults.minuteMin) {598 this.minute = this._defaults.minuteMin;599 this._defaults.secondMin = minDateTime.getSeconds();600 if (this.second <= this._defaults.secondMin) {601 this.second = this._defaults.secondMin;602 this._defaults.millisecMin = minDateTime.getMilliseconds();603 if (this.millisec <= this._defaults.millisecMin) {604 this.millisec = this._defaults.millisecMin;605 this._defaults.microsecMin = minDateTime.getMicroseconds();606 } else {607 if (this.microsec < this._defaults.microsecMin) {608 this.microsec = this._defaults.microsecMin;609 }610 this._defaults.microsecMin = this.microsecMinOriginal;611 }612 } else {613 this._defaults.millisecMin = this.millisecMinOriginal;614 this._defaults.microsecMin = this.microsecMinOriginal;615 }616 } else {617 this._defaults.secondMin = this.secondMinOriginal;618 this._defaults.millisecMin = this.millisecMinOriginal;619 this._defaults.microsecMin = this.microsecMinOriginal;620 }621 } else {622 this._defaults.minuteMin = this.minuteMinOriginal;623 this._defaults.secondMin = this.secondMinOriginal;624 this._defaults.millisecMin = this.millisecMinOriginal;625 this._defaults.microsecMin = this.microsecMinOriginal;626 }627 } else {628 this._defaults.hourMin = this.hourMinOriginal;629 this._defaults.minuteMin = this.minuteMinOriginal;630 this._defaults.secondMin = this.secondMinOriginal;631 this._defaults.millisecMin = this.millisecMinOriginal;632 this._defaults.microsecMin = this.microsecMinOriginal;633 }634 }635636 if ($.datepicker._get(dp_inst, 'maxDateTime') !== null && $.datepicker._get(dp_inst, 'maxDateTime') !== undefined && dp_date) {637 var maxDateTime = $.datepicker._get(dp_inst, 'maxDateTime'),638 maxDateTimeDate = new Date(maxDateTime.getFullYear(), maxDateTime.getMonth(), maxDateTime.getDate(), 0, 0, 0, 0);639640 if (this.hourMaxOriginal === null || this.minuteMaxOriginal === null || this.secondMaxOriginal === null || this.millisecMaxOriginal === null) {641 this.hourMaxOriginal = o.hourMax;642 this.minuteMaxOriginal = o.minuteMax;643 this.secondMaxOriginal = o.secondMax;644 this.millisecMaxOriginal = o.millisecMax;645 this.microsecMaxOriginal = o.microsecMax;646 }647648 if (dp_inst.settings.timeOnly || maxDateTimeDate.getTime() === dp_date.getTime()) {649 this._defaults.hourMax = maxDateTime.getHours();650 if (this.hour >= this._defaults.hourMax) {651 this.hour = this._defaults.hourMax;652 this._defaults.minuteMax = maxDateTime.getMinutes();653 if (this.minute >= this._defaults.minuteMax) {654 this.minute = this._defaults.minuteMax;655 this._defaults.secondMax = maxDateTime.getSeconds();656 if (this.second >= this._defaults.secondMax) {657 this.second = this._defaults.secondMax;658 this._defaults.millisecMax = maxDateTime.getMilliseconds();659 if (this.millisec >= this._defaults.millisecMax) {660 this.millisec = this._defaults.millisecMax;661 this._defaults.microsecMax = maxDateTime.getMicroseconds();662 } else {663 if (this.microsec > this._defaults.microsecMax) {664 this.microsec = this._defaults.microsecMax;665 }666 this._defaults.microsecMax = this.microsecMaxOriginal;667 }668 } else {669 this._defaults.millisecMax = this.millisecMaxOriginal;670 this._defaults.microsecMax = this.microsecMaxOriginal;671 }672 } else {673 this._defaults.secondMax = this.secondMaxOriginal;674 this._defaults.millisecMax = this.millisecMaxOriginal;675 this._defaults.microsecMax = this.microsecMaxOriginal;676 }677 } else {678 this._defaults.minuteMax = this.minuteMaxOriginal;679 this._defaults.secondMax = this.secondMaxOriginal;680 this._defaults.millisecMax = this.millisecMaxOriginal;681 this._defaults.microsecMax = this.microsecMaxOriginal;682 }683 } else {684 this._defaults.hourMax = this.hourMaxOriginal;685 this._defaults.minuteMax = this.minuteMaxOriginal;686 this._defaults.secondMax = this.secondMaxOriginal;687 this._defaults.millisecMax = this.millisecMaxOriginal;688 this._defaults.microsecMax = this.microsecMaxOriginal;689 }690 }691692 if (dp_inst.settings.minTime!==null) { 693 var tempMinTime=new Date("01/01/1970 " + dp_inst.settings.minTime); 694 if (this.hour<tempMinTime.getHours()) {695 this.hour=this._defaults.hourMin=tempMinTime.getHours();696 this.minute=this._defaults.minuteMin=tempMinTime.getMinutes(); 697 } else if (this.hour===tempMinTime.getHours() && this.minute<tempMinTime.getMinutes()) {698 this.minute=this._defaults.minuteMin=tempMinTime.getMinutes();699 } else { 700 if (this._defaults.hourMin<tempMinTime.getHours()) {701 this._defaults.hourMin=tempMinTime.getHours();702 this._defaults.minuteMin=tempMinTime.getMinutes(); 703 } else if (this._defaults.hourMin===tempMinTime.getHours()===this.hour && this._defaults.minuteMin<tempMinTime.getMinutes()) {704 this._defaults.minuteMin=tempMinTime.getMinutes(); 705 } else {706 this._defaults.minuteMin=0;707 }708 } 709 }710 711 if (dp_inst.settings.maxTime!==null) { 712 var tempMaxTime=new Date("01/01/1970 " + dp_inst.settings.maxTime);713 if (this.hour>tempMaxTime.getHours()) {714 this.hour=this._defaults.hourMax=tempMaxTime.getHours(); 715 this.minute=this._defaults.minuteMax=tempMaxTime.getMinutes();716 } else if (this.hour===tempMaxTime.getHours() && this.minute>tempMaxTime.getMinutes()) { 717 this.minute=this._defaults.minuteMax=tempMaxTime.getMinutes(); 718 } else {719 if (this._defaults.hourMax>tempMaxTime.getHours()) {720 this._defaults.hourMax=tempMaxTime.getHours();721 this._defaults.minuteMax=tempMaxTime.getMinutes(); 722 } else if (this._defaults.hourMax===tempMaxTime.getHours()===this.hour && this._defaults.minuteMax>tempMaxTime.getMinutes()) {723 this._defaults.minuteMax=tempMaxTime.getMinutes(); 724 } else {725 this._defaults.minuteMax=59;726 }727 } 728 }729 730 if (adjustSliders !== undefined && adjustSliders === true) {731 var hourMax = parseInt((this._defaults.hourMax - ((this._defaults.hourMax - this._defaults.hourMin) % this._defaults.stepHour)), 10),732 minMax = parseInt((this._defaults.minuteMax - ((this._defaults.minuteMax - this._defaults.minuteMin) % this._defaults.stepMinute)), 10),733 secMax = parseInt((this._defaults.secondMax - ((this._defaults.secondMax - this._defaults.secondMin) % this._defaults.stepSecond)), 10),734 millisecMax = parseInt((this._defaults.millisecMax - ((this._defaults.millisecMax - this._defaults.millisecMin) % this._defaults.stepMillisec)), 10),735 microsecMax = parseInt((this._defaults.microsecMax - ((this._defaults.microsecMax - this._defaults.microsecMin) % this._defaults.stepMicrosec)), 10);736737 if (this.hour_slider) {738 this.control.options(this, this.hour_slider, 'hour', { min: this._defaults.hourMin, max: hourMax, step: this._defaults.stepHour });739 this.control.value(this, this.hour_slider, 'hour', this.hour - (this.hour % this._defaults.stepHour));740 }741 if (this.minute_slider) {742 this.control.options(this, this.minute_slider, 'minute', { min: this._defaults.minuteMin, max: minMax, step: this._defaults.stepMinute });743 this.control.value(this, this.minute_slider, 'minute', this.minute - (this.minute % this._defaults.stepMinute));744 }745 if (this.second_slider) {746 this.control.options(this, this.second_slider, 'second', { min: this._defaults.secondMin, max: secMax, step: this._defaults.stepSecond });747 this.control.value(this, this.second_slider, 'second', this.second - (this.second % this._defaults.stepSecond));748 }749 if (this.millisec_slider) {750 this.control.options(this, this.millisec_slider, 'millisec', { min: this._defaults.millisecMin, max: millisecMax, step: this._defaults.stepMillisec });751 this.control.value(this, this.millisec_slider, 'millisec', this.millisec - (this.millisec % this._defaults.stepMillisec));752 }753 if (this.microsec_slider) {754 this.control.options(this, this.microsec_slider, 'microsec', { min: this._defaults.microsecMin, max: microsecMax, step: this._defaults.stepMicrosec });755 this.control.value(this, this.microsec_slider, 'microsec', this.microsec - (this.microsec % this._defaults.stepMicrosec));756 }757 }758759 },760761 /*762 * when a slider moves, set the internal time...763 * on time change is also called when the time is updated in the text field764 */765 _onTimeChange: function () {766 if (!this._defaults.showTimepicker) {767 return;768 }769 var hour = (this.hour_slider) ? this.control.value(this, this.hour_slider, 'hour') : false,770 minute = (this.minute_slider) ? this.control.value(this, this.minute_slider, 'minute') : false,771 second = (this.second_slider) ? this.control.value(this, this.second_slider, 'second') : false,772 millisec = (this.millisec_slider) ? this.control.value(this, this.millisec_slider, 'millisec') : false,773 microsec = (this.microsec_slider) ? this.control.value(this, this.microsec_slider, 'microsec') : false,774 timezone = (this.timezone_select) ? this.timezone_select.val() : false,775 o = this._defaults,776 pickerTimeFormat = o.pickerTimeFormat || o.timeFormat,777 pickerTimeSuffix = o.pickerTimeSuffix || o.timeSuffix;778779 if (typeof(hour) === 'object') {780 hour = false;781 }782 if (typeof(minute) === 'object') {783 minute = false;784 }785 if (typeof(second) === 'object') {786 second = false;787 }788 if (typeof(millisec) === 'object') {789 millisec = false;790 }791 if (typeof(microsec) === 'object') {792 microsec = false;793 }794 if (typeof(timezone) === 'object') {795 timezone = false;796 }797798 if (hour !== false) {799 hour = parseInt(hour, 10);800 }801 if (minute !== false) {802 minute = parseInt(minute, 10);803 }804 if (second !== false) {805 second = parseInt(second, 10);806 }807 if (millisec !== false) {808 millisec = parseInt(millisec, 10);809 }810 if (microsec !== false) {811 microsec = parseInt(microsec, 10);812 }813 if (timezone !== false) {814 timezone = timezone.toString();815 }816817 var ampm = o[hour < 12 ? 'amNames' : 'pmNames'][0];818819 // If the update was done in the input field, the input field should not be updated.820 // If the update was done using the sliders, update the input field.821 var hasChanged = (822 hour !== parseInt(this.hour,10) || // sliders should all be numeric823 minute !== parseInt(this.minute,10) || 824 second !== parseInt(this.second,10) || 825 millisec !== parseInt(this.millisec,10) || 826 microsec !== parseInt(this.microsec,10) || 827 (this.ampm.length > 0 && (hour < 12) !== ($.inArray(this.ampm.toUpperCase(), this.amNames) !== -1)) || 828 (this.timezone !== null && timezone !== this.timezone.toString()) // could be numeric or "EST" format, so use toString()829 );830831 if (hasChanged) {832833 if (hour !== false) {834 this.hour = hour;835 }836 if (minute !== false) {837 this.minute = minute;838 }839 if (second !== false) {840 this.second = second;841 }842 if (millisec !== false) {843 this.millisec = millisec;844 }845 if (microsec !== false) {846 this.microsec = microsec;847 }848 if (timezone !== false) {849 this.timezone = timezone;850 }851852 if (!this.inst) {853 this.inst = $.datepicker._getInst(this.$input[0]);854 }855856 this._limitMinMaxDateTime(this.inst, true);857 }858 if (this.support.ampm) {859 this.ampm = ampm;860 }861862 // Updates the time within the timepicker863 this.formattedTime = $.datepicker.formatTime(o.timeFormat, this, o);864 if (this.$timeObj) {865 if (pickerTimeFormat === o.timeFormat) {866 this.$timeObj.text(this.formattedTime + pickerTimeSuffix);867 }868 else {869 this.$timeObj.text($.datepicker.formatTime(pickerTimeFormat, this, o) + pickerTimeSuffix);870 }871 }872873 this.timeDefined = true;874 if (hasChanged) {875 this._updateDateTime();876 //this.$input.focus(); // may automatically open the picker on setDate877 }878 },879880 /*881 * call custom onSelect.882 * bind to sliders slidestop, and grid click.883 */884 _onSelectHandler: function () {885 var onSelect = this._defaults.onSelect || this.inst.settings.onSelect;886 var inputEl = this.$input ? this.$input[0] : null;887 if (onSelect && inputEl) {888 onSelect.apply(inputEl, [this.formattedDateTime, this]);889 }890 },891892 /*893 * update our input with the new date time..894 */895 _updateDateTime: function (dp_inst) {896 dp_inst = this.inst || dp_inst;897 var dtTmp = (dp_inst.currentYear > 0? 898 new Date(dp_inst.currentYear, dp_inst.currentMonth, dp_inst.currentDay) : 899 new Date(dp_inst.selectedYear, dp_inst.selectedMonth, dp_inst.selectedDay)),900 dt = $.datepicker._daylightSavingAdjust(dtTmp),901 //dt = $.datepicker._daylightSavingAdjust(new Date(dp_inst.selectedYear, dp_inst.selectedMonth, dp_inst.selectedDay)),902 //dt = $.datepicker._daylightSavingAdjust(new Date(dp_inst.currentYear, dp_inst.currentMonth, dp_inst.currentDay)),903 dateFmt = $.datepicker._get(dp_inst, 'dateFormat'),904 formatCfg = $.datepicker._getFormatConfig(dp_inst),905 timeAvailable = dt !== null && this.timeDefined;906 this.formattedDate = $.datepicker.formatDate(dateFmt, (dt === null ? new Date() : dt), formatCfg);907 var formattedDateTime = this.formattedDate;908 909 // if a slider was changed but datepicker doesn't have a value yet, set it910 if (dp_inst.lastVal === "") {911 dp_inst.currentYear = dp_inst.selectedYear;912 dp_inst.currentMonth = dp_inst.selectedMonth;913 dp_inst.currentDay = dp_inst.selectedDay;914 }915916 /*917 * remove following lines to force every changes in date picker to change the input value918 * Bug descriptions: when an input field has a default value, and click on the field to pop up the date picker. 919 * If the user manually empty the value in the input field, the date picker will never change selected value.920 */921 //if (dp_inst.lastVal !== undefined && (dp_inst.lastVal.length > 0 && this.$input.val().length === 0)) {922 // return;923 //}924925 if (this._defaults.timeOnly === true && this._defaults.timeOnlyShowDate === false) {926 formattedDateTime = this.formattedTime;927 } else if ((this._defaults.timeOnly !== true && (this._defaults.alwaysSetTime || timeAvailable)) || (this._defaults.timeOnly === true && this._defaults.timeOnlyShowDate === true)) {928 formattedDateTime += this._defaults.separator + this.formattedTime + this._defaults.timeSuffix;929 }930931 this.formattedDateTime = formattedDateTime;932933 if (!this._defaults.showTimepicker) {934 this.$input.val(this.formattedDate);935 } else if (this.$altInput && this._defaults.timeOnly === false && this._defaults.altFieldTimeOnly === true) {936 this.$altInput.val(this.formattedTime);937 this.$input.val(this.formattedDate);938 } else if (this.$altInput) {939 this.$input.val(formattedDateTime);940 var altFormattedDateTime = '',941 altSeparator = this._defaults.altSeparator !== null ? this._defaults.altSeparator : this._defaults.separator,942 altTimeSuffix = this._defaults.altTimeSuffix !== null ? this._defaults.altTimeSuffix : this._defaults.timeSuffix;943 944 if (!this._defaults.timeOnly) {945 if (this._defaults.altFormat) {946 altFormattedDateTime = $.datepicker.formatDate(this._defaults.altFormat, (dt === null ? new Date() : dt), formatCfg);947 }948 else {949 altFormattedDateTime = this.formattedDate;950 }951952 if (altFormattedDateTime) {953 altFormattedDateTime += altSeparator;954 }955 }956957 if (this._defaults.altTimeFormat !== null) {958 altFormattedDateTime += $.datepicker.formatTime(this._defaults.altTimeFormat, this, this._defaults) + altTimeSuffix;959 }960 else {961 altFormattedDateTime += this.formattedTime + altTimeSuffix;962 }963 this.$altInput.val(altFormattedDateTime);964 } else {965 this.$input.val(formattedDateTime);966 }967968 this.$input.trigger("change");969 },970971 _onFocus: function () {972 if (!this.$input.val() && this._defaults.defaultValue) {973 this.$input.val(this._defaults.defaultValue);974 var inst = $.datepicker._getInst(this.$input.get(0)),975 tp_inst = $.datepicker._get(inst, 'timepicker');976 if (tp_inst) {977 if (tp_inst._defaults.timeOnly && (inst.input.val() !== inst.lastVal)) {978 try {979 $.datepicker._updateDatepicker(inst);980 } catch (err) {981 $.timepicker.log(err);982 }983 }984 }985 }986 },987988 /*989 * Small abstraction to control types990 * We can add more, just be sure to follow the pattern: create, options, value991 */992 _controls: {993 // slider methods994 slider: {995 create: function (tp_inst, obj, unit, val, min, max, step) {996 var rtl = tp_inst._defaults.isRTL; // if rtl go -60->0 instead of 0->60997 return obj.prop('slide', null).slider({998 orientation: "horizontal",999 value: rtl ? val * -1 : val,1000 min: rtl ? max * -1 : min,1001 max: rtl ? min * -1 : max,1002 step: step,1003 slide: function (event, ui) {1004 tp_inst.control.value(tp_inst, $(this), unit, rtl ? ui.value * -1 : ui.value);1005 tp_inst._onTimeChange();1006 },1007 stop: function (event, ui) {1008 tp_inst._onSelectHandler();1009 }1010 }); 1011 },1012 options: function (tp_inst, obj, unit, opts, val) {1013 if (tp_inst._defaults.isRTL) {1014 if (typeof(opts) === 'string') {1015 if (opts === 'min' || opts === 'max') {1016 if (val !== undefined) {1017 return obj.slider(opts, val * -1);1018 }1019 return Math.abs(obj.slider(opts));1020 }1021 return obj.slider(opts);1022 }1023 var min = opts.min, 1024 max = opts.max;1025 opts.min = opts.max = null;1026 if (min !== undefined) {1027 opts.max = min * -1;1028 }1029 if (max !== undefined) {1030 opts.min = max * -1;1031 }1032 return obj.slider(opts);1033 }1034 if (typeof(opts) === 'string' && val !== undefined) {1035 return obj.slider(opts, val);1036 }1037 return obj.slider(opts);1038 },1039 value: function (tp_inst, obj, unit, val) {1040 if (tp_inst._defaults.isRTL) {1041 if (val !== undefined) {1042 return obj.slider('value', val * -1);1043 }1044 return Math.abs(obj.slider('value'));1045 }1046 if (val !== undefined) {1047 return obj.slider('value', val);1048 }1049 return obj.slider('value');1050 }1051 },1052 // select methods1053 select: {1054 create: function (tp_inst, obj, unit, val, min, max, step) {1055 var sel = '<select class="ui-timepicker-select ui-state-default ui-corner-all" data-unit="' + unit + '" data-min="' + min + '" data-max="' + max + '" data-step="' + step + '">',1056 format = tp_inst._defaults.pickerTimeFormat || tp_inst._defaults.timeFormat;10571058 for (var i = min; i <= max; i += step) {1059 sel += '<option value="' + i + '"' + (i === val ? ' selected' : '') + '>';1060 if (unit === 'hour') {1061 sel += $.datepicker.formatTime($.trim(format.replace(/[^ht ]/ig, '')), {hour: i}, tp_inst._defaults);1062 }1063 else if (unit === 'millisec' || unit === 'microsec' || i >= 10) { sel += i; }1064 else {sel += '0' + i.toString(); }1065 sel += '</option>';1066 }1067 sel += '</select>';10681069 obj.children('select').remove();10701071 $(sel).appendTo(obj).change(function (e) {1072 tp_inst._onTimeChange();1073 tp_inst._onSelectHandler();1074 tp_inst._afterInject();1075 });10761077 return obj;1078 },1079 options: function (tp_inst, obj, unit, opts, val) {1080 var o = {},1081 $t = obj.children('select');1082 if (typeof(opts) === 'string') {1083 if (val === undefined) {1084 return $t.data(opts);1085 }1086 o[opts] = val; 1087 }1088 else { o = opts; }1089 return tp_inst.control.create(tp_inst, obj, $t.data('unit'), $t.val(), o.min>=0 ? o.min : $t.data('min'), o.max || $t.data('max'), o.step || $t.data('step'));1090 },1091 value: function (tp_inst, obj, unit, val) {1092 var $t = obj.children('select');1093 if (val !== undefined) {1094 return $t.val(val);1095 }1096 return $t.val();1097 }1098 }1099 } // end _controls11001101 });11021103 $.fn.extend({1104 /*1105 * shorthand just to use timepicker.1106 */1107 timepicker: function (o) {1108 o = o || {};1109 var tmp_args = Array.prototype.slice.call(arguments);11101111 if (typeof o === 'object') {1112 tmp_args[0] = $.extend(o, {1113 timeOnly: true1114 });1115 }11161117 return $(this).each(function () {1118 $.fn.datetimepicker.apply($(this), tmp_args);1119 });1120 },11211122 /*1123 * extend timepicker to datepicker1124 */1125 datetimepicker: function (o) {1126 o = o || {};1127 var tmp_args = arguments;11281129 if (typeof(o) === 'string') {1130 if (o === 'getDate' || (o === 'option' && tmp_args.length === 2 && typeof (tmp_args[1]) === 'string')) {1131 return $.fn.datepicker.apply($(this[0]), tmp_args);1132 } else {1133 return this.each(function () {1134 var $t = $(this);1135 $t.datepicker.apply($t, tmp_args);1136 });1137 }1138 } else {1139 return this.each(function () {1140 var $t = $(this);1141 $t.datepicker($.timepicker._newInst($t, o)._defaults);1142 });1143 }1144 }1145 });11461147 /*1148 * Public Utility to parse date and time1149 */1150 $.datepicker.parseDateTime = function (dateFormat, timeFormat, dateTimeString, dateSettings, timeSettings) {1151 var parseRes = parseDateTimeInternal(dateFormat, timeFormat, dateTimeString, dateSettings, timeSettings);1152 if (parseRes.timeObj) {1153 var t = parseRes.timeObj;1154 parseRes.date.setHours(t.hour, t.minute, t.second, t.millisec);1155 parseRes.date.setMicroseconds(t.microsec);1156 }11571158 return parseRes.date;1159 };11601161 /*1162 * Public utility to parse time1163 */1164 $.datepicker.parseTime = function (timeFormat, timeString, options) {1165 var o = extendRemove(extendRemove({}, $.timepicker._defaults), options || {}),1166 iso8601 = (timeFormat.replace(/\'.*?\'/g, '').indexOf('Z') !== -1);11671168 // Strict parse requires the timeString to match the timeFormat exactly1169 var strictParse = function (f, s, o) {11701171 // pattern for standard and localized AM/PM markers1172 var getPatternAmpm = function (amNames, pmNames) {1173 var markers = [];1174 if (amNames) {1175 $.merge(markers, amNames);1176 }1177 if (pmNames) {1178 $.merge(markers, pmNames);1179 }1180 markers = $.map(markers, function (val) {1181 return val.replace(/[.*+?|()\[\]{}\\]/g, '\\$&');1182 });1183 return '(' + markers.join('|') + ')?';1184 };11851186 // figure out position of time elements.. cause js cant do named captures1187 var getFormatPositions = function (timeFormat) {1188 var finds = timeFormat.toLowerCase().match(/(h{1,2}|m{1,2}|s{1,2}|l{1}|c{1}|t{1,2}|z|'.*?')/g),1189 orders = {1190 h: -1,1191 m: -1,1192 s: -1,1193 l: -1,1194 c: -1,1195 t: -1,1196 z: -11197 };11981199 if (finds) {1200 for (var i = 0; i < finds.length; i++) {1201 if (orders[finds[i].toString().charAt(0)] === -1) {1202 orders[finds[i].toString().charAt(0)] = i + 1;1203 }1204 }1205 }1206 return orders;1207 };12081209 var regstr = '^' + f.toString()1210 .replace(/([hH]{1,2}|mm?|ss?|[tT]{1,2}|[zZ]|[lc]|'.*?')/g, function (match) {1211 var ml = match.length;1212 switch (match.charAt(0).toLowerCase()) {1213 case 'h':1214 return ml === 1 ? '(\\d?\\d)' : '(\\d{' + ml + '})';1215 case 'm':1216 return ml === 1 ? '(\\d?\\d)' : '(\\d{' + ml + '})';1217 case 's':1218 return ml === 1 ? '(\\d?\\d)' : '(\\d{' + ml + '})';1219 case 'l':1220 return '(\\d?\\d?\\d)';1221 case 'c':1222 return '(\\d?\\d?\\d)';1223 case 'z':1224 return '(z|[-+]\\d\\d:?\\d\\d|\\S+)?';1225 case 't':1226 return getPatternAmpm(o.amNames, o.pmNames);1227 default: // literal escaped in quotes1228 return '(' + match.replace(/\'/g, "").replace(/(\.|\$|\^|\\|\/|\(|\)|\[|\]|\?|\+|\*)/g, function (m) { return "\\" + m; }) + ')?';1229 }1230 })1231 .replace(/\s/g, '\\s?') +1232 o.timeSuffix + '$',1233 order = getFormatPositions(f),1234 ampm = '',1235 treg;12361237 treg = s.match(new RegExp(regstr, 'i'));12381239 var resTime = {1240 hour: 0,1241 minute: 0,1242 second: 0,1243 millisec: 0,1244 microsec: 01245 };12461247 if (treg) {1248 if (order.t !== -1) {1249 if (treg[order.t] === undefined || treg[order.t].length === 0) {1250 ampm = '';1251 resTime.ampm = '';1252 } else {1253 ampm = $.inArray(treg[order.t].toUpperCase(), $.map(o.amNames, function (x,i) { return x.toUpperCase(); })) !== -1 ? 'AM' : 'PM';1254 resTime.ampm = o[ampm === 'AM' ? 'amNames' : 'pmNames'][0];1255 }1256 }12571258 if (order.h !== -1) {1259 if (ampm === 'AM' && treg[order.h] === '12') {1260 resTime.hour = 0; // 12am = 0 hour1261 } else {1262 if (ampm === 'PM' && treg[order.h] !== '12') {1263 resTime.hour = parseInt(treg[order.h], 10) + 12; // 12pm = 12 hour, any other pm = hour + 121264 } else {1265 resTime.hour = Number(treg[order.h]);1266 }1267 }1268 }12691270 if (order.m !== -1) {1271 resTime.minute = Number(treg[order.m]);1272 }1273 if (order.s !== -1) {1274 resTime.second = Number(treg[order.s]);1275 }1276 if (order.l !== -1) {1277 resTime.millisec = Number(treg[order.l]);1278 }1279 if (order.c !== -1) {1280 resTime.microsec = Number(treg[order.c]);1281 }1282 if (order.z !== -1 && treg[order.z] !== undefined) {1283 resTime.timezone = $.timepicker.timezoneOffsetNumber(treg[order.z]);1284 }128512861287 return resTime;1288 }1289 return false;1290 };// end strictParse12911292 // First try JS Date, if that fails, use strictParse1293 var looseParse = function (f, s, o) {1294 try {1295 var d = new Date('2012-01-01 ' + s);1296 if (isNaN(d.getTime())) {1297 d = new Date('2012-01-01T' + s);1298 if (isNaN(d.getTime())) {1299 d = new Date('01/01/2012 ' + s);1300 if (isNaN(d.getTime())) {1301 throw "Unable to parse time with native Date: " + s;1302 }1303 }1304 }13051306 return {1307 hour: d.getHours(),1308 minute: d.getMinutes(),1309 second: d.getSeconds(),1310 millisec: d.getMilliseconds(),1311 microsec: d.getMicroseconds(),1312 timezone: d.getTimezoneOffset() * -11313 };1314 }1315 catch (err) {1316 try {1317 return strictParse(f, s, o);1318 }1319 catch (err2) {1320 $.timepicker.log("Unable to parse \ntimeString: " + s + "\ntimeFormat: " + f);1321 } 1322 }1323 return false;1324 }; // end looseParse1325 1326 if (typeof o.parse === "function") {1327 return o.parse(timeFormat, timeString, o);1328 }1329 if (o.parse === 'loose') {1330 return looseParse(timeFormat, timeString, o);1331 }1332 return strictParse(timeFormat, timeString, o);1333 };13341335 /**1336 * Public utility to format the time1337 * @param {string} format format of the time1338 * @param {Object} time Object not a Date for timezones1339 * @param {Object} [options] essentially the regional[].. amNames, pmNames, ampm1340 * @returns {string} the formatted time1341 */1342 $.datepicker.formatTime = function (format, time, options) {1343 options = options || {};1344 options = $.extend({}, $.timepicker._defaults, options);1345 time = $.extend({1346 hour: 0,1347 minute: 0,1348 second: 0,1349 millisec: 0,1350 microsec: 0,1351 timezone: null1352 }, time);13531354 var tmptime = format,1355 ampmName = options.amNames[0],1356 hour = parseInt(time.hour, 10);13571358 if (hour > 11) {1359 ampmName = options.pmNames[0];1360 }13611362 tmptime = tmptime.replace(/(?:HH?|hh?|mm?|ss?|[tT]{1,2}|[zZ]|[lc]|'.*?')/g, function (match) {1363 switch (match) {1364 case 'HH':1365 return ('0' + hour).slice(-2);1366 case 'H':1367 return hour;1368 case 'hh':1369 return ('0' + convert24to12(hour)).slice(-2);1370 case 'h':1371 return convert24to12(hour);1372 case 'mm':1373 return ('0' + time.minute).slice(-2);1374 case 'm':1375 return time.minute;1376 case 'ss':1377 return ('0' + time.second).slice(-2);1378 case 's':1379 return time.second;1380 case 'l':1381 return ('00' + time.millisec).slice(-3);1382 case 'c':1383 return ('00' + time.microsec).slice(-3);1384 case 'z':1385 return $.timepicker.timezoneOffsetString(time.timezone === null ? options.timezone : time.timezone, false);1386 case 'Z':1387 return $.timepicker.timezoneOffsetString(time.timezone === null ? options.timezone : time.timezone, true);1388 case 'T':1389 return ampmName.charAt(0).toUpperCase();1390 case 'TT':1391 return ampmName.toUpperCase();1392 case 't':1393 return ampmName.charAt(0).toLowerCase();1394 case 'tt':1395 return ampmName.toLowerCase();1396 default:1397 return match.replace(/'/g, "");1398 }1399 });14001401 return tmptime;1402 };14031404 /*1405 * the bad hack :/ override datepicker so it doesn't close on select1406 // inspired: http://stackoverflow.com/questions/1252512/jquery-datepicker-prevent-closing-picker-when-clicking-a-date/1762378#17623781407 */1408 $.datepicker._base_selectDate = $.datepicker._selectDate;1409 $.datepicker._selectDate = function (id, dateStr) {1410 var inst = this._getInst($(id)[0]),1411 tp_inst = this._get(inst, 'timepicker'),1412 was_inline;14131414 if (tp_inst && inst.settings.showTimepicker) {1415 tp_inst._limitMinMaxDateTime(inst, true);1416 was_inline = inst.inline;1417 inst.inline = inst.stay_open = true;1418 //This way the onSelect handler called from calendarpicker get the full dateTime1419 this._base_selectDate(id, dateStr);1420 inst.inline = was_inline;1421 inst.stay_open = false;1422 this._notifyChange(inst);1423 this._updateDatepicker(inst);1424 } else {1425 this._base_selectDate(id, dateStr);1426 }1427 };14281429 /*1430 * second bad hack :/ override datepicker so it triggers an event when changing the input field1431 * and does not redraw the datepicker on every selectDate event1432 */1433 $.datepicker._base_updateDatepicker = $.datepicker._updateDatepicker;1434 $.datepicker._updateDatepicker = function (inst) {14351436 // don't popup the datepicker if there is another instance already opened1437 var input = inst.input[0];1438 if ($.datepicker._curInst && $.datepicker._curInst !== inst && $.datepicker._datepickerShowing && $.datepicker._lastInput !== input) {1439 return;1440 }14411442 if (typeof(inst.stay_open) !== 'boolean' || inst.stay_open === false) {14431444 this._base_updateDatepicker(inst);14451446 // Reload the time control when changing something in the input text field.1447 var tp_inst = this._get(inst, 'timepicker');1448 if (tp_inst) {1449 tp_inst._addTimePicker(inst);1450 }1451 }1452 };14531454 /*1455 * third bad hack :/ override datepicker so it allows spaces and colon in the input field1456 */1457 $.datepicker._base_doKeyPress = $.datepicker._doKeyPress;1458 $.datepicker._doKeyPress = function (event) {1459 var inst = $.datepicker._getInst(event.target),1460 tp_inst = $.datepicker._get(inst, 'timepicker');14611462 if (tp_inst) {1463 if ($.datepicker._get(inst, 'constrainInput')) {1464 var ampm = tp_inst.support.ampm,1465 tz = tp_inst._defaults.showTimezone !== null ? tp_inst._defaults.showTimezone : tp_inst.support.timezone,1466 dateChars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat')),1467 datetimeChars = tp_inst._defaults.timeFormat.toString()1468 .replace(/[hms]/g, '')1469 .replace(/TT/g, ampm ? 'APM' : '')1470 .replace(/Tt/g, ampm ? 'AaPpMm' : '')1471 .replace(/tT/g, ampm ? 'AaPpMm' : '')1472 .replace(/T/g, ampm ? 'AP' : '')1473 .replace(/tt/g, ampm ? 'apm' : '')1474 .replace(/t/g, ampm ? 'ap' : '') + 1475 " " + tp_inst._defaults.separator + 1476 tp_inst._defaults.timeSuffix + 1477 (tz ? tp_inst._defaults.timezoneList.join('') : '') + 1478 (tp_inst._defaults.amNames.join('')) + (tp_inst._defaults.pmNames.join('')) + 1479 dateChars,1480 chr = String.fromCharCode(event.charCode === undefined ? event.keyCode : event.charCode);1481 return event.ctrlKey || (chr < ' ' || !dateChars || datetimeChars.indexOf(chr) > -1);1482 }1483 }14841485 return $.datepicker._base_doKeyPress(event);1486 };14871488 /*1489 * Fourth bad hack :/ override _updateAlternate function used in inline mode to init altField1490 * Update any alternate field to synchronise with the main field.1491 */1492 $.datepicker._base_updateAlternate = $.datepicker._updateAlternate;1493 $.datepicker._updateAlternate = function (inst) {1494 var tp_inst = this._get(inst, 'timepicker');1495 if (tp_inst) {1496 var altField = tp_inst._defaults.altField;1497 if (altField) { // update alternate field too1498 var altFormat = tp_inst._defaults.altFormat || tp_inst._defaults.dateFormat,1499 date = this._getDate(inst),1500 formatCfg = $.datepicker._getFormatConfig(inst),1501 altFormattedDateTime = '', 1502 altSeparator = tp_inst._defaults.altSeparator ? tp_inst._defaults.altSeparator : tp_inst._defaults.separator, 1503 altTimeSuffix = tp_inst._defaults.altTimeSuffix ? tp_inst._defaults.altTimeSuffix : tp_inst._defaults.timeSuffix,1504 altTimeFormat = tp_inst._defaults.altTimeFormat !== null ? tp_inst._defaults.altTimeFormat : tp_inst._defaults.timeFormat;1505 1506 altFormattedDateTime += $.datepicker.formatTime(altTimeFormat, tp_inst, tp_inst._defaults) + altTimeSuffix;1507 if (!tp_inst._defaults.timeOnly && !tp_inst._defaults.altFieldTimeOnly && date !== null) {1508 if (tp_inst._defaults.altFormat) {1509 altFormattedDateTime = $.datepicker.formatDate(tp_inst._defaults.altFormat, date, formatCfg) + altSeparator + altFormattedDateTime;1510 }1511 else {1512 altFormattedDateTime = tp_inst.formattedDate + altSeparator + altFormattedDateTime;1513 }1514 }1515 $(altField).val( inst.input.val() ? altFormattedDateTime : "");1516 }1517 }1518 else {1519 $.datepicker._base_updateAlternate(inst); 1520 }1521 };15221523 /*1524 * Override key up event to sync manual input changes.1525 */1526 $.datepicker._base_doKeyUp = $.datepicker._doKeyUp;1527 $.datepicker._doKeyUp = function (event) {1528 var inst = $.datepicker._getInst(event.target),1529 tp_inst = $.datepicker._get(inst, 'timepicker');15301531 if (tp_inst) {1532 if (tp_inst._defaults.timeOnly && (inst.input.val() !== inst.lastVal)) {1533 try {1534 $.datepicker._updateDatepicker(inst);1535 } catch (err) {1536 $.timepicker.log(err);1537 }1538 }1539 }15401541 return $.datepicker._base_doKeyUp(event);1542 };15431544 /*1545 * override "Today" button to also grab the time.1546 */1547 $.datepicker._base_gotoToday = $.datepicker._gotoToday;1548 $.datepicker._gotoToday = function (id) {1549 var inst = this._getInst($(id)[0]),1550 $dp = inst.dpDiv;1551 var tp_inst = this._get(inst, 'timepicker');1552 selectLocalTimezone(tp_inst);1553 var now = new Date();1554 this._setTime(inst, now);1555 this._setDate(inst, now);1556 this._base_gotoToday(id);1557 };15581559 /*1560 * Disable & enable the Time in the datetimepicker1561 */1562 $.datepicker._disableTimepickerDatepicker = function (target) {1563 var inst = this._getInst(target);1564 if (!inst) {1565 return;1566 }15671568 var tp_inst = this._get(inst, 'timepicker');1569 $(target).datepicker('getDate'); // Init selected[Year|Month|Day]1570 if (tp_inst) {1571 inst.settings.showTimepicker = false;1572 tp_inst._defaults.showTimepicker = false;1573 tp_inst._updateDateTime(inst);1574 }1575 };15761577 $.datepicker._enableTimepickerDatepicker = function (target) {1578 var inst = this._getInst(target);1579 if (!inst) {1580 return;1581 }15821583 var tp_inst = this._get(inst, 'timepicker');1584 $(target).datepicker('getDate'); // Init selected[Year|Month|Day]1585 if (tp_inst) {1586 inst.settings.showTimepicker = true;1587 tp_inst._defaults.showTimepicker = true;1588 tp_inst._addTimePicker(inst); // Could be disabled on page load1589 tp_inst._updateDateTime(inst);1590 }1591 };15921593 /*1594 * Create our own set time function1595 */1596 $.datepicker._setTime = function (inst, date) {1597 var tp_inst = this._get(inst, 'timepicker');1598 if (tp_inst) {1599 var defaults = tp_inst._defaults;16001601 // calling _setTime with no date sets time to defaults1602 tp_inst.hour = date ? date.getHours() : defaults.hour;1603 tp_inst.minute = date ? date.getMinutes() : defaults.minute;1604 tp_inst.second = date ? date.getSeconds() : defaults.second;1605 tp_inst.millisec = date ? date.getMilliseconds() : defaults.millisec;1606 tp_inst.microsec = date ? date.getMicroseconds() : defaults.microsec;16071608 //check if within min/max times.. 1609 tp_inst._limitMinMaxDateTime(inst, true);16101611 tp_inst._onTimeChange();1612 tp_inst._updateDateTime(inst);1613 }1614 };16151616 /*1617 * Create new public method to set only time, callable as $().datepicker('setTime', date)1618 */1619 $.datepicker._setTimeDatepicker = function (target, date, withDate) {1620 var inst = this._getInst(target);1621 if (!inst) {1622 return;1623 }16241625 var tp_inst = this._get(inst, 'timepicker');16261627 if (tp_inst) {1628 this._setDateFromField(inst);1629 var tp_date;1630 if (date) {1631 if (typeof date === "string") {1632 tp_inst._parseTime(date, withDate);1633 tp_date = new Date();1634 tp_date.setHours(tp_inst.hour, tp_inst.minute, tp_inst.second, tp_inst.millisec);1635 tp_date.setMicroseconds(tp_inst.microsec);1636 } else {1637 tp_date = new Date(date.getTime());1638 tp_date.setMicroseconds(date.getMicroseconds());1639 }1640 if (tp_date.toString() === 'Invalid Date') {1641 tp_date = undefined;1642 }1643 this._setTime(inst, tp_date);1644 }1645 }16461647 };16481649 /*1650 * override setDate() to allow setting time too within Date object1651 */1652 $.datepicker._base_setDateDatepicker = $.datepicker._setDateDatepicker;1653 $.datepicker._setDateDatepicker = function (target, _date) {1654 var inst = this._getInst(target);1655 var date = _date;1656 if (!inst) {1657 return;1658 }16591660 if (typeof(_date) === 'string') {1661 date = new Date(_date);1662 if (!date.getTime()) {1663 this._base_setDateDatepicker.apply(this, arguments);1664 date = $(target).datepicker('getDate');1665 }1666 }16671668 var tp_inst = this._get(inst, 'timepicker');1669 var tp_date;1670 if (date instanceof Date) {1671 tp_date = new Date(date.getTime());1672 tp_date.setMicroseconds(date.getMicroseconds());1673 } else {1674 tp_date = date;1675 }1676 1677 // This is important if you are using the timezone option, javascript's Date 1678 // object will only return the timezone offset for the current locale, so we 1679 // adjust it accordingly. If not using timezone option this won't matter..1680 // If a timezone is different in tp, keep the timezone as is1681 if (tp_inst && tp_date) {1682 // look out for DST if tz wasn't specified1683 if (!tp_inst.support.timezone && tp_inst._defaults.timezone === null) {1684 tp_inst.timezone = tp_date.getTimezoneOffset() * -1;1685 }1686 date = $.timepicker.timezoneAdjust(date, tp_inst.timezone);1687 tp_date = $.timepicker.timezoneAdjust(tp_date, tp_inst.timezone);1688 }16891690 this._updateDatepicker(inst);1691 this._base_setDateDatepicker.apply(this, arguments);1692 this._setTimeDatepicker(target, tp_date, true);1693 };16941695 /*1696 * override getDate() to allow getting time too within Date object1697 */1698 $.datepicker._base_getDateDatepicker = $.datepicker._getDateDatepicker;1699 $.datepicker._getDateDatepicker = function (target, noDefault) {1700 var inst = this._getInst(target);1701 if (!inst) {1702 return;1703 }17041705 var tp_inst = this._get(inst, 'timepicker');17061707 if (tp_inst) {1708 // if it hasn't yet been defined, grab from field1709 if (inst.lastVal === undefined) {1710 this._setDateFromField(inst, noDefault);1711 }17121713 var date = this._getDate(inst);1714 var currDT = $.trim((tp_inst.$altInput && tp_inst._defaults.altFieldTimeOnly) ? tp_inst.$input.val() + ' ' + tp_inst.$altInput.val() : tp_inst.$input.val());1715 if (date && tp_inst._parseTime(currDT, !inst.settings.timeOnly)) {1716 date.setHours(tp_inst.hour, tp_inst.minute, tp_inst.second, tp_inst.millisec);1717 date.setMicroseconds(tp_inst.microsec);17181719 // This is important if you are using the timezone option, javascript's Date 1720 // object will only return the timezone offset for the current locale, so we 1721 // adjust it accordingly. If not using timezone option this won't matter..1722 if (tp_inst.timezone != null) {1723 // look out for DST if tz wasn't specified1724 if (!tp_inst.support.timezone && tp_inst._defaults.timezone === null) {1725 tp_inst.timezone = date.getTimezoneOffset() * -1;1726 }1727 date = $.timepicker.timezoneAdjust(date, tp_inst.timezone);1728 }1729 }1730 return date;1731 }1732 return this._base_getDateDatepicker(target, noDefault);1733 };17341735 /*1736 * override parseDate() because UI 1.8.14 throws an error about "Extra characters"1737 * An option in datapicker to ignore extra format characters would be nicer.1738 */1739 $.datepicker._base_parseDate = $.datepicker.parseDate;1740 $.datepicker.parseDate = function (format, value, settings) {1741 var date;1742 try {1743 date = this._base_parseDate(format, value, settings);1744 } catch (err) {1745 // Hack! The error message ends with a colon, a space, and1746 // the "extra" characters. We rely on that instead of1747 // attempting to perfectly reproduce the parsing algorithm.1748 if (err.indexOf(":") >= 0) {1749 date = this._base_parseDate(format, value.substring(0, value.length - (err.length - err.indexOf(':') - 2)), settings);1750 $.timepicker.log("Error parsing the date string: " + err + "\ndate string = " + value + "\ndate format = " + format);1751 } else {1752 throw err;1753 }1754 }1755 return date;1756 };17571758 /*1759 * override formatDate to set date with time to the input1760 */1761 $.datepicker._base_formatDate = $.datepicker._formatDate;1762 $.datepicker._formatDate = function (inst, day, month, year) {1763 var tp_inst = this._get(inst, 'timepicker');1764 if (tp_inst) {1765 tp_inst._updateDateTime(inst);1766 return tp_inst.$input.val();1767 }1768 return this._base_formatDate(inst);1769 };17701771 /*1772 * override options setter to add time to maxDate(Time) and minDate(Time). MaxDate1773 */1774 $.datepicker._base_optionDatepicker = $.datepicker._optionDatepicker;1775 $.datepicker._optionDatepicker = function (target, name, value) {1776 var inst = this._getInst(target),1777 name_clone;1778 if (!inst) {1779 return null;1780 }17811782 var tp_inst = this._get(inst, 'timepicker');1783 if (tp_inst) {1784 var min = null,1785 max = null,1786 onselect = null,1787 overrides = tp_inst._defaults.evnts,1788 fns = {},1789 prop,1790 ret,1791 oldVal,1792 $target;1793 if (typeof name === 'string') { // if min/max was set with the string1794 if (name === 'minDate' || name === 'minDateTime') {1795 min = value;1796 } else if (name === 'maxDate' || name === 'maxDateTime') {1797 max = value;1798 } else if (name === 'onSelect') {1799 onselect = value;1800 } else if (overrides.hasOwnProperty(name)) {1801 if (typeof (value) === 'undefined') {1802 return overrides[name];1803 }1804 fns[name] = value;1805 name_clone = {}; //empty results in exiting function after overrides updated1806 }1807 } else if (typeof name === 'object') { //if min/max was set with the JSON1808 if (name.minDate) {1809 min = name.minDate;1810 } else if (name.minDateTime) {1811 min = name.minDateTime;1812 } else if (name.maxDate) {1813 max = name.maxDate;1814 } else if (name.maxDateTime) {1815 max = name.maxDateTime;1816 }1817 for (prop in overrides) {1818 if (overrides.hasOwnProperty(prop) && name[prop]) {1819 fns[prop] = name[prop];1820 }1821 }1822 }1823 for (prop in fns) {1824 if (fns.hasOwnProperty(prop)) {1825 overrides[prop] = fns[prop];1826 if (!name_clone) { name_clone = $.extend({}, name); }1827 delete name_clone[prop];1828 }1829 }1830 if (name_clone && isEmptyObject(name_clone)) { return; }1831 if (min) { //if min was set1832 if (min === 0) {1833 min = new Date();1834 } else {1835 min = new Date(min);1836 }1837 tp_inst._defaults.minDate = min;1838 tp_inst._defaults.minDateTime = min;1839 } else if (max) { //if max was set1840 if (max === 0) {1841 max = new Date();1842 } else {1843 max = new Date(max);1844 }1845 tp_inst._defaults.maxDate = max;1846 tp_inst._defaults.maxDateTime = max;1847 } else if (onselect) {1848 tp_inst._defaults.onSelect = onselect;1849 }18501851 // Datepicker will override our date when we call _base_optionDatepicker when 1852 // calling minDate/maxDate, so we will first grab the value, call 1853 // _base_optionDatepicker, then set our value back.1854 if(min || max){1855 $target = $(target);1856 oldVal = $target.datetimepicker('getDate');1857 ret = this._base_optionDatepicker.call($.datepicker, target, name_clone || name, value);1858 $target.datetimepicker('setDate', oldVal);1859 return ret;1860 }1861 }1862 if (value === undefined) {1863 return this._base_optionDatepicker.call($.datepicker, target, name);1864 }1865 return this._base_optionDatepicker.call($.datepicker, target, name_clone || name, value);1866 };1867 1868 /*1869 * jQuery isEmptyObject does not check hasOwnProperty - if someone has added to the object prototype,1870 * it will return false for all objects1871 */1872 var isEmptyObject = function (obj) {1873 var prop;1874 for (prop in obj) {1875 if (obj.hasOwnProperty(prop)) {1876 return false;1877 }1878 }1879 return true;1880 };18811882 /*1883 * jQuery extend now ignores nulls!1884 */1885 var extendRemove = function (target, props) {1886 $.extend(target, props);1887 for (var name in props) {1888 if (props[name] === null || props[name] === undefined) {1889 target[name] = props[name];1890 }1891 }1892 return target;1893 };18941895 /*1896 * Determine by the time format which units are supported1897 * Returns an object of booleans for each unit1898 */1899 var detectSupport = function (timeFormat) {1900 var tf = timeFormat.replace(/'.*?'/g, '').toLowerCase(), // removes literals1901 isIn = function (f, t) { // does the format contain the token?1902 return f.indexOf(t) !== -1 ? true : false;1903 };1904 return {1905 hour: isIn(tf, 'h'),1906 minute: isIn(tf, 'm'),1907 second: isIn(tf, 's'),1908 millisec: isIn(tf, 'l'),1909 microsec: isIn(tf, 'c'),1910 timezone: isIn(tf, 'z'),1911 ampm: isIn(tf, 't') && isIn(timeFormat, 'h'),1912 iso8601: isIn(timeFormat, 'Z')1913 };1914 };19151916 /*1917 * Converts 24 hour format into 12 hour1918 * Returns 12 hour without leading 01919 */1920 var convert24to12 = function (hour) {1921 hour %= 12;19221923 if (hour === 0) {1924 hour = 12;1925 }19261927 return String(hour);1928 };19291930 var computeEffectiveSetting = function (settings, property) {1931 return settings && settings[property] ? settings[property] : $.timepicker._defaults[property];1932 };19331934 /*1935 * Splits datetime string into date and time substrings.1936 * Throws exception when date can't be parsed1937 * Returns {dateString: dateString, timeString: timeString}1938 */1939 var splitDateTime = function (dateTimeString, timeSettings) {1940 // The idea is to get the number separator occurrences in datetime and the time format requested (since time has1941 // fewer unknowns, mostly numbers and am/pm). We will use the time pattern to split.1942 var separator = computeEffectiveSetting(timeSettings, 'separator'),1943 format = computeEffectiveSetting(timeSettings, 'timeFormat'),1944 timeParts = format.split(separator), // how many occurrences of separator may be in our format?1945 timePartsLen = timeParts.length,1946 allParts = dateTimeString.split(separator),1947 allPartsLen = allParts.length;19481949 if (allPartsLen > 1) {1950 return {1951 dateString: allParts.splice(0, allPartsLen - timePartsLen).join(separator),1952 timeString: allParts.splice(0, timePartsLen).join(separator)1953 };1954 }19551956 return {1957 dateString: dateTimeString,1958 timeString: ''1959 };1960 };19611962 /*1963 * Internal function to parse datetime interval1964 * Returns: {date: Date, timeObj: Object}, where1965 * date - parsed date without time (type Date)1966 * timeObj = {hour: , minute: , second: , millisec: , microsec: } - parsed time. Optional1967 */1968 var parseDateTimeInternal = function (dateFormat, timeFormat, dateTimeString, dateSettings, timeSettings) {1969 var date,1970 parts,1971 parsedTime;19721973 parts = splitDateTime(dateTimeString, timeSettings);1974 date = $.datepicker._base_parseDate(dateFormat, parts.dateString, dateSettings);19751976 if (parts.timeString === '') {1977 return {1978 date: date1979 };1980 }19811982 parsedTime = $.datepicker.parseTime(timeFormat, parts.timeString, timeSettings);19831984 if (!parsedTime) {1985 throw 'Wrong time format';1986 }19871988 return {1989 date: date,1990 timeObj: parsedTime1991 };1992 };19931994 /*1995 * Internal function to set timezone_select to the local timezone1996 */1997 var selectLocalTimezone = function (tp_inst, date) {1998 if (tp_inst && tp_inst.timezone_select) {1999 var now = date || new Date();2000 tp_inst.timezone_select.val(-now.getTimezoneOffset());2001 }2002 };20032004 /*2005 * Create a Singleton Instance2006 */2007 $.timepicker = new Timepicker();20082009 /**2010 * Get the timezone offset as string from a date object (eg '+0530' for UTC+5.5)2011 * @param {number} tzMinutes if not a number, less than -720 (-1200), or greater than 840 (+1400) this value is returned2012 * @param {boolean} iso8601 if true formats in accordance to iso8601 "+12:45"2013 * @return {string}2014 */2015 $.timepicker.timezoneOffsetString = function (tzMinutes, iso8601) {2016 if (isNaN(tzMinutes) || tzMinutes > 840 || tzMinutes < -720) {2017 return tzMinutes;2018 }20192020 var off = tzMinutes,2021 minutes = off % 60,2022 hours = (off - minutes) / 60,2023 iso = iso8601 ? ':' : '',2024 tz = (off >= 0 ? '+' : '-') + ('0' + Math.abs(hours)).slice(-2) + iso + ('0' + Math.abs(minutes)).slice(-2);2025 2026 if (tz === '+00:00') {2027 return 'Z';2028 }2029 return tz;2030 };20312032 /**2033 * Get the number in minutes that represents a timezone string2034 * @param {string} tzString formatted like "+0500", "-1245", "Z"2035 * @return {number} the offset minutes or the original string if it doesn't match expectations2036 */2037 $.timepicker.timezoneOffsetNumber = function (tzString) {2038 var normalized = tzString.toString().replace(':', ''); // excuse any iso8601, end up with "+1245"20392040 if (normalized.toUpperCase() === 'Z') { // if iso8601 with Z, its 0 minute offset2041 return 0;2042 }20432044 if (!/^(\-|\+)\d{4}$/.test(normalized)) { // possibly a user defined tz, so just give it back2045 return tzString;2046 }20472048 return ((normalized.substr(0, 1) === '-' ? -1 : 1) * // plus or minus2049 ((parseInt(normalized.substr(1, 2), 10) * 60) + // hours (converted to minutes)2050 parseInt(normalized.substr(3, 2), 10))); // minutes2051 };20522053 /**2054 * No way to set timezone in js Date, so we must adjust the minutes to compensate. (think setDate, getDate)2055 * @param {Date} date2056 * @param {string} toTimezone formatted like "+0500", "-1245"2057 * @return {Date}2058 */2059 $.timepicker.timezoneAdjust = function (date, toTimezone) {2060 var toTz = $.timepicker.timezoneOffsetNumber(toTimezone);2061 if (!isNaN(toTz)) {2062 date.setMinutes(date.getMinutes() + -date.getTimezoneOffset() - toTz);2063 }2064 return date;2065 };20662067 /**2068 * Calls `timepicker()` on the `startTime` and `endTime` elements, and configures them to2069 * enforce date range limits.2070 * n.b. The input value must be correctly formatted (reformatting is not supported)2071 * @param {Element} startTime2072 * @param {Element} endTime2073 * @param {Object} options Options for the timepicker() call2074 * @return {jQuery}2075 */2076 $.timepicker.timeRange = function (startTime, endTime, options) {2077 return $.timepicker.handleRange('timepicker', startTime, endTime, options);2078 };20792080 /**2081 * Calls `datetimepicker` on the `startTime` and `endTime` elements, and configures them to2082 * enforce date range limits.2083 * @param {Element} startTime2084 * @param {Element} endTime2085 * @param {Object} options Options for the `timepicker()` call. Also supports `reformat`,2086 * a boolean value that can be used to reformat the input values to the `dateFormat`.2087 * @param {string} method Can be used to specify the type of picker to be added2088 * @return {jQuery}2089 */2090 $.timepicker.datetimeRange = function (startTime, endTime, options) {2091 $.timepicker.handleRange('datetimepicker', startTime, endTime, options);2092 };20932094 /**2095 * Calls `datepicker` on the `startTime` and `endTime` elements, and configures them to2096 * enforce date range limits.2097 * @param {Element} startTime2098 * @param {Element} endTime2099 * @param {Object} options Options for the `timepicker()` call. Also supports `reformat`,2100 * a boolean value that can be used to reformat the input values to the `dateFormat`.2101 * @return {jQuery}2102 */2103 $.timepicker.dateRange = function (startTime, endTime, options) {2104 $.timepicker.handleRange('datepicker', startTime, endTime, options);2105 };21062107 /**2108 * Calls `method` on the `startTime` and `endTime` elements, and configures them to2109 * enforce date range limits.2110 * @param {string} method Can be used to specify the type of picker to be added2111 * @param {Element} startTime2112 * @param {Element} endTime2113 * @param {Object} options Options for the `timepicker()` call. Also supports `reformat`,2114 * a boolean value that can be used to reformat the input values to the `dateFormat`.2115 * @return {jQuery}2116 */2117 $.timepicker.handleRange = function (method, startTime, endTime, options) {2118 options = $.extend({}, {2119 minInterval: 0, // min allowed interval in milliseconds2120 maxInterval: 0, // max allowed interval in milliseconds2121 start: {}, // options for start picker2122 end: {} // options for end picker2123 }, options);21242125 // for the mean time this fixes an issue with calling getDate with timepicker()2126 var timeOnly = false;2127 if(method === 'timepicker'){2128 timeOnly = true;2129 method = 'datetimepicker';2130 }21312132 function checkDates(changed, other) {2133 var startdt = startTime[method]('getDate'),2134 enddt = endTime[method]('getDate'),2135 changeddt = changed[method]('getDate');21362137 if (startdt !== null) {2138 var minDate = new Date(startdt.getTime()),2139 maxDate = new Date(startdt.getTime());21402141 minDate.setMilliseconds(minDate.getMilliseconds() + options.minInterval);2142 maxDate.setMilliseconds(maxDate.getMilliseconds() + options.maxInterval);21432144 if (options.minInterval > 0 && minDate > enddt) { // minInterval check2145 endTime[method]('setDate', minDate);2146 }2147 else if (options.maxInterval > 0 && maxDate < enddt) { // max interval check2148 endTime[method]('setDate', maxDate);2149 }2150 else if (startdt > enddt) {2151 other[method]('setDate', changeddt);2152 }2153 }2154 }21552156 function selected(changed, other, option) {2157 if (!changed.val()) {2158 return;2159 }2160 var date = changed[method].call(changed, 'getDate');2161 if (date !== null && options.minInterval > 0) {2162 if (option === 'minDate') {2163 date.setMilliseconds(date.getMilliseconds() + options.minInterval);2164 }2165 if (option === 'maxDate') {2166 date.setMilliseconds(date.getMilliseconds() - options.minInterval);2167 }2168 }2169 2170 if (date.getTime) {2171 other[method].call(other, 'option', option, date);2172 }2173 }21742175 $.fn[method].call(startTime, $.extend({2176 timeOnly: timeOnly,2177 onClose: function (dateText, inst) {2178 checkDates($(this), endTime);2179 },2180 onSelect: function (selectedDateTime) {2181 selected($(this), endTime, 'minDate');2182 }2183 }, options, options.start));2184 $.fn[method].call(endTime, $.extend({2185 timeOnly: timeOnly,2186 onClose: function (dateText, inst) {2187 checkDates($(this), startTime);2188 },2189 onSelect: function (selectedDateTime) {2190 selected($(this), startTime, 'maxDate');2191 }2192 }, options, options.end));21932194 checkDates(startTime, endTime);2195 2196 selected(startTime, endTime, 'minDate');2197 selected(endTime, startTime, 'maxDate');21982199 return $([startTime.get(0), endTime.get(0)]);2200 };22012202 /**2203 * Log error or data to the console during error or debugging2204 * @param {Object} err pass any type object to log to the console during error or debugging2205 * @return {void}2206 */2207 $.timepicker.log = function () {2208 if (window.console) {2209 window.console.log.apply(window.console, Array.prototype.slice.call(arguments));2210 }2211 };22122213 /*2214 * Add util object to allow access to private methods for testability.2215 */2216 $.timepicker._util = {2217 _extendRemove: extendRemove,2218 _isEmptyObject: isEmptyObject,2219 _convert24to12: convert24to12,2220 _detectSupport: detectSupport,2221 _selectLocalTimezone: selectLocalTimezone,2222 _computeEffectiveSetting: computeEffectiveSetting,2223 _splitDateTime: splitDateTime,2224 _parseDateTimeInternal: parseDateTimeInternal2225 };22262227 /*2228 * Microsecond support2229 */2230 if (!Date.prototype.getMicroseconds) {2231 Date.prototype.microseconds = 0;2232 Date.prototype.getMicroseconds = function () { return this.microseconds; };2233 Date.prototype.setMicroseconds = function (m) {2234 this.setMilliseconds(this.getMilliseconds() + Math.floor(m / 1000));2235 this.microseconds = m % 1000;2236 return this;2237 };2238 }22392240 /*2241 * Keep up with the version2242 */2243 $.timepicker.version = "1.5.5";2244
...
jquery-ui-timepicker.js
Source:jquery-ui-timepicker.js
1/*! jQuery Timepicker Addon - v1.4.6 - 2014-08-092* http://trentrichardson.com/examples/timepicker3* Copyright (c) 2014 Trent Richardson; Licensed MIT */4(function ($) {5 /*6 * Lets not redefine timepicker, Prevent "Uncaught RangeError: Maximum call stack size exceeded"7 */8 $.ui.timepicker = $.ui.timepicker || {};9 if ($.ui.timepicker.version) {10 return;11 }12 /*13 * Extend jQueryUI, get it started with our version number14 */15 $.extend($.ui, {16 timepicker: {17 version: "1.4.6"18 }19 });20 /* 21 * Timepicker manager.22 * Use the singleton instance of this class, $.timepicker, to interact with the time picker.23 * Settings for (groups of) time pickers are maintained in an instance object,24 * allowing multiple different settings on the same page.25 */26 var Timepicker = function () {27 this.regional = []; // Available regional settings, indexed by language code28 this.regional[''] = { // Default regional settings29 currentText: 'Now',30 closeText: 'Done',31 amNames: ['AM', 'A'],32 pmNames: ['PM', 'P'],33 timeFormat: 'HH:mm',34 timeSuffix: '',35 timeOnlyTitle: 'Choose Time',36 timeText: 'Time',37 hourText: 'Hour',38 minuteText: 'Minute',39 secondText: 'Second',40 millisecText: 'Millisecond',41 microsecText: 'Microsecond',42 timezoneText: 'Time Zone',43 isRTL: false44 };45 this._defaults = { // Global defaults for all the datetime picker instances46 showButtonPanel: true,47 timeOnly: false,48 timeOnlyShowDate: false,49 showHour: null,50 showMinute: null,51 showSecond: null,52 showMillisec: null,53 showMicrosec: null,54 showTimezone: null,55 showTime: true,56 stepHour: 1,57 stepMinute: 1,58 stepSecond: 1,59 stepMillisec: 1,60 stepMicrosec: 1,61 hour: 0,62 minute: 0,63 second: 0,64 millisec: 0,65 microsec: 0,66 timezone: null,67 hourMin: 0,68 minuteMin: 0,69 secondMin: 0,70 millisecMin: 0,71 microsecMin: 0,72 hourMax: 23,73 minuteMax: 59,74 secondMax: 59,75 millisecMax: 999,76 microsecMax: 999,77 minDateTime: null,78 maxDateTime: null,79 maxTime: null,80 minTime: null,81 onSelect: null,82 hourGrid: 0,83 minuteGrid: 0,84 secondGrid: 0,85 millisecGrid: 0,86 microsecGrid: 0,87 alwaysSetTime: true,88 separator: ' ',89 altFieldTimeOnly: true,90 altTimeFormat: null,91 altSeparator: null,92 altTimeSuffix: null,93 altRedirectFocus: true,94 pickerTimeFormat: null,95 pickerTimeSuffix: null,96 showTimepicker: true,97 timezoneList: null,98 addSliderAccess: false,99 sliderAccessArgs: null,100 controlType: 'slider',101 defaultValue: null,102 parse: 'strict'103 };104 $.extend(this._defaults, this.regional['']);105 };106 $.extend(Timepicker.prototype, {107 $input: null,108 $altInput: null,109 $timeObj: null,110 inst: null,111 hour_slider: null,112 minute_slider: null,113 second_slider: null,114 millisec_slider: null,115 microsec_slider: null,116 timezone_select: null,117 maxTime: null,118 minTime: null,119 hour: 0,120 minute: 0,121 second: 0,122 millisec: 0,123 microsec: 0,124 timezone: null,125 hourMinOriginal: null,126 minuteMinOriginal: null,127 secondMinOriginal: null,128 millisecMinOriginal: null,129 microsecMinOriginal: null,130 hourMaxOriginal: null,131 minuteMaxOriginal: null,132 secondMaxOriginal: null,133 millisecMaxOriginal: null,134 microsecMaxOriginal: null,135 ampm: '',136 formattedDate: '',137 formattedTime: '',138 formattedDateTime: '',139 timezoneList: null,140 units: ['hour', 'minute', 'second', 'millisec', 'microsec'],141 support: {},142 control: null,143 /* 144 * Override the default settings for all instances of the time picker.145 * @param {Object} settings object - the new settings to use as defaults (anonymous object)146 * @return {Object} the manager object147 */148 setDefaults: function (settings) {149 extendRemove(this._defaults, settings || {});150 return this;151 },152 /*153 * Create a new Timepicker instance154 */155 _newInst: function ($input, opts) {156 var tp_inst = new Timepicker(),157 inlineSettings = {},158 fns = {},159 overrides, i;160 for (var attrName in this._defaults) {161 if (this._defaults.hasOwnProperty(attrName)) {162 var attrValue = $input.attr('time:' + attrName);163 if (attrValue) {164 try {165 inlineSettings[attrName] = eval(attrValue);166 } catch (err) {167 inlineSettings[attrName] = attrValue;168 }169 }170 }171 }172 overrides = {173 beforeShow: function (input, dp_inst) {174 if ($.isFunction(tp_inst._defaults.evnts.beforeShow)) {175 return tp_inst._defaults.evnts.beforeShow.call($input[0], input, dp_inst, tp_inst);176 }177 },178 onChangeMonthYear: function (year, month, dp_inst) {179 // Update the time as well : this prevents the time from disappearing from the $input field.180 tp_inst._updateDateTime(dp_inst);181 if ($.isFunction(tp_inst._defaults.evnts.onChangeMonthYear)) {182 tp_inst._defaults.evnts.onChangeMonthYear.call($input[0], year, month, dp_inst, tp_inst);183 }184 },185 onClose: function (dateText, dp_inst) {186 if (tp_inst.timeDefined === true && $input.val() !== '') {187 tp_inst._updateDateTime(dp_inst);188 }189 if ($.isFunction(tp_inst._defaults.evnts.onClose)) {190 tp_inst._defaults.evnts.onClose.call($input[0], dateText, dp_inst, tp_inst);191 }192 }193 };194 for (i in overrides) {195 if (overrides.hasOwnProperty(i)) {196 fns[i] = opts[i] || null;197 }198 }199 tp_inst._defaults = $.extend({}, this._defaults, inlineSettings, opts, overrides, {200 evnts: fns,201 timepicker: tp_inst // add timepicker as a property of datepicker: $.datepicker._get(dp_inst, 'timepicker');202 });203 tp_inst.amNames = $.map(tp_inst._defaults.amNames, function (val) {204 return val.toUpperCase();205 });206 tp_inst.pmNames = $.map(tp_inst._defaults.pmNames, function (val) {207 return val.toUpperCase();208 });209 // detect which units are supported210 tp_inst.support = detectSupport(211 tp_inst._defaults.timeFormat + 212 (tp_inst._defaults.pickerTimeFormat ? tp_inst._defaults.pickerTimeFormat : '') +213 (tp_inst._defaults.altTimeFormat ? tp_inst._defaults.altTimeFormat : ''));214 // controlType is string - key to our this._controls215 if (typeof(tp_inst._defaults.controlType) === 'string') {216 if (tp_inst._defaults.controlType === 'slider' && typeof($.ui.slider) === 'undefined') {217 tp_inst._defaults.controlType = 'select';218 }219 tp_inst.control = tp_inst._controls[tp_inst._defaults.controlType];220 }221 // controlType is an object and must implement create, options, value methods222 else {223 tp_inst.control = tp_inst._defaults.controlType;224 }225 // prep the timezone options226 var timezoneList = [-720, -660, -600, -570, -540, -480, -420, -360, -300, -270, -240, -210, -180, -120, -60,227 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];228 if (tp_inst._defaults.timezoneList !== null) {229 timezoneList = tp_inst._defaults.timezoneList;230 }231 var tzl = timezoneList.length, tzi = 0, tzv = null;232 if (tzl > 0 && typeof timezoneList[0] !== 'object') {233 for (; tzi < tzl; tzi++) {234 tzv = timezoneList[tzi];235 timezoneList[tzi] = { value: tzv, label: $.timepicker.timezoneOffsetString(tzv, tp_inst.support.iso8601) };236 }237 }238 tp_inst._defaults.timezoneList = timezoneList;239 // set the default units240 tp_inst.timezone = tp_inst._defaults.timezone !== null ? $.timepicker.timezoneOffsetNumber(tp_inst._defaults.timezone) :241 ((new Date()).getTimezoneOffset() * -1);242 tp_inst.hour = tp_inst._defaults.hour < tp_inst._defaults.hourMin ? tp_inst._defaults.hourMin :243 tp_inst._defaults.hour > tp_inst._defaults.hourMax ? tp_inst._defaults.hourMax : tp_inst._defaults.hour;244 tp_inst.minute = tp_inst._defaults.minute < tp_inst._defaults.minuteMin ? tp_inst._defaults.minuteMin :245 tp_inst._defaults.minute > tp_inst._defaults.minuteMax ? tp_inst._defaults.minuteMax : tp_inst._defaults.minute;246 tp_inst.second = tp_inst._defaults.second < tp_inst._defaults.secondMin ? tp_inst._defaults.secondMin :247 tp_inst._defaults.second > tp_inst._defaults.secondMax ? tp_inst._defaults.secondMax : tp_inst._defaults.second;248 tp_inst.millisec = tp_inst._defaults.millisec < tp_inst._defaults.millisecMin ? tp_inst._defaults.millisecMin :249 tp_inst._defaults.millisec > tp_inst._defaults.millisecMax ? tp_inst._defaults.millisecMax : tp_inst._defaults.millisec;250 tp_inst.microsec = tp_inst._defaults.microsec < tp_inst._defaults.microsecMin ? tp_inst._defaults.microsecMin :251 tp_inst._defaults.microsec > tp_inst._defaults.microsecMax ? tp_inst._defaults.microsecMax : tp_inst._defaults.microsec;252 tp_inst.ampm = '';253 tp_inst.$input = $input;254 if (tp_inst._defaults.altField) {255 tp_inst.$altInput = $(tp_inst._defaults.altField);256 if (tp_inst._defaults.altRedirectFocus === true) {257 tp_inst.$altInput.css({258 cursor: 'pointer'259 }).focus(function () {260 $input.trigger("focus");261 });262 }263 }264 if (tp_inst._defaults.minDate === 0 || tp_inst._defaults.minDateTime === 0) {265 tp_inst._defaults.minDate = new Date();266 }267 if (tp_inst._defaults.maxDate === 0 || tp_inst._defaults.maxDateTime === 0) {268 tp_inst._defaults.maxDate = new Date();269 }270 // datepicker needs minDate/maxDate, timepicker needs minDateTime/maxDateTime..271 if (tp_inst._defaults.minDate !== undefined && tp_inst._defaults.minDate instanceof Date) {272 tp_inst._defaults.minDateTime = new Date(tp_inst._defaults.minDate.getTime());273 }274 if (tp_inst._defaults.minDateTime !== undefined && tp_inst._defaults.minDateTime instanceof Date) {275 tp_inst._defaults.minDate = new Date(tp_inst._defaults.minDateTime.getTime());276 }277 if (tp_inst._defaults.maxDate !== undefined && tp_inst._defaults.maxDate instanceof Date) {278 tp_inst._defaults.maxDateTime = new Date(tp_inst._defaults.maxDate.getTime());279 }280 if (tp_inst._defaults.maxDateTime !== undefined && tp_inst._defaults.maxDateTime instanceof Date) {281 tp_inst._defaults.maxDate = new Date(tp_inst._defaults.maxDateTime.getTime());282 }283 tp_inst.$input.bind('focus', function () {284 tp_inst._onFocus();285 });286 return tp_inst;287 },288 /*289 * add our sliders to the calendar290 */291 _addTimePicker: function (dp_inst) {292 var currDT = (this.$altInput && this._defaults.altFieldTimeOnly) ? this.$input.val() + ' ' + this.$altInput.val() : this.$input.val();293 this.timeDefined = this._parseTime(currDT);294 this._limitMinMaxDateTime(dp_inst, false);295 this._injectTimePicker();296 },297 /*298 * parse the time string from input value or _setTime299 */300 _parseTime: function (timeString, withDate) {301 if (!this.inst) {302 this.inst = $.datepicker._getInst(this.$input[0]);303 }304 if (withDate || !this._defaults.timeOnly) {305 var dp_dateFormat = $.datepicker._get(this.inst, 'dateFormat');306 try {307 var parseRes = parseDateTimeInternal(dp_dateFormat, this._defaults.timeFormat, timeString, $.datepicker._getFormatConfig(this.inst), this._defaults);308 if (!parseRes.timeObj) {309 return false;310 }311 $.extend(this, parseRes.timeObj);312 } catch (err) {313 $.timepicker.log("Error parsing the date/time string: " + err +314 "\ndate/time string = " + timeString +315 "\ntimeFormat = " + this._defaults.timeFormat +316 "\ndateFormat = " + dp_dateFormat);317 return false;318 }319 return true;320 } else {321 var timeObj = $.datepicker.parseTime(this._defaults.timeFormat, timeString, this._defaults);322 if (!timeObj) {323 return false;324 }325 $.extend(this, timeObj);326 return true;327 }328 },329 /*330 * generate and inject html for timepicker into ui datepicker331 */332 _injectTimePicker: function () {333 var $dp = this.inst.dpDiv,334 o = this.inst.settings,335 tp_inst = this,336 litem = '',337 uitem = '',338 show = null,339 max = {},340 gridSize = {},341 size = null,342 i = 0,343 l = 0;344 // Prevent displaying twice345 if ($dp.find("div.ui-timepicker-div").length === 0 && o.showTimepicker) {346 var noDisplay = ' style="display:none;"',347 html = '<div class="ui-timepicker-div' + (o.isRTL ? ' ui-timepicker-rtl' : '') + '"><dl>' + '<dt class="ui_tpicker_time_label"' + ((o.showTime) ? '' : noDisplay) + '>' + o.timeText + '</dt>' +348 '<dd class="ui_tpicker_time"' + ((o.showTime) ? '' : noDisplay) + '></dd>';349 // Create the markup350 for (i = 0, l = this.units.length; i < l; i++) {351 litem = this.units[i];352 uitem = litem.substr(0, 1).toUpperCase() + litem.substr(1);353 show = o['show' + uitem] !== null ? o['show' + uitem] : this.support[litem];354 // Added by Peter Medeiros:355 // - Figure out what the hour/minute/second max should be based on the step values.356 // - Example: if stepMinute is 15, then minMax is 45.357 max[litem] = parseInt((o[litem + 'Max'] - ((o[litem + 'Max'] - o[litem + 'Min']) % o['step' + uitem])), 10);358 gridSize[litem] = 0;359 html += '<dt class="ui_tpicker_' + litem + '_label"' + (show ? '' : noDisplay) + '>' + o[litem + 'Text'] + '</dt>' +360 '<dd class="ui_tpicker_' + litem + '"><div class="ui_tpicker_' + litem + '_slider"' + (show ? '' : noDisplay) + '></div>';361 if (show && o[litem + 'Grid'] > 0) {362 html += '<div style="padding-left: 1px"><table class="ui-tpicker-grid-label"><tr>';363 if (litem === 'hour') {364 for (var h = o[litem + 'Min']; h <= max[litem]; h += parseInt(o[litem + 'Grid'], 10)) {365 gridSize[litem]++;366 var tmph = $.datepicker.formatTime(this.support.ampm ? 'hht' : 'HH', {hour: h}, o);367 html += '<td data-for="' + litem + '">' + tmph + '</td>';368 }369 }370 else {371 for (var m = o[litem + 'Min']; m <= max[litem]; m += parseInt(o[litem + 'Grid'], 10)) {372 gridSize[litem]++;373 html += '<td data-for="' + litem + '">' + ((m < 10) ? '0' : '') + m + '</td>';374 }375 }376 html += '</tr></table></div>';377 }378 html += '</dd>';379 }380 381 // Timezone382 var showTz = o.showTimezone !== null ? o.showTimezone : this.support.timezone;383 html += '<dt class="ui_tpicker_timezone_label"' + (showTz ? '' : noDisplay) + '>' + o.timezoneText + '</dt>';384 html += '<dd class="ui_tpicker_timezone" ' + (showTz ? '' : noDisplay) + '></dd>';385 // Create the elements from string386 html += '</dl></div>';387 var $tp = $(html);388 // if we only want time picker...389 if (o.timeOnly === true) {390 $tp.prepend('<div class="ui-widget-header ui-helper-clearfix ui-corner-all">' + '<div class="ui-datepicker-title">' + o.timeOnlyTitle + '</div>' + '</div>');391 $dp.find('.ui-datepicker-header, .ui-datepicker-calendar').hide();392 }393 394 // add sliders, adjust grids, add events395 for (i = 0, l = tp_inst.units.length; i < l; i++) {396 litem = tp_inst.units[i];397 uitem = litem.substr(0, 1).toUpperCase() + litem.substr(1);398 show = o['show' + uitem] !== null ? o['show' + uitem] : this.support[litem];399 // add the slider400 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]);401 // adjust the grid and add click event402 if (show && o[litem + 'Grid'] > 0) {403 size = 100 * gridSize[litem] * o[litem + 'Grid'] / (max[litem] - o[litem + 'Min']);404 $tp.find('.ui_tpicker_' + litem + ' table').css({405 width: size + "%",406 marginLeft: o.isRTL ? '0' : ((size / (-2 * gridSize[litem])) + "%"),407 marginRight: o.isRTL ? ((size / (-2 * gridSize[litem])) + "%") : '0',408 borderCollapse: 'collapse'409 }).find("td").click(function (e) {410 var $t = $(this),411 h = $t.html(),412 n = parseInt(h.replace(/[^0-9]/g), 10),413 ap = h.replace(/[^apm]/ig),414 f = $t.data('for'); // loses scope, so we use data-for415 if (f === 'hour') {416 if (ap.indexOf('p') !== -1 && n < 12) {417 n += 12;418 }419 else {420 if (ap.indexOf('a') !== -1 && n === 12) {421 n = 0;422 }423 }424 }425 426 tp_inst.control.value(tp_inst, tp_inst[f + '_slider'], litem, n);427 tp_inst._onTimeChange();428 tp_inst._onSelectHandler();429 }).css({430 cursor: 'pointer',431 width: (100 / gridSize[litem]) + '%',432 textAlign: 'center',433 overflow: 'hidden'434 });435 } // end if grid > 0436 } // end for loop437 // Add timezone options438 this.timezone_select = $tp.find('.ui_tpicker_timezone').append('<select></select>').find("select");439 $.fn.append.apply(this.timezone_select,440 $.map(o.timezoneList, function (val, idx) {441 return $("<option />").val(typeof val === "object" ? val.value : val).text(typeof val === "object" ? val.label : val);442 }));443 if (typeof(this.timezone) !== "undefined" && this.timezone !== null && this.timezone !== "") {444 var local_timezone = (new Date(this.inst.selectedYear, this.inst.selectedMonth, this.inst.selectedDay, 12)).getTimezoneOffset() * -1;445 if (local_timezone === this.timezone) {446 selectLocalTimezone(tp_inst);447 } else {448 this.timezone_select.val(this.timezone);449 }450 } else {451 if (typeof(this.hour) !== "undefined" && this.hour !== null && this.hour !== "") {452 this.timezone_select.val(o.timezone);453 } else {454 selectLocalTimezone(tp_inst);455 }456 }457 this.timezone_select.change(function () {458 tp_inst._onTimeChange();459 tp_inst._onSelectHandler();460 });461 // End timezone options462 463 // inject timepicker into datepicker464 var $buttonPanel = $dp.find('.ui-datepicker-buttonpane');465 if ($buttonPanel.length) {466 $buttonPanel.before($tp);467 } else {468 $dp.append($tp);469 }470 this.$timeObj = $tp.find('.ui_tpicker_time');471 if (this.inst !== null) {472 var timeDefined = this.timeDefined;473 this._onTimeChange();474 this.timeDefined = timeDefined;475 }476 // slideAccess integration: http://trentrichardson.com/2011/11/11/jquery-ui-sliders-and-touch-accessibility/477 if (this._defaults.addSliderAccess) {478 var sliderAccessArgs = this._defaults.sliderAccessArgs,479 rtl = this._defaults.isRTL;480 sliderAccessArgs.isRTL = rtl;481 482 setTimeout(function () { // fix for inline mode483 if ($tp.find('.ui-slider-access').length === 0) {484 $tp.find('.ui-slider:visible').sliderAccess(sliderAccessArgs);485 // fix any grids since sliders are shorter486 var sliderAccessWidth = $tp.find('.ui-slider-access:eq(0)').outerWidth(true);487 if (sliderAccessWidth) {488 $tp.find('table:visible').each(function () {489 var $g = $(this),490 oldWidth = $g.outerWidth(),491 oldMarginLeft = $g.css(rtl ? 'marginRight' : 'marginLeft').toString().replace('%', ''),492 newWidth = oldWidth - sliderAccessWidth,493 newMarginLeft = ((oldMarginLeft * newWidth) / oldWidth) + '%',494 css = { width: newWidth, marginRight: 0, marginLeft: 0 };495 css[rtl ? 'marginRight' : 'marginLeft'] = newMarginLeft;496 $g.css(css);497 });498 }499 }500 }, 10);501 }502 // end slideAccess integration503 tp_inst._limitMinMaxDateTime(this.inst, true);504 }505 },506 /*507 * This function tries to limit the ability to go outside the508 * min/max date range509 */510 _limitMinMaxDateTime: function (dp_inst, adjustSliders) {511 var o = this._defaults,512 dp_date = new Date(dp_inst.selectedYear, dp_inst.selectedMonth, dp_inst.selectedDay);513 if (!this._defaults.showTimepicker) {514 return;515 } // No time so nothing to check here516 if ($.datepicker._get(dp_inst, 'minDateTime') !== null && $.datepicker._get(dp_inst, 'minDateTime') !== undefined && dp_date) {517 var minDateTime = $.datepicker._get(dp_inst, 'minDateTime'),518 minDateTimeDate = new Date(minDateTime.getFullYear(), minDateTime.getMonth(), minDateTime.getDate(), 0, 0, 0, 0);519 if (this.hourMinOriginal === null || this.minuteMinOriginal === null || this.secondMinOriginal === null || this.millisecMinOriginal === null || this.microsecMinOriginal === null) {520 this.hourMinOriginal = o.hourMin;521 this.minuteMinOriginal = o.minuteMin;522 this.secondMinOriginal = o.secondMin;523 this.millisecMinOriginal = o.millisecMin;524 this.microsecMinOriginal = o.microsecMin;525 }526 if (dp_inst.settings.timeOnly || minDateTimeDate.getTime() === dp_date.getTime()) {527 this._defaults.hourMin = minDateTime.getHours();528 if (this.hour <= this._defaults.hourMin) {529 this.hour = this._defaults.hourMin;530 this._defaults.minuteMin = minDateTime.getMinutes();531 if (this.minute <= this._defaults.minuteMin) {532 this.minute = this._defaults.minuteMin;533 this._defaults.secondMin = minDateTime.getSeconds();534 if (this.second <= this._defaults.secondMin) {535 this.second = this._defaults.secondMin;536 this._defaults.millisecMin = minDateTime.getMilliseconds();537 if (this.millisec <= this._defaults.millisecMin) {538 this.millisec = this._defaults.millisecMin;539 this._defaults.microsecMin = minDateTime.getMicroseconds();540 } else {541 if (this.microsec < this._defaults.microsecMin) {542 this.microsec = this._defaults.microsecMin;543 }544 this._defaults.microsecMin = this.microsecMinOriginal;545 }546 } else {547 this._defaults.millisecMin = this.millisecMinOriginal;548 this._defaults.microsecMin = this.microsecMinOriginal;549 }550 } else {551 this._defaults.secondMin = this.secondMinOriginal;552 this._defaults.millisecMin = this.millisecMinOriginal;553 this._defaults.microsecMin = this.microsecMinOriginal;554 }555 } else {556 this._defaults.minuteMin = this.minuteMinOriginal;557 this._defaults.secondMin = this.secondMinOriginal;558 this._defaults.millisecMin = this.millisecMinOriginal;559 this._defaults.microsecMin = this.microsecMinOriginal;560 }561 } else {562 this._defaults.hourMin = this.hourMinOriginal;563 this._defaults.minuteMin = this.minuteMinOriginal;564 this._defaults.secondMin = this.secondMinOriginal;565 this._defaults.millisecMin = this.millisecMinOriginal;566 this._defaults.microsecMin = this.microsecMinOriginal;567 }568 }569 if ($.datepicker._get(dp_inst, 'maxDateTime') !== null && $.datepicker._get(dp_inst, 'maxDateTime') !== undefined && dp_date) {570 var maxDateTime = $.datepicker._get(dp_inst, 'maxDateTime'),571 maxDateTimeDate = new Date(maxDateTime.getFullYear(), maxDateTime.getMonth(), maxDateTime.getDate(), 0, 0, 0, 0);572 if (this.hourMaxOriginal === null || this.minuteMaxOriginal === null || this.secondMaxOriginal === null || this.millisecMaxOriginal === null) {573 this.hourMaxOriginal = o.hourMax;574 this.minuteMaxOriginal = o.minuteMax;575 this.secondMaxOriginal = o.secondMax;576 this.millisecMaxOriginal = o.millisecMax;577 this.microsecMaxOriginal = o.microsecMax;578 }579 if (dp_inst.settings.timeOnly || maxDateTimeDate.getTime() === dp_date.getTime()) {580 this._defaults.hourMax = maxDateTime.getHours();581 if (this.hour >= this._defaults.hourMax) {582 this.hour = this._defaults.hourMax;583 this._defaults.minuteMax = maxDateTime.getMinutes();584 if (this.minute >= this._defaults.minuteMax) {585 this.minute = this._defaults.minuteMax;586 this._defaults.secondMax = maxDateTime.getSeconds();587 if (this.second >= this._defaults.secondMax) {588 this.second = this._defaults.secondMax;589 this._defaults.millisecMax = maxDateTime.getMilliseconds();590 if (this.millisec >= this._defaults.millisecMax) {591 this.millisec = this._defaults.millisecMax;592 this._defaults.microsecMax = maxDateTime.getMicroseconds();593 } else {594 if (this.microsec > this._defaults.microsecMax) {595 this.microsec = this._defaults.microsecMax;596 }597 this._defaults.microsecMax = this.microsecMaxOriginal;598 }599 } else {600 this._defaults.millisecMax = this.millisecMaxOriginal;601 this._defaults.microsecMax = this.microsecMaxOriginal;602 }603 } else {604 this._defaults.secondMax = this.secondMaxOriginal;605 this._defaults.millisecMax = this.millisecMaxOriginal;606 this._defaults.microsecMax = this.microsecMaxOriginal;607 }608 } else {609 this._defaults.minuteMax = this.minuteMaxOriginal;610 this._defaults.secondMax = this.secondMaxOriginal;611 this._defaults.millisecMax = this.millisecMaxOriginal;612 this._defaults.microsecMax = this.microsecMaxOriginal;613 }614 } else {615 this._defaults.hourMax = this.hourMaxOriginal;616 this._defaults.minuteMax = this.minuteMaxOriginal;617 this._defaults.secondMax = this.secondMaxOriginal;618 this._defaults.millisecMax = this.millisecMaxOriginal;619 this._defaults.microsecMax = this.microsecMaxOriginal;620 }621 }622 if (dp_inst.settings.minTime!==null) { 623 var tempMinTime=new Date("01/01/1970 " + dp_inst.settings.minTime); 624 if (this.hour<tempMinTime.getHours()) {625 this.hour=this._defaults.hourMin=tempMinTime.getHours();626 this.minute=this._defaults.minuteMin=tempMinTime.getMinutes(); 627 } else if (this.hour===tempMinTime.getHours() && this.minute<tempMinTime.getMinutes()) {628 this.minute=this._defaults.minuteMin=tempMinTime.getMinutes();629 } else { 630 if (this._defaults.hourMin<tempMinTime.getHours()) {631 this._defaults.hourMin=tempMinTime.getHours();632 this._defaults.minuteMin=tempMinTime.getMinutes(); 633 } else if (this._defaults.hourMin===tempMinTime.getHours()===this.hour && this._defaults.minuteMin<tempMinTime.getMinutes()) {634 this._defaults.minuteMin=tempMinTime.getMinutes(); 635 } else {636 this._defaults.minuteMin=0;637 }638 } 639 }640 641 if (dp_inst.settings.maxTime!==null) { 642 var tempMaxTime=new Date("01/01/1970 " + dp_inst.settings.maxTime);643 if (this.hour>tempMaxTime.getHours()) {644 this.hour=this._defaults.hourMax=tempMaxTime.getHours(); 645 this.minute=this._defaults.minuteMax=tempMaxTime.getMinutes();646 } else if (this.hour===tempMaxTime.getHours() && this.minute>tempMaxTime.getMinutes()) { 647 this.minute=this._defaults.minuteMax=tempMaxTime.getMinutes(); 648 } else {649 if (this._defaults.hourMax>tempMaxTime.getHours()) {650 this._defaults.hourMax=tempMaxTime.getHours();651 this._defaults.minuteMax=tempMaxTime.getMinutes(); 652 } else if (this._defaults.hourMax===tempMaxTime.getHours()===this.hour && this._defaults.minuteMax>tempMaxTime.getMinutes()) {653 this._defaults.minuteMax=tempMaxTime.getMinutes(); 654 } else {655 this._defaults.minuteMax=59;656 }657 } 658 }659 660 if (adjustSliders !== undefined && adjustSliders === true) {661 var hourMax = parseInt((this._defaults.hourMax - ((this._defaults.hourMax - this._defaults.hourMin) % this._defaults.stepHour)), 10),662 minMax = parseInt((this._defaults.minuteMax - ((this._defaults.minuteMax - this._defaults.minuteMin) % this._defaults.stepMinute)), 10),663 secMax = parseInt((this._defaults.secondMax - ((this._defaults.secondMax - this._defaults.secondMin) % this._defaults.stepSecond)), 10),664 millisecMax = parseInt((this._defaults.millisecMax - ((this._defaults.millisecMax - this._defaults.millisecMin) % this._defaults.stepMillisec)), 10),665 microsecMax = parseInt((this._defaults.microsecMax - ((this._defaults.microsecMax - this._defaults.microsecMin) % this._defaults.stepMicrosec)), 10);666 if (this.hour_slider) {667 this.control.options(this, this.hour_slider, 'hour', { min: this._defaults.hourMin, max: hourMax, step: this._defaults.stepHour });668 this.control.value(this, this.hour_slider, 'hour', this.hour - (this.hour % this._defaults.stepHour));669 }670 if (this.minute_slider) {671 this.control.options(this, this.minute_slider, 'minute', { min: this._defaults.minuteMin, max: minMax, step: this._defaults.stepMinute });672 this.control.value(this, this.minute_slider, 'minute', this.minute - (this.minute % this._defaults.stepMinute));673 }674 if (this.second_slider) {675 this.control.options(this, this.second_slider, 'second', { min: this._defaults.secondMin, max: secMax, step: this._defaults.stepSecond });676 this.control.value(this, this.second_slider, 'second', this.second - (this.second % this._defaults.stepSecond));677 }678 if (this.millisec_slider) {679 this.control.options(this, this.millisec_slider, 'millisec', { min: this._defaults.millisecMin, max: millisecMax, step: this._defaults.stepMillisec });680 this.control.value(this, this.millisec_slider, 'millisec', this.millisec - (this.millisec % this._defaults.stepMillisec));681 }682 if (this.microsec_slider) {683 this.control.options(this, this.microsec_slider, 'microsec', { min: this._defaults.microsecMin, max: microsecMax, step: this._defaults.stepMicrosec });684 this.control.value(this, this.microsec_slider, 'microsec', this.microsec - (this.microsec % this._defaults.stepMicrosec));685 }686 }687 },688 /*689 * when a slider moves, set the internal time...690 * on time change is also called when the time is updated in the text field691 */692 _onTimeChange: function () {693 if (!this._defaults.showTimepicker) {694 return;695 }696 var hour = (this.hour_slider) ? this.control.value(this, this.hour_slider, 'hour') : false,697 minute = (this.minute_slider) ? this.control.value(this, this.minute_slider, 'minute') : false,698 second = (this.second_slider) ? this.control.value(this, this.second_slider, 'second') : false,699 millisec = (this.millisec_slider) ? this.control.value(this, this.millisec_slider, 'millisec') : false,700 microsec = (this.microsec_slider) ? this.control.value(this, this.microsec_slider, 'microsec') : false,701 timezone = (this.timezone_select) ? this.timezone_select.val() : false,702 o = this._defaults,703 pickerTimeFormat = o.pickerTimeFormat || o.timeFormat,704 pickerTimeSuffix = o.pickerTimeSuffix || o.timeSuffix;705 if (typeof(hour) === 'object') {706 hour = false;707 }708 if (typeof(minute) === 'object') {709 minute = false;710 }711 if (typeof(second) === 'object') {712 second = false;713 }714 if (typeof(millisec) === 'object') {715 millisec = false;716 }717 if (typeof(microsec) === 'object') {718 microsec = false;719 }720 if (typeof(timezone) === 'object') {721 timezone = false;722 }723 if (hour !== false) {724 hour = parseInt(hour, 10);725 }726 if (minute !== false) {727 minute = parseInt(minute, 10);728 }729 if (second !== false) {730 second = parseInt(second, 10);731 }732 if (millisec !== false) {733 millisec = parseInt(millisec, 10);734 }735 if (microsec !== false) {736 microsec = parseInt(microsec, 10);737 }738 if (timezone !== false) {739 timezone = timezone.toString();740 }741 var ampm = o[hour < 12 ? 'amNames' : 'pmNames'][0];742 // If the update was done in the input field, the input field should not be updated.743 // If the update was done using the sliders, update the input field.744 var hasChanged = (745 hour !== parseInt(this.hour,10) || // sliders should all be numeric746 minute !== parseInt(this.minute,10) || 747 second !== parseInt(this.second,10) || 748 millisec !== parseInt(this.millisec,10) || 749 microsec !== parseInt(this.microsec,10) || 750 (this.ampm.length > 0 && (hour < 12) !== ($.inArray(this.ampm.toUpperCase(), this.amNames) !== -1)) || 751 (this.timezone !== null && timezone !== this.timezone.toString()) // could be numeric or "EST" format, so use toString()752 );753 if (hasChanged) {754 if (hour !== false) {755 this.hour = hour;756 }757 if (minute !== false) {758 this.minute = minute;759 }760 if (second !== false) {761 this.second = second;762 }763 if (millisec !== false) {764 this.millisec = millisec;765 }766 if (microsec !== false) {767 this.microsec = microsec;768 }769 if (timezone !== false) {770 this.timezone = timezone;771 }772 if (!this.inst) {773 this.inst = $.datepicker._getInst(this.$input[0]);774 }775 this._limitMinMaxDateTime(this.inst, true);776 }777 if (this.support.ampm) {778 this.ampm = ampm;779 }780 // Updates the time within the timepicker781 this.formattedTime = $.datepicker.formatTime(o.timeFormat, this, o);782 if (this.$timeObj) {783 if (pickerTimeFormat === o.timeFormat) {784 this.$timeObj.text(this.formattedTime + pickerTimeSuffix);785 }786 else {787 this.$timeObj.text($.datepicker.formatTime(pickerTimeFormat, this, o) + pickerTimeSuffix);788 }789 }790 this.timeDefined = true;791 if (hasChanged) {792 this._updateDateTime();793 //this.$input.focus(); // may automatically open the picker on setDate794 }795 },796 /*797 * call custom onSelect.798 * bind to sliders slidestop, and grid click.799 */800 _onSelectHandler: function () {801 var onSelect = this._defaults.onSelect || this.inst.settings.onSelect;802 var inputEl = this.$input ? this.$input[0] : null;803 if (onSelect && inputEl) {804 onSelect.apply(inputEl, [this.formattedDateTime, this]);805 }806 },807 /*808 * update our input with the new date time..809 */810 _updateDateTime: function (dp_inst) {811 dp_inst = this.inst || dp_inst;812 var dtTmp = (dp_inst.currentYear > 0? 813 new Date(dp_inst.currentYear, dp_inst.currentMonth, dp_inst.currentDay) : 814 new Date(dp_inst.selectedYear, dp_inst.selectedMonth, dp_inst.selectedDay)),815 dt = $.datepicker._daylightSavingAdjust(dtTmp),816 //dt = $.datepicker._daylightSavingAdjust(new Date(dp_inst.selectedYear, dp_inst.selectedMonth, dp_inst.selectedDay)),817 //dt = $.datepicker._daylightSavingAdjust(new Date(dp_inst.currentYear, dp_inst.currentMonth, dp_inst.currentDay)),818 dateFmt = $.datepicker._get(dp_inst, 'dateFormat'),819 formatCfg = $.datepicker._getFormatConfig(dp_inst),820 timeAvailable = dt !== null && this.timeDefined;821 this.formattedDate = $.datepicker.formatDate(dateFmt, (dt === null ? new Date() : dt), formatCfg);822 var formattedDateTime = this.formattedDate;823 824 // if a slider was changed but datepicker doesn't have a value yet, set it825 if (dp_inst.lastVal === "") {826 dp_inst.currentYear = dp_inst.selectedYear;827 dp_inst.currentMonth = dp_inst.selectedMonth;828 dp_inst.currentDay = dp_inst.selectedDay;829 }830 /*831 * remove following lines to force every changes in date picker to change the input value832 * Bug descriptions: when an input field has a default value, and click on the field to pop up the date picker. 833 * If the user manually empty the value in the input field, the date picker will never change selected value.834 */835 //if (dp_inst.lastVal !== undefined && (dp_inst.lastVal.length > 0 && this.$input.val().length === 0)) {836 // return;837 //}838 if (this._defaults.timeOnly === true && this._defaults.timeOnlyShowDate === false) {839 formattedDateTime = this.formattedTime;840 } else if ((this._defaults.timeOnly !== true && (this._defaults.alwaysSetTime || timeAvailable)) || (this._defaults.timeOnly === true && this._defaults.timeOnlyShowDate === true)) {841 formattedDateTime += this._defaults.separator + this.formattedTime + this._defaults.timeSuffix;842 }843 this.formattedDateTime = formattedDateTime;844 if (!this._defaults.showTimepicker) {845 this.$input.val(this.formattedDate);846 } else if (this.$altInput && this._defaults.timeOnly === false && this._defaults.altFieldTimeOnly === true) {847 this.$altInput.val(this.formattedTime);848 this.$input.val(this.formattedDate);849 } else if (this.$altInput) {850 this.$input.val(formattedDateTime);851 var altFormattedDateTime = '',852 altSeparator = this._defaults.altSeparator !== null ? this._defaults.altSeparator : this._defaults.separator,853 altTimeSuffix = this._defaults.altTimeSuffix !== null ? this._defaults.altTimeSuffix : this._defaults.timeSuffix;854 855 if (!this._defaults.timeOnly) {856 if (this._defaults.altFormat) {857 altFormattedDateTime = $.datepicker.formatDate(this._defaults.altFormat, (dt === null ? new Date() : dt), formatCfg);858 }859 else {860 altFormattedDateTime = this.formattedDate;861 }862 if (altFormattedDateTime) {863 altFormattedDateTime += altSeparator;864 }865 }866 if (this._defaults.altTimeFormat !== null) {867 altFormattedDateTime += $.datepicker.formatTime(this._defaults.altTimeFormat, this, this._defaults) + altTimeSuffix;868 }869 else {870 altFormattedDateTime += this.formattedTime + altTimeSuffix;871 }872 this.$altInput.val(altFormattedDateTime);873 } else {874 this.$input.val(formattedDateTime);875 }876 this.$input.trigger("change");877 },878 _onFocus: function () {879 if (!this.$input.val() && this._defaults.defaultValue) {880 this.$input.val(this._defaults.defaultValue);881 var inst = $.datepicker._getInst(this.$input.get(0)),882 tp_inst = $.datepicker._get(inst, 'timepicker');883 if (tp_inst) {884 if (tp_inst._defaults.timeOnly && (inst.input.val() !== inst.lastVal)) {885 try {886 $.datepicker._updateDatepicker(inst);887 } catch (err) {888 $.timepicker.log(err);889 }890 }891 }892 }893 },894 /*895 * Small abstraction to control types896 * We can add more, just be sure to follow the pattern: create, options, value897 */898 _controls: {899 // slider methods900 slider: {901 create: function (tp_inst, obj, unit, val, min, max, step) {902 var rtl = tp_inst._defaults.isRTL; // if rtl go -60->0 instead of 0->60903 return obj.prop('slide', null).slider({904 orientation: "horizontal",905 value: rtl ? val * -1 : val,906 min: rtl ? max * -1 : min,907 max: rtl ? min * -1 : max,908 step: step,909 slide: function (event, ui) {910 tp_inst.control.value(tp_inst, $(this), unit, rtl ? ui.value * -1 : ui.value);911 tp_inst._onTimeChange();912 },913 stop: function (event, ui) {914 tp_inst._onSelectHandler();915 }916 }); 917 },918 options: function (tp_inst, obj, unit, opts, val) {919 if (tp_inst._defaults.isRTL) {920 if (typeof(opts) === 'string') {921 if (opts === 'min' || opts === 'max') {922 if (val !== undefined) {923 return obj.slider(opts, val * -1);924 }925 return Math.abs(obj.slider(opts));926 }927 return obj.slider(opts);928 }929 var min = opts.min, 930 max = opts.max;931 opts.min = opts.max = null;932 if (min !== undefined) {933 opts.max = min * -1;934 }935 if (max !== undefined) {936 opts.min = max * -1;937 }938 return obj.slider(opts);939 }940 if (typeof(opts) === 'string' && val !== undefined) {941 return obj.slider(opts, val);942 }943 return obj.slider(opts);944 },945 value: function (tp_inst, obj, unit, val) {946 if (tp_inst._defaults.isRTL) {947 if (val !== undefined) {948 return obj.slider('value', val * -1);949 }950 return Math.abs(obj.slider('value'));951 }952 if (val !== undefined) {953 return obj.slider('value', val);954 }955 return obj.slider('value');956 }957 },958 // select methods959 select: {960 create: function (tp_inst, obj, unit, val, min, max, step) {961 var sel = '<select class="ui-timepicker-select" data-unit="' + unit + '" data-min="' + min + '" data-max="' + max + '" data-step="' + step + '">',962 format = tp_inst._defaults.pickerTimeFormat || tp_inst._defaults.timeFormat;963 for (var i = min; i <= max; i += step) {964 sel += '<option value="' + i + '"' + (i === val ? ' selected' : '') + '>';965 if (unit === 'hour') {966 sel += $.datepicker.formatTime($.trim(format.replace(/[^ht ]/ig, '')), {hour: i}, tp_inst._defaults);967 }968 else if (unit === 'millisec' || unit === 'microsec' || i >= 10) { sel += i; }969 else {sel += '0' + i.toString(); }970 sel += '</option>';971 }972 sel += '</select>';973 obj.children('select').remove();974 $(sel).appendTo(obj).change(function (e) {975 tp_inst._onTimeChange();976 tp_inst._onSelectHandler();977 });978 return obj;979 },980 options: function (tp_inst, obj, unit, opts, val) {981 var o = {},982 $t = obj.children('select');983 if (typeof(opts) === 'string') {984 if (val === undefined) {985 return $t.data(opts);986 }987 o[opts] = val; 988 }989 else { o = opts; }990 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'));991 },992 value: function (tp_inst, obj, unit, val) {993 var $t = obj.children('select');994 if (val !== undefined) {995 return $t.val(val);996 }997 return $t.val();998 }999 }1000 } // end _controls1001 });1002 $.fn.extend({1003 /*1004 * shorthand just to use timepicker.1005 */1006 timepicker: function (o) {1007 o = o || {};1008 var tmp_args = Array.prototype.slice.call(arguments);1009 if (typeof o === 'object') {1010 tmp_args[0] = $.extend(o, {1011 timeOnly: true1012 });1013 }1014 return $(this).each(function () {1015 $.fn.datetimepicker.apply($(this), tmp_args);1016 });1017 },1018 /*1019 * extend timepicker to datepicker1020 */1021 datetimepicker: function (o) {1022 o = o || {};1023 var tmp_args = arguments;1024 if (typeof(o) === 'string') {1025 if (o === 'getDate' || (o === 'option' && tmp_args.length === 2 && typeof (tmp_args[1]) === 'string')) {1026 return $.fn.datepicker.apply($(this[0]), tmp_args);1027 } else {1028 return this.each(function () {1029 var $t = $(this);1030 $t.datepicker.apply($t, tmp_args);1031 });1032 }1033 } else {1034 return this.each(function () {1035 var $t = $(this);1036 $t.datepicker($.timepicker._newInst($t, o)._defaults);1037 });1038 }1039 }1040 });1041 /*1042 * Public Utility to parse date and time1043 */1044 $.datepicker.parseDateTime = function (dateFormat, timeFormat, dateTimeString, dateSettings, timeSettings) {1045 var parseRes = parseDateTimeInternal(dateFormat, timeFormat, dateTimeString, dateSettings, timeSettings);1046 if (parseRes.timeObj) {1047 var t = parseRes.timeObj;1048 parseRes.date.setHours(t.hour, t.minute, t.second, t.millisec);1049 parseRes.date.setMicroseconds(t.microsec);1050 }1051 return parseRes.date;1052 };1053 /*1054 * Public utility to parse time1055 */1056 $.datepicker.parseTime = function (timeFormat, timeString, options) {1057 var o = extendRemove(extendRemove({}, $.timepicker._defaults), options || {}),1058 iso8601 = (timeFormat.replace(/\'.*?\'/g, '').indexOf('Z') !== -1);1059 // Strict parse requires the timeString to match the timeFormat exactly1060 var strictParse = function (f, s, o) {1061 // pattern for standard and localized AM/PM markers1062 var getPatternAmpm = function (amNames, pmNames) {1063 var markers = [];1064 if (amNames) {1065 $.merge(markers, amNames);1066 }1067 if (pmNames) {1068 $.merge(markers, pmNames);1069 }1070 markers = $.map(markers, function (val) {1071 return val.replace(/[.*+?|()\[\]{}\\]/g, '\\$&');1072 });1073 return '(' + markers.join('|') + ')?';1074 };1075 // figure out position of time elements.. cause js cant do named captures1076 var getFormatPositions = function (timeFormat) {1077 var finds = timeFormat.toLowerCase().match(/(h{1,2}|m{1,2}|s{1,2}|l{1}|c{1}|t{1,2}|z|'.*?')/g),1078 orders = {1079 h: -1,1080 m: -1,1081 s: -1,1082 l: -1,1083 c: -1,1084 t: -1,1085 z: -11086 };1087 if (finds) {1088 for (var i = 0; i < finds.length; i++) {1089 if (orders[finds[i].toString().charAt(0)] === -1) {1090 orders[finds[i].toString().charAt(0)] = i + 1;1091 }1092 }1093 }1094 return orders;1095 };1096 var regstr = '^' + f.toString()1097 .replace(/([hH]{1,2}|mm?|ss?|[tT]{1,2}|[zZ]|[lc]|'.*?')/g, function (match) {1098 var ml = match.length;1099 switch (match.charAt(0).toLowerCase()) {1100 case 'h':1101 return ml === 1 ? '(\\d?\\d)' : '(\\d{' + ml + '})';1102 case 'm':1103 return ml === 1 ? '(\\d?\\d)' : '(\\d{' + ml + '})';1104 case 's':1105 return ml === 1 ? '(\\d?\\d)' : '(\\d{' + ml + '})';1106 case 'l':1107 return '(\\d?\\d?\\d)';1108 case 'c':1109 return '(\\d?\\d?\\d)';1110 case 'z':1111 return '(z|[-+]\\d\\d:?\\d\\d|\\S+)?';1112 case 't':1113 return getPatternAmpm(o.amNames, o.pmNames);1114 default: // literal escaped in quotes1115 return '(' + match.replace(/\'/g, "").replace(/(\.|\$|\^|\\|\/|\(|\)|\[|\]|\?|\+|\*)/g, function (m) { return "\\" + m; }) + ')?';1116 }1117 })1118 .replace(/\s/g, '\\s?') +1119 o.timeSuffix + '$',1120 order = getFormatPositions(f),1121 ampm = '',1122 treg;1123 treg = s.match(new RegExp(regstr, 'i'));1124 var resTime = {1125 hour: 0,1126 minute: 0,1127 second: 0,1128 millisec: 0,1129 microsec: 01130 };1131 if (treg) {1132 if (order.t !== -1) {1133 if (treg[order.t] === undefined || treg[order.t].length === 0) {1134 ampm = '';1135 resTime.ampm = '';1136 } else {1137 ampm = $.inArray(treg[order.t].toUpperCase(), o.amNames) !== -1 ? 'AM' : 'PM';1138 resTime.ampm = o[ampm === 'AM' ? 'amNames' : 'pmNames'][0];1139 }1140 }1141 if (order.h !== -1) {1142 if (ampm === 'AM' && treg[order.h] === '12') {1143 resTime.hour = 0; // 12am = 0 hour1144 } else {1145 if (ampm === 'PM' && treg[order.h] !== '12') {1146 resTime.hour = parseInt(treg[order.h], 10) + 12; // 12pm = 12 hour, any other pm = hour + 121147 } else {1148 resTime.hour = Number(treg[order.h]);1149 }1150 }1151 }1152 if (order.m !== -1) {1153 resTime.minute = Number(treg[order.m]);1154 }1155 if (order.s !== -1) {1156 resTime.second = Number(treg[order.s]);1157 }1158 if (order.l !== -1) {1159 resTime.millisec = Number(treg[order.l]);1160 }1161 if (order.c !== -1) {1162 resTime.microsec = Number(treg[order.c]);1163 }1164 if (order.z !== -1 && treg[order.z] !== undefined) {1165 resTime.timezone = $.timepicker.timezoneOffsetNumber(treg[order.z]);1166 }1167 return resTime;1168 }1169 return false;1170 };// end strictParse1171 // First try JS Date, if that fails, use strictParse1172 var looseParse = function (f, s, o) {1173 try {1174 var d = new Date('2012-01-01 ' + s);1175 if (isNaN(d.getTime())) {1176 d = new Date('2012-01-01T' + s);1177 if (isNaN(d.getTime())) {1178 d = new Date('01/01/2012 ' + s);1179 if (isNaN(d.getTime())) {1180 throw "Unable to parse time with native Date: " + s;1181 }1182 }1183 }1184 return {1185 hour: d.getHours(),1186 minute: d.getMinutes(),1187 second: d.getSeconds(),1188 millisec: d.getMilliseconds(),1189 microsec: d.getMicroseconds(),1190 timezone: d.getTimezoneOffset() * -11191 };1192 }1193 catch (err) {1194 try {1195 return strictParse(f, s, o);1196 }1197 catch (err2) {1198 $.timepicker.log("Unable to parse \ntimeString: " + s + "\ntimeFormat: " + f);1199 } 1200 }1201 return false;1202 }; // end looseParse1203 1204 if (typeof o.parse === "function") {1205 return o.parse(timeFormat, timeString, o);1206 }1207 if (o.parse === 'loose') {1208 return looseParse(timeFormat, timeString, o);1209 }1210 return strictParse(timeFormat, timeString, o);1211 };1212 /**1213 * Public utility to format the time1214 * @param {string} format format of the time1215 * @param {Object} time Object not a Date for timezones1216 * @param {Object} [options] essentially the regional[].. amNames, pmNames, ampm1217 * @returns {string} the formatted time1218 */1219 $.datepicker.formatTime = function (format, time, options) {1220 options = options || {};1221 options = $.extend({}, $.timepicker._defaults, options);1222 time = $.extend({1223 hour: 0,1224 minute: 0,1225 second: 0,1226 millisec: 0,1227 microsec: 0,1228 timezone: null1229 }, time);1230 var tmptime = format,1231 ampmName = options.amNames[0],1232 hour = parseInt(time.hour, 10);1233 if (hour > 11) {1234 ampmName = options.pmNames[0];1235 }1236 tmptime = tmptime.replace(/(?:HH?|hh?|mm?|ss?|[tT]{1,2}|[zZ]|[lc]|'.*?')/g, function (match) {1237 switch (match) {1238 case 'HH':1239 return ('0' + hour).slice(-2);1240 case 'H':1241 return hour;1242 case 'hh':1243 return ('0' + convert24to12(hour)).slice(-2);1244 case 'h':1245 return convert24to12(hour);1246 case 'mm':1247 return ('0' + time.minute).slice(-2);1248 case 'm':1249 return time.minute;1250 case 'ss':1251 return ('0' + time.second).slice(-2);1252 case 's':1253 return time.second;1254 case 'l':1255 return ('00' + time.millisec).slice(-3);1256 case 'c':1257 return ('00' + time.microsec).slice(-3);1258 case 'z':1259 return $.timepicker.timezoneOffsetString(time.timezone === null ? options.timezone : time.timezone, false);1260 case 'Z':1261 return $.timepicker.timezoneOffsetString(time.timezone === null ? options.timezone : time.timezone, true);1262 case 'T':1263 return ampmName.charAt(0).toUpperCase();1264 case 'TT':1265 return ampmName.toUpperCase();1266 case 't':1267 return ampmName.charAt(0).toLowerCase();1268 case 'tt':1269 return ampmName.toLowerCase();1270 default:1271 return match.replace(/'/g, "");1272 }1273 });1274 return tmptime;1275 };1276 /*1277 * the bad hack :/ override datepicker so it doesn't close on select1278 // inspired: http://stackoverflow.com/questions/1252512/jquery-datepicker-prevent-closing-picker-when-clicking-a-date/1762378#17623781279 */1280 $.datepicker._base_selectDate = $.datepicker._selectDate;1281 $.datepicker._selectDate = function (id, dateStr) {1282 var inst = this._getInst($(id)[0]),1283 tp_inst = this._get(inst, 'timepicker');1284 if (tp_inst && inst.settings.showTimepicker) {1285 tp_inst._limitMinMaxDateTime(inst, true);1286 inst.inline = inst.stay_open = true;1287 //This way the onSelect handler called from calendarpicker get the full dateTime1288 this._base_selectDate(id, dateStr);1289 inst.inline = inst.stay_open = false;1290 this._notifyChange(inst);1291 this._updateDatepicker(inst);1292 } else {1293 this._base_selectDate(id, dateStr);1294 }1295 };1296 /*1297 * second bad hack :/ override datepicker so it triggers an event when changing the input field1298 * and does not redraw the datepicker on every selectDate event1299 */1300 $.datepicker._base_updateDatepicker = $.datepicker._updateDatepicker;1301 $.datepicker._updateDatepicker = function (inst) {1302 // don't popup the datepicker if there is another instance already opened1303 var input = inst.input[0];1304 if ($.datepicker._curInst && $.datepicker._curInst !== inst && $.datepicker._datepickerShowing && $.datepicker._lastInput !== input) {1305 return;1306 }1307 if (typeof(inst.stay_open) !== 'boolean' || inst.stay_open === false) {1308 this._base_updateDatepicker(inst);1309 // Reload the time control when changing something in the input text field.1310 var tp_inst = this._get(inst, 'timepicker');1311 if (tp_inst) {1312 tp_inst._addTimePicker(inst);1313 }1314 }1315 };1316 /*1317 * third bad hack :/ override datepicker so it allows spaces and colon in the input field1318 */1319 $.datepicker._base_doKeyPress = $.datepicker._doKeyPress;1320 $.datepicker._doKeyPress = function (event) {1321 var inst = $.datepicker._getInst(event.target),1322 tp_inst = $.datepicker._get(inst, 'timepicker');1323 if (tp_inst) {1324 if ($.datepicker._get(inst, 'constrainInput')) {1325 var ampm = tp_inst.support.ampm,1326 tz = tp_inst._defaults.showTimezone !== null ? tp_inst._defaults.showTimezone : tp_inst.support.timezone,1327 dateChars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat')),1328 datetimeChars = tp_inst._defaults.timeFormat.toString()1329 .replace(/[hms]/g, '')1330 .replace(/TT/g, ampm ? 'APM' : '')1331 .replace(/Tt/g, ampm ? 'AaPpMm' : '')1332 .replace(/tT/g, ampm ? 'AaPpMm' : '')1333 .replace(/T/g, ampm ? 'AP' : '')1334 .replace(/tt/g, ampm ? 'apm' : '')1335 .replace(/t/g, ampm ? 'ap' : '') + 1336 " " + tp_inst._defaults.separator + 1337 tp_inst._defaults.timeSuffix + 1338 (tz ? tp_inst._defaults.timezoneList.join('') : '') + 1339 (tp_inst._defaults.amNames.join('')) + (tp_inst._defaults.pmNames.join('')) + 1340 dateChars,1341 chr = String.fromCharCode(event.charCode === undefined ? event.keyCode : event.charCode);1342 return event.ctrlKey || (chr < ' ' || !dateChars || datetimeChars.indexOf(chr) > -1);1343 }1344 }1345 return $.datepicker._base_doKeyPress(event);1346 };1347 /*1348 * Fourth bad hack :/ override _updateAlternate function used in inline mode to init altField1349 * Update any alternate field to synchronise with the main field.1350 */1351 $.datepicker._base_updateAlternate = $.datepicker._updateAlternate;1352 $.datepicker._updateAlternate = function (inst) {1353 var tp_inst = this._get(inst, 'timepicker');1354 if (tp_inst) {1355 var altField = tp_inst._defaults.altField;1356 if (altField) { // update alternate field too1357 var altFormat = tp_inst._defaults.altFormat || tp_inst._defaults.dateFormat,1358 date = this._getDate(inst),1359 formatCfg = $.datepicker._getFormatConfig(inst),1360 altFormattedDateTime = '', 1361 altSeparator = tp_inst._defaults.altSeparator ? tp_inst._defaults.altSeparator : tp_inst._defaults.separator, 1362 altTimeSuffix = tp_inst._defaults.altTimeSuffix ? tp_inst._defaults.altTimeSuffix : tp_inst._defaults.timeSuffix,1363 altTimeFormat = tp_inst._defaults.altTimeFormat !== null ? tp_inst._defaults.altTimeFormat : tp_inst._defaults.timeFormat;1364 1365 altFormattedDateTime += $.datepicker.formatTime(altTimeFormat, tp_inst, tp_inst._defaults) + altTimeSuffix;1366 if (!tp_inst._defaults.timeOnly && !tp_inst._defaults.altFieldTimeOnly && date !== null) {1367 if (tp_inst._defaults.altFormat) {1368 altFormattedDateTime = $.datepicker.formatDate(tp_inst._defaults.altFormat, date, formatCfg) + altSeparator + altFormattedDateTime;1369 }1370 else {1371 altFormattedDateTime = tp_inst.formattedDate + altSeparator + altFormattedDateTime;1372 }1373 }1374 $(altField).val( inst.input.val() ? altFormattedDateTime : "");1375 }1376 }1377 else {1378 $.datepicker._base_updateAlternate(inst); 1379 }1380 };1381 /*1382 * Override key up event to sync manual input changes.1383 */1384 $.datepicker._base_doKeyUp = $.datepicker._doKeyUp;1385 $.datepicker._doKeyUp = function (event) {1386 var inst = $.datepicker._getInst(event.target),1387 tp_inst = $.datepicker._get(inst, 'timepicker');1388 if (tp_inst) {1389 if (tp_inst._defaults.timeOnly && (inst.input.val() !== inst.lastVal)) {1390 try {1391 $.datepicker._updateDatepicker(inst);1392 } catch (err) {1393 $.timepicker.log(err);1394 }1395 }1396 }1397 return $.datepicker._base_doKeyUp(event);1398 };1399 /*1400 * override "Today" button to also grab the time.1401 */1402 $.datepicker._base_gotoToday = $.datepicker._gotoToday;1403 $.datepicker._gotoToday = function (id) {1404 var inst = this._getInst($(id)[0]),1405 $dp = inst.dpDiv;1406 this._base_gotoToday(id);1407 var tp_inst = this._get(inst, 'timepicker');1408 selectLocalTimezone(tp_inst);1409 var now = new Date();1410 this._setTime(inst, now);1411 $('.ui-datepicker-today', $dp).click();1412 };1413 /*1414 * Disable & enable the Time in the datetimepicker1415 */1416 $.datepicker._disableTimepickerDatepicker = function (target) {1417 var inst = this._getInst(target);1418 if (!inst) {1419 return;1420 }1421 var tp_inst = this._get(inst, 'timepicker');1422 $(target).datepicker('getDate'); // Init selected[Year|Month|Day]1423 if (tp_inst) {1424 inst.settings.showTimepicker = false;1425 tp_inst._defaults.showTimepicker = false;1426 tp_inst._updateDateTime(inst);1427 }1428 };1429 $.datepicker._enableTimepickerDatepicker = function (target) {1430 var inst = this._getInst(target);1431 if (!inst) {1432 return;1433 }1434 var tp_inst = this._get(inst, 'timepicker');1435 $(target).datepicker('getDate'); // Init selected[Year|Month|Day]1436 if (tp_inst) {1437 inst.settings.showTimepicker = true;1438 tp_inst._defaults.showTimepicker = true;1439 tp_inst._addTimePicker(inst); // Could be disabled on page load1440 tp_inst._updateDateTime(inst);1441 }1442 };1443 /*1444 * Create our own set time function1445 */1446 $.datepicker._setTime = function (inst, date) {1447 var tp_inst = this._get(inst, 'timepicker');1448 if (tp_inst) {1449 var defaults = tp_inst._defaults;1450 // calling _setTime with no date sets time to defaults1451 tp_inst.hour = date ? date.getHours() : defaults.hour;1452 tp_inst.minute = date ? date.getMinutes() : defaults.minute;1453 tp_inst.second = date ? date.getSeconds() : defaults.second;1454 tp_inst.millisec = date ? date.getMilliseconds() : defaults.millisec;1455 tp_inst.microsec = date ? date.getMicroseconds() : defaults.microsec;1456 //check if within min/max times.. 1457 tp_inst._limitMinMaxDateTime(inst, true);1458 tp_inst._onTimeChange();1459 tp_inst._updateDateTime(inst);1460 }1461 };1462 /*1463 * Create new public method to set only time, callable as $().datepicker('setTime', date)1464 */1465 $.datepicker._setTimeDatepicker = function (target, date, withDate) {1466 var inst = this._getInst(target);1467 if (!inst) {1468 return;1469 }1470 var tp_inst = this._get(inst, 'timepicker');1471 if (tp_inst) {1472 this._setDateFromField(inst);1473 var tp_date;1474 if (date) {1475 if (typeof date === "string") {1476 tp_inst._parseTime(date, withDate);1477 tp_date = new Date();1478 tp_date.setHours(tp_inst.hour, tp_inst.minute, tp_inst.second, tp_inst.millisec);1479 tp_date.setMicroseconds(tp_inst.microsec);1480 } else {1481 tp_date = new Date(date.getTime());1482 tp_date.setMicroseconds(date.getMicroseconds());1483 }1484 if (tp_date.toString() === 'Invalid Date') {1485 tp_date = undefined;1486 }1487 this._setTime(inst, tp_date);1488 }1489 }1490 };1491 /*1492 * override setDate() to allow setting time too within Date object1493 */1494 $.datepicker._base_setDateDatepicker = $.datepicker._setDateDatepicker;1495 $.datepicker._setDateDatepicker = function (target, _date) {1496 var inst = this._getInst(target);1497 var date = _date;1498 if (!inst) {1499 return;1500 }1501 if (typeof(_date) === 'string') {1502 date = new Date(_date);1503 if (!date.getTime()) {1504 this._base_setDateDatepicker.apply(this, arguments);1505 date = $(target).datepicker('getDate');1506 }1507 }1508 var tp_inst = this._get(inst, 'timepicker');1509 var tp_date;1510 if (date instanceof Date) {1511 tp_date = new Date(date.getTime());1512 tp_date.setMicroseconds(date.getMicroseconds());1513 } else {1514 tp_date = date;1515 }1516 1517 // This is important if you are using the timezone option, javascript's Date 1518 // object will only return the timezone offset for the current locale, so we 1519 // adjust it accordingly. If not using timezone option this won't matter..1520 // If a timezone is different in tp, keep the timezone as is1521 if (tp_inst && tp_date) {1522 // look out for DST if tz wasn't specified1523 if (!tp_inst.support.timezone && tp_inst._defaults.timezone === null) {1524 tp_inst.timezone = tp_date.getTimezoneOffset() * -1;1525 }1526 date = $.timepicker.timezoneAdjust(date, tp_inst.timezone);1527 tp_date = $.timepicker.timezoneAdjust(tp_date, tp_inst.timezone);1528 }1529 this._updateDatepicker(inst);1530 this._base_setDateDatepicker.apply(this, arguments);1531 this._setTimeDatepicker(target, tp_date, true);1532 };1533 /*1534 * override getDate() to allow getting time too within Date object1535 */1536 $.datepicker._base_getDateDatepicker = $.datepicker._getDateDatepicker;1537 $.datepicker._getDateDatepicker = function (target, noDefault) {1538 var inst = this._getInst(target);1539 if (!inst) {1540 return;1541 }1542 var tp_inst = this._get(inst, 'timepicker');1543 if (tp_inst) {1544 // if it hasn't yet been defined, grab from field1545 if (inst.lastVal === undefined) {1546 this._setDateFromField(inst, noDefault);1547 }1548 var date = this._getDate(inst);1549 if (date && tp_inst._parseTime($(target).val(), tp_inst.timeOnly)) {1550 date.setHours(tp_inst.hour, tp_inst.minute, tp_inst.second, tp_inst.millisec);1551 date.setMicroseconds(tp_inst.microsec);1552 // This is important if you are using the timezone option, javascript's Date 1553 // object will only return the timezone offset for the current locale, so we 1554 // adjust it accordingly. If not using timezone option this won't matter..1555 if (tp_inst.timezone != null) {1556 // look out for DST if tz wasn't specified1557 if (!tp_inst.support.timezone && tp_inst._defaults.timezone === null) {1558 tp_inst.timezone = date.getTimezoneOffset() * -1;1559 }1560 date = $.timepicker.timezoneAdjust(date, tp_inst.timezone);1561 }1562 }1563 return date;1564 }1565 return this._base_getDateDatepicker(target, noDefault);1566 };1567 /*1568 * override parseDate() because UI 1.8.14 throws an error about "Extra characters"1569 * An option in datapicker to ignore extra format characters would be nicer.1570 */1571 $.datepicker._base_parseDate = $.datepicker.parseDate;1572 $.datepicker.parseDate = function (format, value, settings) {1573 var date;1574 try {1575 date = this._base_parseDate(format, value, settings);1576 } catch (err) {1577 // Hack! The error message ends with a colon, a space, and1578 // the "extra" characters. We rely on that instead of1579 // attempting to perfectly reproduce the parsing algorithm.1580 if (err.indexOf(":") >= 0) {1581 date = this._base_parseDate(format, value.substring(0, value.length - (err.length - err.indexOf(':') - 2)), settings);1582 $.timepicker.log("Error parsing the date string: " + err + "\ndate string = " + value + "\ndate format = " + format);1583 } else {1584 throw err;1585 }1586 }1587 return date;1588 };1589 /*1590 * override formatDate to set date with time to the input1591 */1592 $.datepicker._base_formatDate = $.datepicker._formatDate;1593 $.datepicker._formatDate = function (inst, day, month, year) {1594 var tp_inst = this._get(inst, 'timepicker');1595 if (tp_inst) {1596 tp_inst._updateDateTime(inst);1597 return tp_inst.$input.val();1598 }1599 return this._base_formatDate(inst);1600 };1601 /*1602 * override options setter to add time to maxDate(Time) and minDate(Time). MaxDate1603 */1604 $.datepicker._base_optionDatepicker = $.datepicker._optionDatepicker;1605 $.datepicker._optionDatepicker = function (target, name, value) {1606 var inst = this._getInst(target),1607 name_clone;1608 if (!inst) {1609 return null;1610 }1611 var tp_inst = this._get(inst, 'timepicker');1612 if (tp_inst) {1613 var min = null,1614 max = null,1615 onselect = null,1616 overrides = tp_inst._defaults.evnts,1617 fns = {},1618 prop;1619 if (typeof name === 'string') { // if min/max was set with the string1620 if (name === 'minDate' || name === 'minDateTime') {1621 min = value;1622 } else if (name === 'maxDate' || name === 'maxDateTime') {1623 max = value;1624 } else if (name === 'onSelect') {1625 onselect = value;1626 } else if (overrides.hasOwnProperty(name)) {1627 if (typeof (value) === 'undefined') {1628 return overrides[name];1629 }1630 fns[name] = value;1631 name_clone = {}; //empty results in exiting function after overrides updated1632 }1633 } else if (typeof name === 'object') { //if min/max was set with the JSON1634 if (name.minDate) {1635 min = name.minDate;1636 } else if (name.minDateTime) {1637 min = name.minDateTime;1638 } else if (name.maxDate) {1639 max = name.maxDate;1640 } else if (name.maxDateTime) {1641 max = name.maxDateTime;1642 }1643 for (prop in overrides) {1644 if (overrides.hasOwnProperty(prop) && name[prop]) {1645 fns[prop] = name[prop];1646 }1647 }1648 }1649 for (prop in fns) {1650 if (fns.hasOwnProperty(prop)) {1651 overrides[prop] = fns[prop];1652 if (!name_clone) { name_clone = $.extend({}, name); }1653 delete name_clone[prop];1654 }1655 }1656 if (name_clone && isEmptyObject(name_clone)) { return; }1657 if (min) { //if min was set1658 if (min === 0) {1659 min = new Date();1660 } else {1661 min = new Date(min);1662 }1663 tp_inst._defaults.minDate = min;1664 tp_inst._defaults.minDateTime = min;1665 } else if (max) { //if max was set1666 if (max === 0) {1667 max = new Date();1668 } else {1669