;(function () { var template = '
' + '
' + ' #{hourValue}' + ' :' + ' #{minValue}' + '
' + '
' + '
' + ' ' + '
' + '
' + ' ' + '
' + '
' + '
', datepicker = $.fn.datepicker, dp = datepicker.Constructor; datepicker.Timepicker = function (inst, opts) { this.d = inst; this.opts = opts; this.init(); }; datepicker.Timepicker.prototype = { init: function () { var input = 'input'; this._setTime(this.d.date); this._buildHTML(); if (navigator.userAgent.match(/trident/gi)) { input = 'change'; } this.d.$el.on('selectDate', this._onSelectDate.bind(this)); this.$ranges.on(input, this._onChangeRange.bind(this)); this.$ranges.on('mouseup', this._onMouseUpRange.bind(this)); this.$ranges.on('mousemove focus ', this._onMouseEnterRange.bind(this)); this.$ranges.on('mouseout blur', this._onMouseOutRange.bind(this)); }, _setTime: function (date) { var _date = dp.getParsedDate(date); this._handleDate(date); this.hours = _date.hours < this.minHours ? this.minHours : _date.hours; this.minutes = _date.minutes < this.minMinutes ? this.minMinutes : _date.minutes; }, _setMinTimeFromDate: function (date) { this.minHours = date.getHours(); this.minMinutes = date.getMinutes(); }, _setMaxTimeFromDate: function (date) { this.maxHours = date.getHours(); this.maxMinutes = date.getMinutes(); }, _setDefaultMinMaxTime: function () { var maxHours = 23, maxMinutes = 59, opts = this.opts; this.minHours = opts.minHours < 0 || opts.minHours > maxHours ? 0 : opts.minHours; this.minMinutes = opts.minMinutes < 0 || opts.minMinutes > maxMinutes ? 0 : opts.minMinutes; this.maxHours = opts.maxHours < 0 || opts.maxHours > maxHours ? maxHours : opts.maxHours; this.maxMinutes = opts.maxMinutes < 0 || opts.maxMinutes > maxMinutes ? maxMinutes : opts.maxMinutes; }, /** * Looks for min/max hours/minutes and if current values * are out of range sets valid values. * @private */ _validateHoursMinutes: function (date) { if (this.hours < this.minHours) { this.hours = this.minHours; } else if (this.hours > this.maxHours) { this.hours = this.maxHours; } if (this.minutes < this.minMinutes) { this.minutes = this.minMinutes; } else if (this.minutes > this.maxMinutes) { this.minutes = this.maxMinutes; } }, _buildHTML: function () { var lz = dp.getLeadingZeroNum, data = { hourMin: this.minHours, hourMax: lz(this.maxHours), hourStep: this.opts.hoursStep, hourValue: lz(this.displayHours), minMin: this.minMinutes, minMax: lz(this.maxMinutes), minStep: this.opts.minutesStep, minValue: lz(this.minutes) }, _template = dp.template(template, data); this.$timepicker = $(_template).appendTo(this.d.$datepicker); this.$ranges = $('[type="range"]', this.$timepicker); this.$hours = $('[name="hours"]', this.$timepicker); this.$minutes = $('[name="minutes"]', this.$timepicker); this.$hoursText = $('.datepicker--time-current-hours', this.$timepicker); this.$minutesText = $('.datepicker--time-current-minutes', this.$timepicker); if (this.d.ampm) { this.$ampm = $('') .appendTo($('.datepicker--time-current', this.$timepicker)) .html(this.dayPeriod); this.$timepicker.addClass('-am-pm-'); } }, _updateCurrentTime: function () { var h = dp.getLeadingZeroNum(this.displayHours), m = dp.getLeadingZeroNum(this.minutes); this.$hoursText.html(h); this.$minutesText.html(m); if (this.d.ampm) { this.$ampm.html(this.dayPeriod); } }, _updateRanges: function () { this.$hours.attr({ min: this.minHours, max: this.maxHours }).val(this.hours); this.$minutes.attr({ min: this.minMinutes, max: this.maxMinutes }).val(this.minutes) }, /** * Sets minHours, minMinutes etc. from date. If date is not passed, than sets * values from options * @param [date] {object} - Date object, to get values from * @private */ _handleDate: function (date) { this._setDefaultMinMaxTime(); if (date) { if (dp.isSame(date, this.d.opts.minDate)) { this._setMinTimeFromDate(this.d.opts.minDate); } else if (dp.isSame(date, this.d.opts.maxDate)) { this._setMaxTimeFromDate(this.d.opts.maxDate); } } this._validateHoursMinutes(date); }, update: function () { this._updateRanges(); this._updateCurrentTime(); }, /** * Calculates valid hour value to display in text input and datepicker's body. * @param date {Date|Number} - date or hours * @returns {{hours: *, dayPeriod: string}} * @private */ _getValidHoursFromDate: function (date) { var d = date, hours = date; if (date instanceof Date) { d = dp.getParsedDate(date); hours = d.hours; } var ampm = this.d.ampm, dayPeriod = 'am'; if (ampm) { switch(true) { case hours == 0: hours = 12; break; case hours == 12: dayPeriod = 'pm'; break; case hours > 11: hours = hours - 12; dayPeriod = 'pm'; break; default: break; } } return { hours: hours, dayPeriod: dayPeriod } }, set hours (val) { this._hours = val; var displayHours = this._getValidHoursFromDate(val); this.displayHours = displayHours.hours; this.dayPeriod = displayHours.dayPeriod; }, get hours() { return this._hours; }, // Events // ------------------------------------------------- _onChangeRange: function (e) { var $target = $(e.target), name = $target.attr('name'); this.d.timepickerIsActive = true; this[name] = $target.val(); this._updateCurrentTime(); this.d._trigger('timeChange', [this.hours, this.minutes]) }, _onSelectDate: function (e, data) { this._handleDate(data); this.update(); }, _onMouseEnterRange: function (e) { var name = $(e.target).attr('name'); $('.datepicker--time-current-' + name, this.$timepicker).addClass('-focus-'); }, _onMouseOutRange: function (e) { var name = $(e.target).attr('name'); if (this.d.inFocus) return; // Prevent removing focus when mouse out of range slider $('.datepicker--time-current-' + name, this.$timepicker).removeClass('-focus-'); }, _onMouseUpRange: function (e) { this.d.timepickerIsActive = false; } }; })();