: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
obj.children('select').remove();
$(sel).appendTo(obj).change(function (e) {
tp_inst._onSelectHandler();
options: function (tp_inst, obj, unit, opts, val) {
$t = obj.children('select');
if (typeof(opts) === 'string') {
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'));
value: function (tp_inst, obj, unit, val) {
var $t = obj.children('select');
* shorthand just to use timepicker.
timepicker: function (o) {
var tmp_args = Array.prototype.slice.call(arguments);
if (typeof o === 'object') {
tmp_args[0] = $.extend(o, {
return $(this).each(function () {
$.fn.datetimepicker.apply($(this), tmp_args);
* extend timepicker to datepicker
datetimepicker: function (o) {
var tmp_args = arguments;
if (typeof(o) === 'string') {
return $.fn.datepicker.apply($(this[0]), tmp_args);
return this.each(function () {
$t.datepicker.apply($t, tmp_args);
return this.each(function () {
$t.datepicker($.timepicker._newInst($t, o)._defaults);
* Public Utility to parse date and time
$.datepicker.parseDateTime = function (dateFormat, timeFormat, dateTimeString, dateSettings, timeSettings) {
var parseRes = parseDateTimeInternal(dateFormat, timeFormat, dateTimeString, dateSettings, timeSettings);
var t = parseRes.timeObj;
parseRes.date.setHours(t.hour, t.minute, t.second, t.millisec);
parseRes.date.setMicroseconds(t.microsec);
* Public utility to parse time
$.datepicker.parseTime = function (timeFormat, timeString, options) {
var o = extendRemove(extendRemove({}, $.timepicker._defaults), options || {}),
iso8601 = (timeFormat.replace(/\'.*?\'/g, '').indexOf('Z') !== -1);
// Strict parse requires the timeString to match the timeFormat exactly
var strictParse = function (f, s, o) {
// pattern for standard and localized AM/PM markers
var getPatternAmpm = function (amNames, pmNames) {
$.merge(markers, amNames);
$.merge(markers, pmNames);
markers = $.map(markers, function (val) {
return val.replace(/[.*+?|()\[\]{}\\]/g, '\\$&');
return '(' + markers.join('|') + ')?';
// figure out position of time elements.. cause js cant do named captures
var getFormatPositions = function (timeFormat) {
var finds = timeFormat.toLowerCase().match(/(h{1,2}|m{1,2}|s{1,2}|l{1}|c{1}|t{1,2}|z|'.*?')/g),
for (var i = 0; i < finds.length; i++) {
if (orders[finds[i].toString().charAt(0)] === -1) {
orders[finds[i].toString().charAt(0)] = i + 1;
var regstr = '^' + f.toString()
.replace(/([hH]{1,2}|mm?|ss?|[tT]{1,2}|[zZ]|[lc]|'.*?')/g, function (match) {
switch (match.charAt(0).toLowerCase()) {
return ml === 1 ? '(\\d?\\d)' : '(\\d{' + ml + '})';
return ml === 1 ? '(\\d?\\d)' : '(\\d{' + ml + '})';
return ml === 1 ? '(\\d?\\d)' : '(\\d{' + ml + '})';
return '(z|[-+]\\d\\d:?\\d\\d|\\S+)?';
return getPatternAmpm(o.amNames, o.pmNames);
default: // literal escaped in quotes
return '(' + match.replace(/\'/g, "").replace(/(\.|\$|\^|\\|\/|\(|\)|\[|\]|\?|\+|\*)/g, function (m) { return "\\" + m; }) + ')?';
.replace(/\s/g, '\\s?') +
order = getFormatPositions(f),
treg = s.match(new RegExp(regstr, 'i'));
if (treg[order.t] === undefined || treg[order.t].length === 0) {
ampm = $.inArray(treg[order.t].toUpperCase(), o.amNames) !== -1 ? 'AM' : 'PM';
resTime.ampm = o[ampm === 'AM' ? 'amNames' : 'pmNames'][0];
if (ampm === 'AM' && treg[order.h] === '12') {
resTime.hour = 0; // 12am = 0 hour
if (ampm === 'PM' && treg[order.h] !== '12') {
resTime.hour = parseInt(treg[order.h], 10) + 12; // 12pm = 12 hour, any other pm = hour + 12
resTime.hour = Number(treg[order.h]);
resTime.minute = Number(treg[order.m]);
resTime.second = Number(treg[order.s]);
resTime.millisec = Number(treg[order.l]);
resTime.microsec = Number(treg[order.c]);
if (order.z !== -1 && treg[order.z] !== undefined) {
resTime.timezone = $.timepicker.timezoneOffsetNumber(treg[order.z]);
// First try JS Date, if that fails, use strictParse
var looseParse = function (f, s, o) {
var d = new Date('2012-01-01 ' + s);
if (isNaN(d.getTime())) {
d = new Date('2012-01-01T' + s);
if (isNaN(d.getTime())) {
d = new Date('01/01/2012 ' + s);
if (isNaN(d.getTime())) {
throw "Unable to parse time with native Date: " + s;
millisec: d.getMilliseconds(),
microsec: d.getMicroseconds(),
timezone: d.getTimezoneOffset() * -1
return strictParse(f, s, o);
$.timepicker.log("Unable to parse \ntimeString: " + s + "\ntimeFormat: " + f);
if (typeof o.parse === "function") {
return o.parse(timeFormat, timeString, o);
if (o.parse === 'loose') {
return looseParse(timeFormat, timeString, o);
return strictParse(timeFormat, timeString, o);
* Public utility to format the time
* @param {string} format format of the time
* @param {Object} time Object not a Date for timezones
* @param {Object} [options] essentially the regional[].. amNames, pmNames, ampm
* @returns {string} the formatted time
$.datepicker.formatTime = function (format, time, options) {
options = $.extend({}, $.timepicker._defaults, options);
ampmName = options.amNames[0],
hour = parseInt(time.hour, 10);
ampmName = options.pmNames[0];
tmptime = tmptime.replace(/(?:HH?|hh?|mm?|ss?|[tT]{1,2}|[zZ]|[lc]|'.*?')/g, function (match) {
return ('0' + hour).slice(-2);
return ('0' + convert24to12(hour)).slice(-2);
return convert24to12(hour);
return ('0' + time.minute).slice(-2);
return ('0' + time.second).slice(-2);
return ('00' + time.millisec).slice(-3);
return ('00' + time.microsec).slice(-3);
return $.timepicker.timezoneOffsetString(time.timezone === null ? options.timezone : time.timezone, false);
return $.timepicker.timezoneOffsetString(time.timezone === null ? options.timezone : time.timezone, true);
return ampmName.charAt(0).toUpperCase();
return ampmName.toUpperCase();
return ampmName.charAt(0).toLowerCase();
return ampmName.toLowerCase();
return match.replace(/'/g, "");
* the bad hack :/ override datepicker so it doesn't close on select
// inspired: http://stackoverflow.com/questions/1252512/jquery-datepicker-prevent-closing-picker-when-clicking-a-date/1762378#1762378
$.datepicker._base_selectDate = $.datepicker._selectDate;
$.datepicker._selectDate = function (id, dateStr) {
var inst = this._getInst($(id)[0]),
tp_inst = this._get(inst, 'timepicker');
tp_inst._limitMinMaxDateTime(inst, true);
inst.inline = inst.stay_open = true;
//This way the onSelect handler called from calendarpicker get the full dateTime
this._base_selectDate(id, dateStr);
inst.inline = inst.stay_open = false;
this._notifyChange(inst);
this._updateDatepicker(inst);
this._base_selectDate(id, dateStr);
* second bad hack :/ override datepicker so it triggers an event when changing the input field
* and does not redraw the datepicker on every selectDate event
$.datepicker._base_updateDatepicker = $.datepicker._updateDatepicker;
$.datepicker._updateDatepicker = function (inst) {
// don't popup the datepicker if there is another instance already opened
var input = inst.input[0];
if ($.datepicker._curInst && $.datepicker._curInst !== inst && $.datepicker._datepickerShowing && $.datepicker._lastInput !== input) {
if (typeof(inst.stay_open) !== 'boolean' || inst.stay_open === false) {
this._base_updateDatepicker(inst);
// Reload the time control when changing something in the input text field.
var tp_inst = this._get(inst, 'timepicker');
tp_inst._addTimePicker(inst);
* third bad hack :/ override datepicker so it allows spaces and colon in the input field
$.datepicker._base_doKeyPress = $.datepicker._doKeyPress;
$.datepicker._doKeyPress = function (event) {
var inst = $.datepicker._getInst(event.target),
tp_inst = $.datepicker._get(inst, 'timepicker');
if ($.datepicker._get(inst, 'constrainInput')) {
var ampm = tp_inst.support.ampm,
tz = tp_inst._defaults.showTimezone !== null ? tp_inst._defaults.showTimezone : tp_inst.support.timezone,
dateChars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat')),
datetimeChars = tp_inst._defaults.timeFormat.toString()
.replace(/TT/g, ampm ? 'APM' : '')
.replace(/Tt/g, ampm ? 'AaPpMm' : '')
.replace(/tT/g, ampm ? 'AaPpMm' : '')
.replace(/T/g, ampm ? 'AP' : '')
.replace(/tt/g, ampm ? 'apm' : '')
.replace(/t/g, ampm ? 'ap' : '') +
" " + tp_inst._defaults.separator +
tp_inst._defaults.timeSuffix +
(tz ? tp_inst._defaults.timezoneList.join('') : '') +
(tp_inst._defaults.amNames.join('')) + (tp_inst._defaults.pmNames.join('')) +
chr = String.fromCharCode(event.charCode === undefined ? event.keyCode : event.charCode);
return event.ctrlKey || (chr < ' ' || !dateChars || datetimeChars.indexOf(chr) > -1);
return $.datepicker._base_doKeyPress(event);
* Fourth bad hack :/ override _updateAlternate function used in inline mode to init altField
* Update any alternate field to synchronise with the main field.
$.datepicker._base_updateAlternate = $.datepicker._updateAlternate;
$.datepicker._updateAlternate = function (inst) {
var tp_inst = this._get(inst, 'timepicker');
var altField = tp_inst._defaults.altField;
if (altField) { // update alternate field too
var altFormat = tp_inst._defaults.altFormat || tp_inst._defaults.dateFormat,
date = this._getDate(inst),
formatCfg = $.datepicker._getFormatConfig(inst),
altFormattedDateTime = '',
altSeparator = tp_inst._defaults.altSeparator ? tp_inst._defaults.altSeparator : tp_inst._defaults.separator,
altTimeSuffix = tp_inst._defaults.altTimeSuffix ? tp_inst._defaults.altTimeSuffix : tp_inst._defaults.timeSuffix,
altTimeFormat = tp_inst._defaults.altTimeFormat !== null ? tp_inst._defaults.altTimeFormat : tp_inst._defaults.timeFormat;
altFormattedDateTime += $.datepicker.formatTime(altTimeFormat, tp_inst, tp_inst._defaults) + altTimeSuffix;
if (!tp_inst._defaults.timeOnly && !tp_inst._defaults.altFieldTimeOnly && date !== null) {
if (tp_inst._defaults.altFormat) {
altFormattedDateTime = $.datepicker.formatDate(tp_inst._defaults.altFormat, date, formatCfg) + altSeparator + altFormattedDateTime;
altFormattedDateTime = tp_inst.formattedDate + altSeparator + altFormattedDateTime;
$(altField).val(altFormattedDateTime);
$.datepicker._base_updateAlternate(inst);
* Override key up event to sync manual input changes.
$.datepicker._base_doKeyUp = $.datepicker._doKeyUp;
$.datepicker._doKeyUp = function (event) {
var inst = $.datepicker._getInst(event.target),
tp_inst = $.datepicker._get(inst, 'timepicker');
if (tp_inst._defaults.timeOnly && (inst.input.val() !== inst.lastVal)) {
$.datepicker._updateDatepicker(inst);
return $.datepicker._base_doKeyUp(event);
* override "Today" button to also grab the time.
$.datepicker._base_gotoToday = $.datepicker._gotoToday;
$.datepicker._gotoToday = function (id) {
var inst = this._getInst($(id)[0]),
this._base_gotoToday(id);
var tp_inst = this._get(inst, 'timepicker');
selectLocalTimezone(tp_inst);
this._setTime(inst, now);
$('.ui-datepicker-today', $dp).click();
* Disable & enable the Time in the datetimepicker
$.datepicker._disableTimepickerDatepicker = function (target) {
var inst = this._getInst(target);
var tp_inst = this._get(inst, 'timepicker');
$(target).datepicker('getDate'); // Init selected[Year|Month|Day]
inst.settings.showTimepicker = false;