terom@22: /*
terom@22: * jQuery timepicker addon
terom@22: * By: Trent Richardson [http://trentrichardson.com]
terom@22: * Version 0.9.1
terom@22: * Last Modified: 12/2/2010
terom@22: *
terom@22: * Copyright 2010 Trent Richardson
terom@22: * Dual licensed under the MIT and GPL licenses.
terom@22: * http://trentrichardson.com/Impromptu/GPL-LICENSE.txt
terom@22: * http://trentrichardson.com/Impromptu/MIT-LICENSE.txt
terom@22: *
terom@22: * HERES THE CSS:
terom@22: * .ui-timepicker-div .ui-widget-header{ margin-bottom: 8px; }
terom@22: * .ui-timepicker-div dl{ text-align: left; }
terom@22: * .ui-timepicker-div dl dt{ height: 25px; }
terom@22: * .ui-timepicker-div dl dd{ margin: -25px 0 10px 65px; }
terom@22: * .ui-timepicker-div td { font-size: 90%; }
terom@22: */
terom@22:
terom@22: (function($) {
terom@22:
terom@22: $.extend($.ui, { timepicker: { version: "0.9.1" } });
terom@22:
terom@22: /* Time picker manager.
terom@22: Use the singleton instance of this class, $.timepicker, to interact with the time picker.
terom@22: Settings for (groups of) time pickers are maintained in an instance object,
terom@22: allowing multiple different settings on the same page. */
terom@22:
terom@22: function Timepicker() {
terom@22: this.regional = []; // Available regional settings, indexed by language code
terom@22: this.regional[''] = { // Default regional settings
terom@22: currentText: 'Now',
terom@22: closeText: 'Done',
terom@22: ampm: false,
terom@22: timeFormat: 'hh:mm tt',
terom@22: timeOnlyTitle: 'Choose Time',
terom@22: timeText: 'Time',
terom@22: hourText: 'Hour',
terom@22: minuteText: 'Minute',
terom@22: secondText: 'Second'
terom@22: };
terom@22: this._defaults = { // Global defaults for all the datetime picker instances
terom@22: showButtonPanel: true,
terom@22: timeOnly: false,
terom@22: showHour: true,
terom@22: showMinute: true,
terom@22: showSecond: false,
terom@22: showTime: true,
terom@22: stepHour: 0.05,
terom@22: stepMinute: 0.05,
terom@22: stepSecond: 0.05,
terom@22: hour: 0,
terom@22: minute: 0,
terom@22: second: 0,
terom@22: hourMin: 0,
terom@22: minuteMin: 0,
terom@22: secondMin: 0,
terom@22: hourMax: 23,
terom@22: minuteMax: 59,
terom@22: secondMax: 59,
terom@22: hourGrid: 0,
terom@22: minuteGrid: 0,
terom@22: secondGrid: 0,
terom@22: alwaysSetTime: true
terom@22: };
terom@22: $.extend(this._defaults, this.regional['']);
terom@22: }
terom@22:
terom@22: $.extend(Timepicker.prototype, {
terom@22: $input: null,
terom@22: $altInput: null,
terom@22: $timeObj: null,
terom@22: inst: null,
terom@22: hour_slider: null,
terom@22: minute_slider: null,
terom@22: second_slider: null,
terom@22: hour: 0,
terom@22: minute: 0,
terom@22: second: 0,
terom@22: ampm: '',
terom@22: formattedDate: '',
terom@22: formattedTime: '',
terom@22: formattedDateTime: '',
terom@22:
terom@22: /* Override the default settings for all instances of the time picker.
terom@22: @param settings object - the new settings to use as defaults (anonymous object)
terom@22: @return the manager object */
terom@22: setDefaults: function(settings) {
terom@22: extendRemove(this._defaults, settings || {});
terom@22: return this;
terom@22: },
terom@22:
terom@22: //########################################################################
terom@22: // Create a new Timepicker instance
terom@22: //########################################################################
terom@22: _newInst: function($input, o) {
terom@22: var tp_inst = new Timepicker(),
terom@22: inlineSettings = {};
terom@22:
terom@22: for (var attrName in this._defaults) {
terom@22: var attrValue = $input.attr('time:' + attrName);
terom@22: if (attrValue) {
terom@22: try {
terom@22: inlineSettings[attrName] = eval(attrValue);
terom@22: } catch (err) {
terom@22: inlineSettings[attrName] = attrValue;
terom@22: }
terom@22: }
terom@22: }
terom@22: tp_inst._defaults = $.extend({}, this._defaults, inlineSettings, o, {
terom@22: beforeShow: function(input, dp_inst) {
terom@22: tp_inst.hour = tp_inst._defaults.hour;
terom@22: tp_inst.minute = tp_inst._defaults.minute;
terom@22: tp_inst.second = tp_inst._defaults.second;
terom@22: tp_inst.ampm = '';
terom@22: tp_inst.$input = $(input);
terom@22: if (o.altField)
terom@22: tp_inst.$altInput = $($.datepicker._get(dp_inst, 'altField'))
terom@22: .css({ cursor: 'pointer' })
terom@22: .focus(function(){
terom@22: $input.trigger("focus");
terom@22: });
terom@22: tp_inst.inst = dp_inst;
terom@22: tp_inst._addTimePicker();
terom@22: if ($.isFunction(o.beforeShow))
terom@22: o.beforeShow(input, dp_inst);
terom@22: },
terom@22: onChangeMonthYear: function(year, month, dp_inst) {
terom@22: // Update the time as well : this prevents the time from disappearing from the $input field.
terom@22: tp_inst._updateDateTime(dp_inst);
terom@22: if ($.isFunction(o.onChangeMonthYear))
terom@22: o.onChangeMonthYear(year, month, dp_inst);
terom@22: },
terom@22: onClose: function(dateText, dp_inst) {
terom@22: if (tp_inst.timeDefined === true && $input.val() != '')
terom@22: tp_inst._updateDateTime(dp_inst);
terom@22: if ($.isFunction(o.onClose))
terom@22: o.onClose(dateText, dp_inst);
terom@22: },
terom@22: timepicker: tp_inst // add timepicker as a property of datepicker: $.datepicker._get(dp_inst, 'timepicker');
terom@22: });
terom@22: return tp_inst;
terom@22: },
terom@22:
terom@22: //########################################################################
terom@22: // add our sliders to the calendar
terom@22: //########################################################################
terom@22: _addTimePicker: function() {
terom@22: var currDT = (this.$altInput) ?
terom@22: this.$input.val() + ' ' + this.$altInput.val() :
terom@22: this.$input.val(),
terom@22: parsedDT = this._parseTime(currDT);
terom@22:
terom@22: this.timeDefined = (parsedDT) ? true : false;
terom@22: this._injectTimePicker();
terom@22: },
terom@22:
terom@22: //########################################################################
terom@22: // parse the time string from input value or _setTime
terom@22: //########################################################################
terom@22: _parseTime: function(timeString, withDate) {
terom@22: var regstr = this._defaults.timeFormat.toString()
terom@22: .replace(/h{1,2}/ig, '(\\d?\\d)')
terom@22: .replace(/m{1,2}/ig, '(\\d?\\d)')
terom@22: .replace(/s{1,2}/ig, '(\\d?\\d)')
terom@22: .replace(/t{1,2}/ig, '(am|pm|a|p)?')
terom@22: .replace(/\s/g, '\\s?') + '$',
terom@22:
terom@22: treg = timeString.match(new RegExp(regstr, 'i')),
terom@22: order = this._getFormatPositions();
terom@22:
terom@22: if (withDate || !this._defaults.timeOnly) {
terom@22: // the time should come after x number of characters and a space.
terom@22: // x = at least the length of text specified by the date format
terom@22: var dp_dateFormat = $.datepicker._get(this.inst, 'dateFormat');
terom@22: regstr = '.{' + dp_dateFormat.length + ',}\\s+' + regstr;
terom@22: }
terom@22:
terom@22: if (treg) {
terom@22: if (order.t !== -1)
terom@22: this.ampm = ((treg[order.t] === undefined || treg[order.t].length === 0) ?
terom@22: '' :
terom@22: (treg[order.t].charAt(0).toUpperCase() == 'A') ? 'AM' : 'PM').toUpperCase();
terom@22:
terom@22: if (order.h !== -1) {
terom@22: if (this.ampm == 'AM' && treg[order.h] == '12')
terom@22: this.hour = 0; // 12am = 0 hour
terom@22: else if (this.ampm == 'PM' && treg[order.h] != '12')
terom@22: this.hour = (parseFloat(treg[order.h]) + 12).toFixed(0); // 12pm = 12 hour, any other pm = hour + 12
terom@22: else this.hour = treg[order.h];
terom@22: }
terom@22:
terom@22: if (order.m !== -1) this.minute = treg[order.m];
terom@22: if (order.s !== -1) this.second = treg[order.s];
terom@22: }
terom@22: },
terom@22:
terom@22: //########################################################################
terom@22: // figure out position of time elements.. cause js cant do named captures
terom@22: //########################################################################
terom@22: _getFormatPositions: function() {
terom@22: var finds = this._defaults.timeFormat.toLowerCase().match(/(h{1,2}|m{1,2}|s{1,2}|t{1,2})/g),
terom@22: orders = { h: -1, m: -1, s: -1, t: -1 };
terom@22:
terom@22: if (finds)
terom@22: for (var i = 0; i < finds.length; i++)
terom@22: if (orders[finds[i].toString().charAt(0)] == -1)
terom@22: orders[finds[i].toString().charAt(0)] = i + 1;
terom@22:
terom@22: return orders;
terom@22: },
terom@22:
terom@22: //########################################################################
terom@22: // generate and inject html for timepicker into ui datepicker
terom@22: //########################################################################
terom@22: _injectTimePicker: function() {
terom@22: var $dp = this.inst.dpDiv,
terom@22: o = this._defaults,
terom@22: tp_inst = this,
terom@22: // Added by Peter Medeiros:
terom@22: // - Figure out what the hour/minute/second max should be based on the step values.
terom@22: // - Example: if stepMinute is 15, then minMax is 45.
terom@22: hourMax = (o.hourMax - (o.hourMax % o.stepHour)).toFixed(0),
terom@22: minMax = (o.minuteMax - (o.minuteMax % o.stepMinute)).toFixed(0),
terom@22: secMax = (o.secondMax - (o.secondMax % o.stepSecond)).toFixed(0),
terom@22: dp_id = this.inst.id.toString().replace(/([^A-Za-z0-9_])/g, '');
terom@22:
terom@22: // Prevent displaying twice
terom@22: if ($dp.find("div#ui-timepicker-div-"+ dp_id).length === 0) {
terom@22: var noDisplay = ' style="display:none;"',
terom@22: html = '
' +
terom@22: '- ' + o.timeText + '
' +
terom@22: '' +
terom@22: '- ' + o.hourText + '
',
terom@22: hourGridSize = 0,
terom@22: minuteGridSize = 0,
terom@22: secondGridSize = 0,
terom@22: size;
terom@22:
terom@22: if (o.showHour && o.hourGrid > 0) {
terom@22: html += '- ' +
terom@22: '' +
terom@22: '
';
terom@22:
terom@22: for (var h = o.hourMin; h < hourMax; h += o.hourGrid) {
terom@22: hourGridSize++;
terom@22: var tmph = (o.ampm && h > 12) ? h-12 : h;
terom@22: if (tmph < 10) tmph = '0' + tmph;
terom@22: if (o.ampm) {
terom@22: if (h == 0) tmph = 12 +'a';
terom@22: else if (h < 12) tmph += 'a';
terom@22: else tmph += 'p';
terom@22: }
terom@22: html += '' + tmph + ' | ';
terom@22: }
terom@22:
terom@22: html += '
' +
terom@22: ' ';
terom@22: } else html += '';
terom@22:
terom@22: html += '- ' + o.minuteText + '
';
terom@22:
terom@22: if (o.showMinute && o.minuteGrid > 0) {
terom@22: html += '- ' +
terom@22: '' +
terom@22: '
';
terom@22:
terom@22: for (var m = o.minuteMin; m < minMax; m += o.minuteGrid) {
terom@22: minuteGridSize++;
terom@22: html += '' + ((m < 10) ? '0' : '') + m + ' | ';
terom@22: }
terom@22:
terom@22: html += '
' +
terom@22: ' ';
terom@22: } else html += '';
terom@22:
terom@22: html += '- ' + o.secondText + '
';
terom@22:
terom@22: if (o.showSecond && o.secondGrid > 0) {
terom@22: html += '- ' +
terom@22: '' +
terom@22: '
';
terom@22:
terom@22: for (var s = o.secondMin; s < secMax; s += o.secondGrid) {
terom@22: secondGridSize++;
terom@22: html += '' + ((s < 10) ? '0' : '') + s + ' | ';
terom@22: }
terom@22:
terom@22: html += '
' +
terom@22: ' ';
terom@22: } else html += '';
terom@22:
terom@22: html += '
';
terom@22: $tp = $(html);
terom@22:
terom@22: // if we only want time picker...
terom@22: if (o.timeOnly === true) {
terom@22: $tp.prepend(
terom@22: '');
terom@22: $dp.find('.ui-datepicker-header, .ui-datepicker-calendar').hide();
terom@22: }
terom@22:
terom@22: this.hour_slider = $tp.find('#ui_tpicker_hour_'+ dp_id).slider({
terom@22: orientation: "horizontal",
terom@22: value: this.hour,
terom@22: min: o.hourMin,
terom@22: max: hourMax,
terom@22: step: o.stepHour,
terom@22: slide: function(event, ui) {
terom@22: tp_inst.hour_slider.slider( "option", "value", ui.value);
terom@22: tp_inst._onTimeChange();
terom@22: }
terom@22: });
terom@22:
terom@22: // Updated by Peter Medeiros:
terom@22: // - Pass in Event and UI instance into slide function
terom@22: this.minute_slider = $tp.find('#ui_tpicker_minute_'+ dp_id).slider({
terom@22: orientation: "horizontal",
terom@22: value: this.minute,
terom@22: min: o.minuteMin,
terom@22: max: minMax,
terom@22: step: o.stepMinute,
terom@22: slide: function(event, ui) {
terom@22: // update the global minute slider instance value with the current slider value
terom@22: tp_inst.minute_slider.slider( "option", "value", ui.value);
terom@22: tp_inst._onTimeChange();
terom@22: }
terom@22: });
terom@22:
terom@22: this.second_slider = $tp.find('#ui_tpicker_second_'+ dp_id).slider({
terom@22: orientation: "horizontal",
terom@22: value: this.second,
terom@22: min: o.secondMin,
terom@22: max: secMax,
terom@22: step: o.stepSecond,
terom@22: slide: function(event, ui) {
terom@22: tp_inst.second_slider.slider( "option", "value", ui.value);
terom@22: tp_inst._onTimeChange();
terom@22: }
terom@22: });
terom@22:
terom@22: // Add grid functionality
terom@22: if (o.showHour && o.hourGrid > 0) {
terom@22: size = 100 * hourGridSize * o.hourGrid / (hourMax - o.hourMin);
terom@22:
terom@22: $tp.find(".ui_tpicker_hour table").css({
terom@22: width: size + "%",
terom@22: marginLeft: (size / (-2 * hourGridSize)) + "%",
terom@22: borderCollapse: 'collapse'
terom@22: }).find("td").each( function(index) {
terom@22: $(this).click(function() {
terom@22: var h = $(this).html();
terom@22: if(o.ampm) {
terom@22: var ap = h.substring(2).toLowerCase(),
terom@22: aph = parseInt(h.substring(0,2));
terom@22: if (ap == 'a') {
terom@22: if (aph == 12) h = 0;
terom@22: else h = aph;
terom@22: } else if (aph == 12) h = 12;
terom@22: else h = aph + 12;
terom@22: }
terom@22: tp_inst.hour_slider.slider("option", "value", h);
terom@22: tp_inst._onTimeChange();
terom@22: }).css({
terom@22: cursor: 'pointer',
terom@22: width: (100 / hourGridSize) + '%',
terom@22: textAlign: 'center',
terom@22: overflow: 'hidden'
terom@22: });
terom@22: });
terom@22: }
terom@22:
terom@22: if (o.showMinute && o.minuteGrid > 0) {
terom@22: size = 100 * minuteGridSize * o.minuteGrid / (minMax - o.minuteMin);
terom@22: $tp.find(".ui_tpicker_minute table").css({
terom@22: width: size + "%",
terom@22: marginLeft: (size / (-2 * minuteGridSize)) + "%",
terom@22: borderCollapse: 'collapse'
terom@22: }).find("td").each(function(index) {
terom@22: $(this).click(function() {
terom@22: tp_inst.minute_slider.slider("option", "value", $(this).html());
terom@22: tp_inst._onTimeChange();
terom@22: }).css({
terom@22: cursor: 'pointer',
terom@22: width: (100 / minuteGridSize) + '%',
terom@22: textAlign: 'center',
terom@22: overflow: 'hidden'
terom@22: });
terom@22: });
terom@22: }
terom@22:
terom@22: if (o.showSecond && o.secondGrid > 0) {
terom@22: $tp.find(".ui_tpicker_second table").css({
terom@22: width: size + "%",
terom@22: marginLeft: (size / (-2 * secondGridSize)) + "%",
terom@22: borderCollapse: 'collapse'
terom@22: }).find("td").each(function(index) {
terom@22: $(this).click(function() {
terom@22: tp_inst.second_slider.slider("option", "value", $(this).html());
terom@22: tp_inst._onTimeChange();
terom@22: }).css({
terom@22: cursor: 'pointer',
terom@22: width: (100 / secondGridSize) + '%',
terom@22: textAlign: 'center',
terom@22: overflow: 'hidden'
terom@22: });
terom@22: });
terom@22: }
terom@22:
terom@22: var $buttonPanel = $dp.find('.ui-datepicker-buttonpane');
terom@22: if ($buttonPanel.length) $buttonPanel.before($tp);
terom@22: else $dp.append($tp);
terom@22:
terom@22: this.$timeObj = $('#ui_tpicker_time_'+ dp_id);
terom@22:
terom@22: if (this.inst !== null) {
terom@22: var timeDefined = this.timeDefined;
terom@22: this._onTimeChange();
terom@22: this.timeDefined = timeDefined;
terom@22: }
terom@22: }
terom@22: },
terom@22:
terom@22: //########################################################################
terom@22: // when a slider moves...
terom@22: // on time change is also called when the time is updated in the text field
terom@22: //########################################################################
terom@22: _onTimeChange: function(force) {
terom@22: var hour = (this.hour_slider) ? this.hour_slider.slider('value') : this.hour,
terom@22: minute = (this.minute_slider) ? this.minute_slider.slider('value') : this.minute,
terom@22: second = (this.second_slider) ? this.second_slider.slider('value') : this.second,
terom@22: ampm = (hour < 11.5) ? 'AM' : 'PM',
terom@22: hasChanged = false;
terom@22: hour = (hour >= 11.5 && hour < 12) ? 12 : hour;
terom@22:
terom@22: // If the update was done in the input field, this field should not be updated.
terom@22: // If the update was done using the sliders, update the input field.
terom@22: if (force || this.hour != hour || this.minute != minute || this.second != second || (this.ampm.length > 0 && this.ampm != ampm))
terom@22: hasChanged = true;
terom@22:
terom@22: this.hour = parseFloat(hour).toFixed(0);
terom@22: this.minute = parseFloat(minute).toFixed(0);
terom@22: this.second = parseFloat(second).toFixed(0);
terom@22: this.ampm = ampm;
terom@22:
terom@22: this._formatTime();
terom@22: if (this.$timeObj) this.$timeObj.text(this.formattedTime);
terom@22:
terom@22: if (hasChanged) {
terom@22: this._updateDateTime();
terom@22: this.timeDefined = true;
terom@22: }
terom@22: },
terom@22:
terom@22: //########################################################################
terom@22: // format the time all pretty...
terom@22: //########################################################################
terom@22: _formatTime: function(time, format, ampm) {
terom@22: if (ampm == undefined) ampm = this._defaults.ampm;
terom@22: time = time || { hour: this.hour, minute: this.minute, second: this.second, ampm: this.ampm };
terom@22: var tmptime = format || this._defaults.timeFormat.toString();
terom@22:
terom@22: if (ampm) {
terom@22: var hour12 = ((time.ampm == 'AM') ? (time.hour) : (time.hour % 12));
terom@22: hour12 = (Number(hour12) === 0) ? 12 : hour12;
terom@22: tmptime = tmptime.toString()
terom@22: .replace(/hh/g, ((hour12 < 10) ? '0' : '') + hour12)
terom@22: .replace(/h/g, hour12)
terom@22: .replace(/mm/g, ((time.minute < 10) ? '0' : '') + time.minute)
terom@22: .replace(/m/g, time.minute)
terom@22: .replace(/ss/g, ((time.second < 10) ? '0' : '') + time.second)
terom@22: .replace(/s/g, time.second)
terom@22: .replace(/TT/g, time.ampm.toUpperCase())
terom@22: .replace(/tt/g, time.ampm.toLowerCase())
terom@22: .replace(/T/g, time.ampm.charAt(0).toUpperCase())
terom@22: .replace(/t/g, time.ampm.charAt(0).toLowerCase());
terom@22: } else {
terom@22: tmptime = tmptime.toString()
terom@22: .replace(/hh/g, ((time.hour < 10) ? '0' : '') + time.hour)
terom@22: .replace(/h/g, time.hour)
terom@22: .replace(/mm/g, ((time.minute < 10) ? '0' : '') + time.minute)
terom@22: .replace(/m/g, time.minute)
terom@22: .replace(/ss/g, ((time.second < 10) ? '0' : '') + time.second)
terom@22: .replace(/s/g, time.second);
terom@22: tmptime = $.trim(tmptime.replace(/t/gi, ''));
terom@22: }
terom@22:
terom@22: if (arguments.length) return tmptime;
terom@22: else this.formattedTime = tmptime;
terom@22: },
terom@22:
terom@22: //########################################################################
terom@22: // update our input with the new date time..
terom@22: //########################################################################
terom@22: _updateDateTime: function() {
terom@22: var dp_inst = this.inst,
terom@22: dt = new Date(dp_inst.selectedYear, dp_inst.selectedMonth, dp_inst.selectedDay),
terom@22: dateFmt = $.datepicker._get(dp_inst, 'dateFormat'),
terom@22: formatCfg = $.datepicker._getFormatConfig(dp_inst),
terom@22: timeAvailable = dt !== null && this.timeDefined;
terom@22: this.formattedDate = $.datepicker.formatDate(dateFmt, (dt === null ? new Date() : dt), formatCfg);
terom@22: var formattedDateTime = this.formattedDate;
terom@22:
terom@22: if (dp_inst.lastVal !== undefined && (dp_inst.lastVal.length > 0 && this.$input.val().length === 0))
terom@22: return;
terom@22:
terom@22: if (this._defaults.timeOnly === true) formattedDateTime = this.formattedTime;
terom@22: else if (this._defaults.timeOnly !== true && (this._defaults.alwaysSetTime || timeAvailable)) {
terom@22: if (this.$altInput) this.$altInput.val(this.formattedTime);
terom@22: else formattedDateTime += ' ' + this.formattedTime;
terom@22: }
terom@22:
terom@22: this.formattedDateTime = formattedDateTime;
terom@22: this.$input.val(formattedDateTime).trigger("change");
terom@22: }
terom@22:
terom@22: });
terom@22:
terom@22: $.fn.extend({
terom@22: //########################################################################
terom@22: // shorthand just to use timepicker..
terom@22: //########################################################################
terom@22: timepicker: function(o) {
terom@22: o = o || {};
terom@22: var tmp_args = arguments;
terom@22:
terom@22: if (typeof o == 'object') tmp_args[0] = $.extend(o, { timeOnly: true });
terom@22:
terom@22: return $(this).each(function() {
terom@22: $.fn.datetimepicker.apply($(this), tmp_args);
terom@22: });
terom@22: },
terom@22:
terom@22: //########################################################################
terom@22: // extend timepicker to datepicker
terom@22: //########################################################################
terom@22: datetimepicker: function(o) {
terom@22: o = o || {};
terom@22: var $input = this,
terom@22: tmp_args = arguments;
terom@22:
terom@22: if (typeof(o) == 'string'){
terom@22: if(o == 'getDate')
terom@22: return $.fn.datepicker.apply($(this), tmp_args);
terom@22: else
terom@22: return this.each(function() {
terom@22: $.fn.datepicker.apply($(this), tmp_args);
terom@22: });
terom@22: }
terom@22: else
terom@22: return this.each(function() {
terom@22: $(this).datepicker($.timepicker._newInst($input, o)._defaults);
terom@22: });
terom@22: }
terom@22: });
terom@22:
terom@22: //########################################################################
terom@22: // the bad hack :/ override datepicker so it doesnt close on select
terom@22: // inspired: http://stackoverflow.com/questions/1252512/jquery-datepicker-prevent-closing-picker-when-clicking-a-date/1762378#1762378
terom@22: //########################################################################
terom@22: $.datepicker._base_selectDate = $.datepicker._selectDate;
terom@22: $.datepicker._selectDate = function (id, dateStr) {
terom@22: var inst = this._getInst($(id)[0]),
terom@22: tp_inst = this._get(inst, 'timepicker');
terom@22:
terom@22: if (tp_inst) {
terom@22: inst.inline = inst.stay_open = true;
terom@22: this._base_selectDate(id, dateStr);
terom@22: inst.inline = inst.stay_open = false;
terom@22: this._notifyChange(inst);
terom@22: this._updateDatepicker(inst);
terom@22: }
terom@22: else this._base_selectDate(id, dateStr);
terom@22: };
terom@22:
terom@22: //#############################################################################################
terom@22: // second bad hack :/ override datepicker so it triggers an event when changing the input field
terom@22: // and does not redraw the datepicker on every selectDate event
terom@22: //#############################################################################################
terom@22: $.datepicker._base_updateDatepicker = $.datepicker._updateDatepicker;
terom@22: $.datepicker._updateDatepicker = function(inst) {
terom@22: if (typeof(inst.stay_open) !== 'boolean' || inst.stay_open === false) {
terom@22: this._base_updateDatepicker(inst);
terom@22: // Reload the time control when changing something in the input text field.
terom@22: this._beforeShow(inst.input, inst);
terom@22: }
terom@22: };
terom@22:
terom@22: $.datepicker._beforeShow = function(input, inst) {
terom@22: var beforeShow = this._get(inst, 'beforeShow');
terom@22: if (beforeShow) {
terom@22: inst.stay_open = true;
terom@22: beforeShow.apply((inst.input ? inst.input[0] : null), [inst.input, inst]);
terom@22: inst.stay_open = false;
terom@22: }
terom@22: };
terom@22:
terom@22: //#######################################################################################
terom@22: // third bad hack :/ override datepicker so it allows spaces and colan in the input field
terom@22: //#######################################################################################
terom@22: $.datepicker._base_doKeyPress = $.datepicker._doKeyPress;
terom@22: $.datepicker._doKeyPress = function(event) {
terom@22: var inst = $.datepicker._getInst(event.target),
terom@22: tp_inst = $.datepicker._get(inst, 'timepicker');
terom@22:
terom@22: if (tp_inst) {
terom@22: if ($.datepicker._get(inst, 'constrainInput')) {
terom@22: var ampm = tp_inst._defaults.ampm,
terom@22: datetimeChars = tp_inst._defaults.timeFormat.toString()
terom@22: .replace(/[hms]/g, '')
terom@22: .replace(/TT/g, ampm ? 'APM' : '')
terom@22: .replace(/T/g, ampm ? 'AP' : '')
terom@22: .replace(/tt/g, ampm ? 'apm' : '')
terom@22: .replace(/t/g, ampm ? 'ap' : '') +
terom@22: " " +
terom@22: $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat')),
terom@22: chr = String.fromCharCode(event.charCode === undefined ? event.keyCode : event.charCode);
terom@22: return event.ctrlKey || (chr < ' ' || !datetimeChars || datetimeChars.indexOf(chr) > -1);
terom@22: }
terom@22: } else return $.datepicker._base_doKeyPress(event);
terom@22:
terom@22: };
terom@22:
terom@22: //#######################################################################################
terom@22: // Override key up event to sync manual input changes.
terom@22: //#######################################################################################
terom@22: $.datepicker._base_doKeyUp = $.datepicker._doKeyUp;
terom@22: $.datepicker._doKeyUp = function (event) {
terom@22: var inst = $.datepicker._getInst(event.target),
terom@22: tp_inst = $.datepicker._get(inst, 'timepicker');
terom@22:
terom@22: if (tp_inst) {
terom@22: if (tp_inst._defaults.timeOnly && (inst.input.val() != inst.lastVal)) {
terom@22: try {
terom@22: $.datepicker._updateDatepicker(inst);
terom@22: }
terom@22: catch (err) {
terom@22: $.datepicker.log(err);
terom@22: }
terom@22: }
terom@22: }
terom@22:
terom@22: return $.datepicker._base_doKeyUp(event);
terom@22: };
terom@22:
terom@22: //#######################################################################################
terom@22: // override "Today" button to also grab the time.
terom@22: //#######################################################################################
terom@22: $.datepicker._base_gotoToday = $.datepicker._gotoToday;
terom@22: $.datepicker._gotoToday = function(id) {
terom@22: this._base_gotoToday(id);
terom@22: this._setTime(this._getInst($(id)[0]), new Date());
terom@22: };
terom@22:
terom@22: //#######################################################################################
terom@22: // Create our own set time function
terom@22: //#######################################################################################
terom@22: $.datepicker._setTime = function(inst, date) {
terom@22: var tp_inst = this._get(inst, 'timepicker');
terom@22:
terom@22: if (tp_inst) {
terom@22: var defaults = tp_inst._defaults,
terom@22: // calling _setTime with no date sets time to defaults
terom@22: hour = date ? date.getHours() : defaults.hour,
terom@22: minute = date ? date.getMinutes() : defaults.minute,
terom@22: second = date ? date.getSeconds() : defaults.second;
terom@22:
terom@22: //check if within min/max times..
terom@22: if ((hour < defaults.hourMin || hour > defaults.hourMax) || (minute < defaults.minuteMin || minute > defaults.minuteMax) || (second < defaults.secondMin || second > defaults.secondMax)) {
terom@22: hour = defaults.hourMin;
terom@22: minute = defaults.minuteMin;
terom@22: second = defaults.secondMin;
terom@22: }
terom@22:
terom@22: if (tp_inst.hour_slider) tp_inst.hour_slider.slider('value', hour);
terom@22: else tp_inst.hour = hour;
terom@22: if (tp_inst.minute_slider) tp_inst.minute_slider.slider('value', minute);
terom@22: else tp_inst.minute = minute;
terom@22: if (tp_inst.second_slider) tp_inst.second_slider.slider('value', second);
terom@22: else tp_inst.second = second;
terom@22:
terom@22: tp_inst._onTimeChange(true);
terom@22: }
terom@22: };
terom@22:
terom@22: //#######################################################################################
terom@22: // Create new public method to set only time, callable as $().datepicker('setTime', date)
terom@22: //#######################################################################################
terom@22: $.datepicker._setTimeDatepicker = function(target, date, withDate) {
terom@22: var inst = this._getInst(target),
terom@22: tp_inst = this._get(inst, 'timepicker');
terom@22:
terom@22: if (tp_inst) {
terom@22: var tp_date;
terom@22: if (date) {
terom@22: if (typeof date == "string") {
terom@22: tp_inst._parseTime(date, withDate);
terom@22: tp_date = new Date();
terom@22: tp_date.setHours(tp_inst.hour, tp_inst.minute, tp_inst.second);
terom@22: }
terom@22: else tp_date = new Date(date.getTime());
terom@22: if (tp_date.toString() == 'Invalid Date') tp_date = undefined;
terom@22: }
terom@22: this._setTime(inst, tp_date);
terom@22: }
terom@22:
terom@22: };
terom@22:
terom@22: //#######################################################################################
terom@22: // override setDate() to allow setting time too within Date object
terom@22: //#######################################################################################
terom@22: $.datepicker._base_setDateDatepicker = $.datepicker._setDateDatepicker;
terom@22: $.datepicker._setDateDatepicker = function(target, date) {
terom@22: var inst = this._getInst(target);
terom@22:
terom@22: // XXX: fix for null date --terom
terom@22: var tp_date = (date ? new Date(date.getTime()) : null);
terom@22:
terom@22: this._updateDatepicker(inst);
terom@22: this._base_setDateDatepicker.apply(this, arguments);
terom@22: this._setTimeDatepicker(target, tp_date, true);
terom@22: };
terom@22:
terom@22: //#######################################################################################
terom@22: // override getDate() to allow getting time too within Date object
terom@22: //#######################################################################################
terom@22: $.datepicker._base_getDateDatepicker = $.datepicker._getDateDatepicker;
terom@22: $.datepicker._getDateDatepicker = function(target, noDefault) {
terom@22: var inst = this._getInst(target),
terom@22: tp_inst = this._get(inst, 'timepicker');
terom@22: if (tp_inst)
terom@22: return (!inst.currentYear || (inst.input && inst.input.val() == '')) ?
terom@22: null :
terom@22: (new Date(inst.currentYear, inst.currentMonth, inst.currentDay, tp_inst.hour, tp_inst.minute, tp_inst.second));
terom@22: else return this._base_getDateDatepicker(inst);
terom@22: };
terom@22:
terom@22: //#######################################################################################
terom@22: // jQuery extend now ignores nulls!
terom@22: //#######################################################################################
terom@22: function extendRemove(target, props) {
terom@22: $.extend(target, props);
terom@22: for (var name in props)
terom@22: if (props[name] === null || props[name] === undefined)
terom@22: target[name] = props[name];
terom@22: return target;
terom@22: }
terom@22:
terom@22: $.timepicker = new Timepicker(); // singleton instance
terom@22: $.timepicker.version = "0.9.1";
terom@22:
terom@22: })(jQuery);