+function ($) { 'use strict'; // DATEPICKER PUBLIC CLASS DEFINITION // ================================== var Datepicker = function (element, options) { this.$element = $(element); this.$element.data('datepicker', this); this.options = $.extend({}, Datepicker.DEFAULTS, options); this.$allowUpdate = true; this.updateOptions(options); this.$dates = new DateArray(); this.$viewDate = this.$Options.defaultViewDate; this.$widget = $(this.initWidget()); this.addTemplateArrows(); this.buildEvents(); this.unapplyEvents(this.$events); this.applyEvents(this.$events); this.$viewMode = this.$Options.startView; this.$allowUpdate = false; this.setStartDate(this.$Options.startDate); this.setEndDate(this.$Options.endDate); this.setDaysOfWeekDisabled(this.$Options.daysOfWeekDisabled); this.setDaysOfWeekHighlighted(this.$Options.daysOfWeekHighlighted); this.setDatesDisabled(this.$Options.datesDisabled); this.fillDays(); this.fillMonths(); this.$allowUpdate = true; this.update(); this.updateWidgetMode(); }; Datepicker.VERSION = '1.0.0'; Datepicker.DEFAULTS = { assumeNearbyYear: false, calendarWeeks: false, datesDisabled: [], daysOfWeekDisabled: [], daysOfWeekHighlighted: [], endDate: Infinity, forceParse: true, format: 'mm/dd/yyyy', maxViewMode: 2, menu: '
', minViewMode: 0, multidate: false, multidateSeparator: ',', startDate: -Infinity, startView: 0, templates: { leftArrow: '', rightArrow: '' }, text: { titleFormat: 'MM yyyy', days: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], daysShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], daysMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], months: ['January','February','March','April','May','June','July','August','September','October','November','December'], monthsShort: ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'] }, toggleActive: false, weekStart: 0 }; Datepicker.prototype.constructor = Datepicker; Datepicker.prototype.updateOptions = function (options) { this.$Options = $.extend({}, this.options, options); this.$Options.startView = this.resolveViewName(this.$Options.startView, 0); this.$Options.minViewMode = this.resolveViewName(this.$Options.minViewMode, 0); this.$Options.maxViewMode = this.resolveViewName(this.$Options.maxViewMode, 4); this.$Options.startView = Math.min(this.$Options.startView, this.$Options.maxViewMode); this.$Options.startView = Math.max(this.$Options.startView, this.$Options.minViewMode); if (this.$Options.multidate !== true) { this.$Options.multidate = Number(this.$Options.multidate) || false; if (this.$Options.multidate !== false) { this.$Options.multidate = Math.max(0, this.$Options.multidate); } } this.$Options.multidateSeparator = String(this.$Options.multidateSeparator); this.$Options.weekStart %= 7; this.$Options.weekEnd = (this.$Options.weekStart + 6) % 7; var format = this.parseFormat(this.$Options.format); if (this.$Options.startDate !== -Infinity) { if (!!this.$Options.startDate) { if (this.$Options.startDate instanceof Date) { this.$Options.startDate = this.localToUtc(this.zeroTime(this.$Options.startDate)); } else { this.$Options.startDate = this.parseDate(this.$Options.startDate, format, this.$Options.assumeNearbyYear); } } else { this.$Options.startDate = -Infinity; } } if (this.$Options.endDate !== Infinity) { if (!!this.$Options.endDate) { if (this.$Options.endDate instanceof Date) { this.$Options.endDate = this.localToUtc(this.zeroTime(this.$Options.endDate)); } else { this.$Options.endDate = this.parseDate(this.$Options.endDate, format, this.$Options.assumeNearbyYear); } } else { this.$Options.endDate = Infinity; } } this.$Options.daysOfWeekDisabled = this.$Options.daysOfWeekDisabled || []; if (!$.isArray(this.$Options.daysOfWeekDisabled)) { this.$Options.daysOfWeekDisabled = this.$Options.daysOfWeekDisabled.split(/[,\s]*/); } this.$Options.daysOfWeekDisabled = $.map(this.$Options.daysOfWeekDisabled, function (date) { return parseInt(date, 10); }); this.$Options.daysOfWeekHighlighted = this.$Options.daysOfWeekHighlighted || []; if (!$.isArray(this.$Options.daysOfWeekHighlighted)) { this.$Options.daysOfWeekHighlighted = this.$Options.daysOfWeekHighlighted.split(/[,\s]*/); } this.$Options.daysOfWeekHighlighted = $.map(this.$Options.daysOfWeekHighlighted, function (date) { return parseInt(date, 10); }); this.$Options.datesDisabled = this.$Options.datesDisabled || []; if (!$.isArray(this.$Options.datesDisabled)) { this.$Options.datesDisabled = [this.$Options.datesDisabled]; } this.$Options.datesDisabled = $.map(this.$Options.datesDisabled,function (date) { return this.parseDate(date, format, this.$Options.assumeNearbyYear); }); if (this.$Options.defaultViewDate) { var year = this.$Options.defaultViewDate.year || new Date().getFullYear(); var month = this.$Options.defaultViewDate.month || 0; var day = this.$Options.defaultViewDate.day || 1; this.$Options.defaultViewDate = this.utcDate(year, month, day); } else { this.$Options.defaultViewDate = this.utcToday(); } }; Datepicker.prototype.resolveViewName = function (view, value) { if (view === 0 || view === 'days' || view === 'month') return 0; if (view === 1 || view === 'months' || view === 'year') return 1; if (view === 2 || view === 'years' || view === 'decade') return 2; if (view === 3 || view === 'decades' || view === 'century') return 3; if (view === 4 || view === 'centuries' || view === 'millennium') return 4; return value === undefined ? false : value; }; Datepicker.prototype.checkTemplate = function (tmp) { try { if (tmp === undefined || tmp === '') return false; if ((tmp.match(/[<>]/g) || []).length <= 0) return true; return $(tmp).length > 0; } catch (e) { return false; } }; Datepicker.prototype.buildEvents = function () { this.$events = [ [this.$element, { 'focus.bs.datepicker': $.proxy(this.showWidget, this), 'click.bs.datepicker': $.proxy(this.showWidget, this) }] ]; this.$eventsAlt = [ [this.$widget, { 'click.bs.datepicker': $.proxy(this.clickWidget, this) }], [$(document), { 'mousedown.bs.datepicker, touchend.bs.datepicker': $.proxy(function (e) { if (!( this.$element.is(e.target) || this.$element.find(e.target).length || this.$widget.is(e.target) || this.$widget.find(e.target).length )) { this.hideWidget(); } }, this) }] ]; }; Datepicker.prototype.applyEvents = function (evs) { for (var i = 0, el, ch, ev; i < evs.length; i++) { el = evs[i][0]; if (evs[i].length === 2) { ch = undefined; ev = evs[i][1]; } else if (evs[i].length === 3) { ch = evs[i][1]; ev = evs[i][2]; } el.on(ev, ch); } }; Datepicker.prototype.unapplyEvents = function (evs) { for (var i = 0, el, ev, ch; i < evs.length; i++) { el = evs[i][0]; if (evs[i].length === 2) { ch = undefined; ev = evs[i][1]; } else if (evs[i].length === 3) { ch = evs[i][1]; ev = evs[i][2]; } el.off(ev, ch); } }; Datepicker.prototype.utcToLocal = function (utc) { return utc && new Date(utc.getTime() + (utc.getTimezoneOffset() * 60000)); }; Datepicker.prototype.localToUtc = function (local) { return local && new Date(local.getTime() - (local.getTimezoneOffset() * 60000)); }; Datepicker.prototype.zeroTime = function (local) { return local && new Date(local.getFullYear(), local.getMonth(), local.getDate()); }; Datepicker.prototype.zeroUtcTime = function (utc) { return utc && new Date(Date.UTC(utc.getUTCFullYear(), utc.getUTCMonth(), utc.getUTCDate())); }; Datepicker.prototype.getDates = function () { return $.map(this.$dates, this.utcToLocal); }; Datepicker.prototype.getUTCDates = function () { return $.map(this.$dates, function (date) { return new Date(date); }); }; Datepicker.prototype.getDate = function () { return this.utcToLocal(this.getUTCDate()); }; Datepicker.prototype.getUTCDate = function () { var selected_date = this.$dates.get(-1); if (typeof(selected_date) !== 'undefined') { return new Date(selected_date); } else { return null; } }; Datepicker.prototype.setValue = function () { this.$element.val(this.getFormattedDate()); }; Datepicker.prototype.setDate = function (date, which) { if (!which || which === 'date') this.toggleMultidate(date && new Date(date)); if (!which || which === 'view') this.$viewDate = date && new Date(date); this.fill(); this.setValue(); if (!which || which !== 'view') this.triggerEvent('changeDate'); if (this.$element) this.$element.change(); if (!which || which === 'date') this.hideWidget(); }; Datepicker.prototype.clearDates = function () { if (this.$element) this.$element.val(''); this.update(); this.triggerEvent('changeDate'); this.hideWidget(); }; Datepicker.prototype.getFormattedDate = function (format) { if (format === undefined) { format = this.$Options.format; } var _self = this; return $.map(this.$dates, function (date) { return _self.formatDate(date, format); }).join(this.$Options.multidateSeparator); }; Datepicker.prototype.setUTCDate = function () { var args = $.isArray(arguments[0]) ? arguments[0] : arguments; this.update.apply(this, $.map(args, this.utcToLocal)); this.triggerEvent('changeDate'); this.setValue(); }; Datepicker.prototype.updateAll = function () { this.update(); this.updateWidgetArrows(); }; Datepicker.prototype.setStartDate = function (startDate) { this.updateOptions({ 'startDate': startDate }); this.updateAll(); }; Datepicker.prototype.setEndDate = function (endDate) { this.updateOptions({ 'endDate': endDate }); this.updateAll(); }; Datepicker.prototype.setDaysOfWeekDisabled = function (daysOfWeekDisabled) { this.updateOptions({ 'daysOfWeekDisabled': daysOfWeekDisabled }); this.updateAll(); }; Datepicker.prototype.setDaysOfWeekHighlighted = function (daysOfWeekHighlighted) { this.updateOptions({ 'daysOfWeekHighlighted': daysOfWeekHighlighted }); this.updateAll(); }; Datepicker.prototype.setDatesDisabled = function (datesDisabled) { this.updateOptions({ 'datesDisabled': datesDisabled }); this.updateAll(); }; Datepicker.prototype.setRange = function (range) { if (!range || !range.length) { delete this.$range; } else { this.$range = $.map(range, function (date) { return date.valueOf(); }); } this.fill(); }; Datepicker.prototype.moveDay = function (date, dir) { var newDate = new Date(date); newDate.setUTCDate(date.getUTCDate() + dir); return newDate; }; Datepicker.prototype.moveWeek = function (date, dir) { return this.moveDay(date, dir * 7); }; Datepicker.prototype.moveMonth = function (date, dir) { if (!this.isValidDate(date)) return this.$Options.defaultViewDate; if (!dir) return date; var newMonth, test; var newDate = new Date(date.valueOf()); var day = newDate.getUTCDate(); var month = newDate.getUTCMonth(); var mag = Math.abs(dir); dir = dir > 0 ? 1 : -1; if (mag === 1) { test = dir === -1 ? function () { return newDate.getUTCMonth() === month; } : function () { return newDate.getUTCMonth() !== newMonth; }; newMonth = month + dir; newDate.setUTCMonth(newMonth); if (newMonth < 0 || newMonth > 11) { newMonth = (newMonth + 12) % 12; } } else { for (var i = 0; i < mag; i++) { newDate = this.moveMonth(newDate, dir); newMonth = newDate.getUTCMonth(); newDate.setUTCDate(day); } test = function () { return newMonth !== newDate.getUTCMonth(); }; } while (test()) { newDate.setUTCDate(--day); newDate.setUTCMonth(newMonth); } return newDate; }; Datepicker.prototype.moveYear = function (date, dir) { return this.moveMonth(date, dir * 12); }; Datepicker.prototype.moveAvailableDate = function (date, dir, fn) { do { date = this[fn](date, dir); if (!this.dateWithinRange(date)) return false; fn = 'moveDay'; } while (this.dateIsDisabled(date)); return date; }; Datepicker.prototype.weekOfDateIsDisabled = function (date) { return $.inArray(date.getUTCDay(), this.$Options.daysOfWeekDisabled) !== -1; }; Datepicker.prototype.dateIsDisabled = function (date) { return this.weekOfDateIsDisabled(date) || $.grep(this.$Options.datesDisabled, function (d) { return this.isUTCEquals(date, d); }).length > 0; }; Datepicker.prototype.dateWithinRange = function (date) { return date >= this.$Options.startDate && date <= this.$Options.endDate; }; Datepicker.prototype.toggleMultidate = function (date) { var ix = this.$dates.contains(date); if (!date) this.$dates.clear(); if (ix !== -1) { if (this.$Options.multidate === true || this.$Options.multidate > 1 || this.$Options.toggleActive) { this.$dates.remove(ix); } } else if (this.$Options.multidate === false) { this.$dates.clear(); this.$dates.push(date); } else { this.$dates.push(date); } if (typeof this.$Options.multidate === 'number') { while (this.$dates.length > this.$Options.multidate) this.$dates.remove(0); } }; Datepicker.prototype.getClassNames = function (date) { var cls = []; var year = this.$viewDate.getUTCFullYear(); var month = this.$viewDate.getUTCMonth(); var today = new Date(); if (date.getUTCFullYear() < year || (date.getUTCFullYear() === year && date.getUTCMonth() < month)) { cls.push('old'); } else if (date.getUTCFullYear() > year || (date.getUTCFullYear() === year && date.getUTCMonth() > month)) { cls.push('new'); } if (date.getUTCFullYear() === today.getFullYear() && date.getUTCMonth() === today.getMonth() && date.getUTCDate() === today.getDate()) { cls.push('today'); } if (this.$dates.contains(date) !== -1) cls.push('active'); if (!this.dateWithinRange(date)) cls.push('disabled'); if (this.dateIsDisabled(date)) cls.push('disabled', 'disabled-date'); if ($.inArray(date.getUTCDay(), this.$Options.daysOfWeekHighlighted) !== -1) cls.push('highlighted'); if (this.$range) { if (date > this.$range[0] && date < this.$range[this.$range.length-1]) cls.push('range'); if ($.inArray(date.valueOf(), this.$range) !== -1) cls.push('selected'); if (date.valueOf() === this.$range[0]) cls.push('range-start'); if (date.valueOf() === this.$range[this.$range.length-1]) cls.push('range-end'); } return cls; }; Datepicker.prototype.fill = function () { var date = new Date(this.$viewDate); var year = date.getUTCFullYear(); var month = date.getUTCMonth(); if (isNaN(year) || isNaN(month)) return; var startYear = this.$Options.startDate !== -Infinity ? this.$Options.startDate.getUTCFullYear() : -Infinity; var startMonth = this.$Options.startDate !== -Infinity ? this.$Options.startDate.getUTCMonth() : -Infinity; var endYear = this.$Options.endDate !== Infinity ? this.$Options.endDate.getUTCFullYear() : Infinity; var endMonth = this.$Options.endDate !== Infinity ? this.$Options.endDate.getUTCMonth() : Infinity; var titleFormat = this.$Options.text.titleFormat; this.$widget .find('.datepicker-days .datepicker-switch') .text(this.formatDate(date, titleFormat)); this.updateWidgetArrows(); this.fillMonths(); var prevMonth = this.utcDate(year, month - 1, 28); var day = this.getDaysInMonth(prevMonth.getUTCFullYear(), prevMonth.getUTCMonth()); prevMonth.setUTCDate(day); prevMonth.setUTCDate(day - (prevMonth.getUTCDay() - this.$Options.weekStart + 7) % 7); var nextMonth = new Date(prevMonth); if (prevMonth.getUTCFullYear() < 100) nextMonth.setUTCFullYear(prevMonth.getUTCFullYear()); nextMonth.setUTCDate(nextMonth.getUTCDate() + 42); nextMonth = nextMonth.valueOf(); var html = []; var clsName; while (prevMonth.valueOf() < nextMonth) { if (prevMonth.getUTCDay() === this.$Options.weekStart) { html.push('' + this.$Options.templates.leftArrow + ' | ') .append('') .append(' | ' + this.$Options.templates.rightArrow + ' | '); var header = $('') .append(row); return header; }; Datepicker.prototype.templateBody = function (klass) { var body = $('||||
---|---|---|---|---|---|---|