var Datepicker; (function (window, $, undefined) { var pluginName = 'datepicker', autoInitSelector = '.datepicker-here', $body, $datepickersContainer, containerBuilt = false, baseTemplate = '' + '
' + '' + '' + '
' + '
', defaults = { classes: '', inline: false, language: 'ru', startDate: new Date(), firstDay: '', weekends: [6, 0], dateFormat: '', altField: '', altFieldDateFormat: '@', toggleSelected: true, keyboardNav: true, position: 'bottom left', offset: 12, view: 'days', minView: 'days', showOtherMonths: true, selectOtherMonths: true, moveToOtherMonthsOnSelect: true, showOtherYears: true, selectOtherYears: true, moveToOtherYearsOnSelect: true, minDate: '', maxDate: '', disableNavWhenOutOfRange: true, multipleDates: false, // Boolean or Number multipleDatesSeparator: ',', range: true, todayButton: false, clearButton: false, showEvent: 'focus', autoClose: false, // navigation monthsFiled: 'monthsShort', prevHtml: '', nextHtml: '', navTitles: { days: 'MM, yyyy', months: 'yyyy', years: 'yyyy1 - yyyy2' }, // events onSelect: '', onChangeMonth: '', onChangeYear: '', onChangeDecade: '', onChangeView: '', onRenderCell: '' }, hotKeys = { 'ctrlRight': [17, 39], 'ctrlUp': [17, 38], 'ctrlLeft': [17, 37], 'ctrlDown': [17, 40], 'shiftRight': [16, 39], 'shiftUp': [16, 38], 'shiftLeft': [16, 37], 'shiftDown': [16, 40], 'altUp': [18, 38], 'altRight': [18, 39], 'altLeft': [18, 37], 'altDown': [18, 40], 'ctrlShiftUp': [16, 17, 38] }; Datepicker = function (el, options) { this.el = el; this.$el = $(el); this.opts = $.extend(true, {}, defaults, options, this.$el.data()); if ($body == undefined) { $body = $('body'); } if (!this.opts.startDate) { this.opts.startDate = new Date(); } if (this.el.nodeName == 'INPUT') { this.elIsInput = true; } if (this.opts.altField) { this.$altField = typeof this.opts.altField == 'string' ? $(this.opts.altField) : this.opts.altField; } this.inited = false; this.visible = false; this.silent = false; // Need to prevent unnecessary rendering this.currentDate = this.opts.startDate; this.currentView = this.opts.view; this._createShortCuts(); this.selectedDates = []; this.views = {}; this.keys = []; this.minRange = ''; this.maxRange = ''; this.init() }; Datepicker.prototype = { viewIndexes: ['days', 'months', 'years'], init: function () { if (!containerBuilt && !this.opts.inline && this.elIsInput) { this._buildDatepickersContainer(); } this._buildBaseHtml(); this._defineLocale(this.opts.language); this._syncWithMinMaxDates(); if (this.elIsInput) { if (!this.opts.inline) { // Set extra classes for proper transitions this._setPositionClasses(this.opts.position); this._bindEvents() } } if (this.opts.classes) { this.$datepicker.addClass(this.opts.classes) } this.views[this.currentView] = new Datepicker.Body(this, this.currentView, this.opts); this.views[this.currentView].show(); this.nav = new Datepicker.Navigation(this, this.opts); this.view = this.currentView; this.$datepicker.on('mouseenter', '.datepicker--cell', this._onMouseEnterCell.bind(this)); this.$datepicker.on('mouseleave', '.datepicker--cell', this._onMouseLeaveCell.bind(this)); this.inited = true; }, _createShortCuts: function () { this.minDate = this.opts.minDate ? this.opts.minDate : new Date(-8639999913600000); this.maxDate = this.opts.maxDate ? this.opts.maxDate : new Date(8639999913600000); }, _bindEvents : function () { this.$el.on(this.opts.showEvent, this._onShowEvent.bind(this)); this.$el.on('blur', this._onBlur.bind(this)); this.$el.on('input', this._onInput.bind(this)); this.$datepicker.on('mousedown', this._onMouseDownDatepicker.bind(this)); this.$datepicker.on('mouseup', this._onMouseUpDatepicker.bind(this)); $(window).on('resize', this._onResize.bind(this)); if (this.opts.keyboardNav) { this.$el.on('keydown', this._onKeyDown.bind(this)); this.$el.on('keyup', this._onKeyUp.bind(this)); this.$el.on('hotKey', this._onHotKey.bind(this)); } }, isWeekend: function (day) { return this.opts.weekends.indexOf(day) !== -1; }, _defineLocale: function (lang) { if (typeof lang == 'string') { this.loc = Datepicker.language[lang]; if (!this.loc) { console.warn('Can\'t find language "' + lang + '" in Datepicker.language, will use "ru" instead'); this.loc = $.extend(true, {}, Datepicker.language.ru) } this.loc = $.extend(true, {}, Datepicker.language.ru, Datepicker.language[lang]) } else { this.loc = $.extend(true, {}, Datepicker.language.ru, lang) } if (this.opts.dateFormat) { this.loc.dateFormat = this.opts.dateFormat } if (this.opts.firstDay) { this.loc.firstDay = this.opts.firstDay } }, _buildDatepickersContainer: function () { containerBuilt = true; $body.append('
'); $datepickersContainer = $('#datepickers-container'); }, _buildBaseHtml: function () { var $appendTarget, $inline = $('
'); if(this.el.nodeName == 'INPUT') { if (!this.opts.inline) { $appendTarget = $datepickersContainer; } else { $appendTarget = $inline.insertAfter(this.$el) } } else { $appendTarget = $inline.appendTo(this.$el) } this.$datepicker = $(baseTemplate).appendTo($appendTarget); this.$content = $('.datepicker--content', this.$datepicker); this.$nav = $('.datepicker--nav', this.$datepicker); }, _triggerOnChange: function () { if (!this.selectedDates.length) { return this.opts.onSelect('', '', this); } var selectedDates = this.selectedDates, parsedSelected = Datepicker.getParsedDate(selectedDates[0]), formattedDates, _this = this, dates = new Date(parsedSelected.year, parsedSelected.month, parsedSelected.date); formattedDates = selectedDates.map(function (date) { return _this.formatDate(_this.loc.dateFormat, date) }).join(this.opts.multipleDatesSeparator); // Create new dates array, to separate it from original selectedDates if (this.opts.multipleDates) { dates = selectedDates.map(function(date) { var parsedDate = Datepicker.getParsedDate(date); return new Date(parsedDate.year, parsedDate.month, parsedDate.date) }) } this.opts.onSelect(formattedDates, dates, this); }, next: function () { var d = this.parsedDate, o = this.opts; switch (this.view) { case 'days': this.date = new Date(d.year, d.month + 1, 1); if (o.onChangeMonth) o.onChangeMonth(this.parsedDate.month, this.parsedDate.year); break; case 'months': this.date = new Date(d.year + 1, d.month, 1); if (o.onChangeYear) o.onChangeYear(this.parsedDate.year); break; case 'years': this.date = new Date(d.year + 10, 0, 1); if (o.onChangeDecade) o.onChangeDecade(this.curDecade); break; } }, prev: function () { var d = this.parsedDate, o = this.opts; switch (this.view) { case 'days': this.date = new Date(d.year, d.month - 1, 1); if (o.onChangeMonth) o.onChangeMonth(this.parsedDate.month, this.parsedDate.year); break; case 'months': this.date = new Date(d.year - 1, d.month, 1); if (o.onChangeYear) o.onChangeYear(this.parsedDate.year); break; case 'years': this.date = new Date(d.year - 10, 0, 1); if (o.onChangeDecade) o.onChangeDecade(this.curDecade); break; } }, formatDate: function (string, date) { date = date || this.date; var result = string, locale = this.loc, decade = Datepicker.getDecade(date), d = Datepicker.getParsedDate(date); switch (true) { case /@/.test(result): result = result.replace(/@/, date.getTime()); case /dd/.test(result): result = result.replace(/\bdd\b/, d.fullDate); case /d/.test(result): result = result.replace(/\bd\b/, d.date); case /DD/.test(result): result = result.replace(/\bDD\b/, locale.days[d.day]); case /D/.test(result): result = result.replace(/\bD\b/, locale.daysShort[d.day]); case /mm/.test(result): result = result.replace(/\bmm\b/, d.fullMonth); case /m/.test(result): result = result.replace(/\bm\b/, d.month + 1); case /MM/.test(result): result = result.replace(/\bMM\b/, this.loc.months[d.month]); case /M/.test(result): result = result.replace(/\bM\b/, locale.monthsShort[d.month]); case /yyyy/.test(result): result = result.replace(/\byyyy\b/, d.year); case /yyyy1/.test(result): result = result.replace(/\byyyy1\b/, decade[0]); case /yyyy2/.test(result): result = result.replace(/\byyyy2\b/, decade[1]); case /yy/.test(result): result = result.replace(/\byy\b/, d.year.toString().slice(-2)); } return result; }, selectDate: function (date) { var d = this.parsedDate, selectedDates = this.selectedDates, len = selectedDates.length, newDate = ''; if (!(date instanceof Date)) return; if (this.view == 'days') { if (date.getMonth() != d.month && this.opts.moveToOtherMonthsOnSelect) { newDate = new Date(date.getFullYear(), date.getMonth(), 1); } } if (this.view == 'years') { if (date.getFullYear() != d.year && this.opts.moveToOtherYearsOnSelect) { newDate = new Date(date.getFullYear(), 0, 1); } } if (newDate) { this.silent = true; this.date = newDate; this.silent = false; this.nav._render() } if (this.opts.multipleDates) { if (len === this.opts.multipleDates) return; if (!this._isSelected(date)) { this.selectedDates.push(date); } } else if (this.opts.range) { if (len == 2) { this.selectedDates = [date] } else if (len == 1) { if (Datepicker.less(this.selectedDates[0], date, this.cellType)) { this.selectedDates = [date] } else { this.selectedDates.push(date); } } else { this.selectedDates = [date] } } else { this. selectedDates = [date]; } this._setInputValue(); if (this.opts.onSelect) { this._triggerOnChange(); } if (this.opts.autoClose) { this.hide(); } this.views[this.currentView]._render() }, removeDate: function (date) { var selected = this.selectedDates, _this = this; if (!(date instanceof Date)) return; return selected.some(function (curDate, i) { if (Datepicker.isSame(curDate, date)) { selected.splice(i, 1); _this.views[_this.currentView]._render(); _this._setInputValue(); if (_this.opts.onSelect) { _this._triggerOnChange(); } return true } }) }, today: function () { this.silent = true; this.view = this.opts.minView; this.silent = false; this.date = new Date(); }, clear: function () { this.selectedDates = []; this.views[this.currentView]._render(); if (this.opts.onSelect) { this._triggerOnChange() } }, /** * Updates datepicker options * @param {String|Object} param - parameter's name to update. If object then it will extend current options * @param {String|Number|Object} [value] - new param value */ update: function (param, value) { var len = arguments.length; if (len == 2) { this.opts[param] = value; } else if (len == 1 && typeof param == 'object') { this.opts = $.extend(true, this.opts, param) } this._createShortCuts(); this._syncWithMinMaxDates(); this._defineLocale(this.opts.language); this.nav._addButtonsIfNeed(); this.nav._render(); this.views[this.currentView]._render(); if (this.elIsInput && !this.opts.inline) { this._setPositionClasses(this.opts.position); if (this.visible) { this.setPosition(this.opts.position) } } if (this.opts.classes) { this.$datepicker.addClass(this.opts.classes) } return this; }, _syncWithMinMaxDates: function () { var curTime = this.date.getTime(); this.silent = true; if (this.minTime > curTime) { this.date = this.minDate; } if (this.maxTime < curTime) { this.date = this.maxDate; } this.silent = false; }, _isSelected: function (checkDate, cellType) { return this.selectedDates.some(function (date) { return Datepicker.isSame(date, checkDate, cellType) }) }, _setInputValue: function () { var _this = this, format = this.loc.dateFormat, altFormat = this.opts.altFieldDateFormat, value = this.selectedDates.map(function (date) { return _this.formatDate(format, date) }), altValues; if (this.$altField) { altValues = this.selectedDates.map(function (date) { return _this.formatDate(altFormat, date) }); this.$altField.val(altValues); } value = value.join(this.opts.multipleDatesSeparator); this.$el.val(value) }, /** * Check if date is between minDate and maxDate * @param date {object} - date object * @param type {string} - cell type * @returns {boolean} * @private */ _isInRange: function (date, type) { var time = date.getTime(), d = Datepicker.getParsedDate(date), min = Datepicker.getParsedDate(this.minDate), max = Datepicker.getParsedDate(this.maxDate), dMinTime = new Date(d.year, d.month, min.date).getTime(), dMaxTime = new Date(d.year, d.month, max.date).getTime(), types = { day: time >= this.minTime && time <= this.maxTime, month: dMinTime >= this.minTime && dMaxTime <= this.maxTime, year: d.year >= min.year && d.year <= max.year }; return type ? types[type] : types.day }, _getDimensions: function ($el) { var offset = $el.offset(); return { width: $el.outerWidth(), height: $el.outerHeight(), left: offset.left, top: offset.top } }, _getDateFromCell: function (cell) { var curDate = this.parsedDate, year = cell.data('year') || curDate.year, month = cell.data('month') == undefined ? curDate.month : cell.data('month'), date = cell.data('date') || 1; return new Date(year, month, date); }, _setPositionClasses: function (pos) { pos = pos.split(' '); var main = pos[0], sec = pos[1], classes = 'datepicker -' + main + '-' + sec + '- -from-' + main + '-'; if (this.visible) classes += ' active'; this.$datepicker .removeAttr('class') .addClass(classes); }, setPosition: function (position) { position = position || this.opts.position; var dims = this._getDimensions(this.$el), selfDims = this._getDimensions(this.$datepicker), pos = position.split(' '), top, left, offset = this.opts.offset, main = pos[0], secondary = pos[1]; switch (main) { case 'top': top = dims.top - selfDims.height - offset; break; case 'right': left = dims.left + dims.width + offset; break; case 'bottom': top = dims.top + dims.height + offset; break; case 'left': left = dims.left - selfDims.width - offset; break; } switch(secondary) { case 'top': top = dims.top; break; case 'right': left = dims.left + dims.width - selfDims.width; break; case 'bottom': top = dims.top + dims.height - selfDims.height; break; case 'left': left = dims.left; break; case 'center': if (/left|right/.test(main)) { top = dims.top + dims.height/2 - selfDims.height/2; } else { left = dims.left + dims.width/2 - selfDims.width/2; } } this.$datepicker .css({ left: left, top: top }) }, show: function () { this.setPosition(this.opts.position); this.$datepicker.addClass('active'); this.visible = true; }, hide: function () { this.$datepicker .removeClass('active') .css({ left: '-100000px' }); this.focused = ''; this.keys = []; this.inFocus = false; this.visible = false; this.$el.blur(); }, down: function (date) { this._changeView(date, 'down'); }, up: function (date) { this._changeView(date, 'up'); }, _changeView: function (date, dir) { date = date || this.focused || this.date; var nextView = dir == 'up' ? this.viewIndex + 1 : this.viewIndex - 1; if (nextView > 2) nextView = 2; if (nextView < 0) nextView = 0; this.silent = true; this.date = new Date(date.getFullYear(), date.getMonth(), 1); this.silent = false; this.view = this.viewIndexes[nextView]; }, _handleHotKey: function (key) { var date = Datepicker.getParsedDate(this._getFocusedDate()), focusedParsed, o = this.opts, newDate, totalDaysInNextMonth, monthChanged = false, yearChanged = false, decadeChanged = false, y = date.year, m = date.month, d = date.date; switch (key) { case 'ctrlRight': case 'ctrlUp': m += 1; monthChanged = true; break; case 'ctrlLeft': case 'ctrlDown': m -= 1; monthChanged = true; break; case 'shiftRight': case 'shiftUp': yearChanged = true; y += 1; break; case 'shiftLeft': case 'shiftDown': yearChanged = true; y -= 1; break; case 'altRight': case 'altUp': decadeChanged = true; y += 10; break; case 'altLeft': case 'altDown': decadeChanged = true; y -= 10; break; case 'ctrlShiftUp': this.up(); break; } totalDaysInNextMonth = Datepicker.getDaysCount(new Date(y,m)); newDate = new Date(y,m,d); // If next month has less days than current, set date to total days in that month if (totalDaysInNextMonth < d) d = totalDaysInNextMonth; // Check if newDate is in valid range if (newDate.getTime() < this.minTime) { newDate = this.minDate; } else if (newDate.getTime() > this.maxTime) { newDate = this.maxDate; } this.focused = newDate; focusedParsed = Datepicker.getParsedDate(newDate); if (monthChanged && o.onChangeMonth) { o.onChangeMonth(focusedParsed.month, focusedParsed.year) } if (yearChanged && o.onChangeYear) { o.onChangeYear(focusedParsed.year) } if (decadeChanged && o.onChangeDecade) { o.onChangeDecade(this.curDecade) } }, _registerKey: function (key) { var exists = this.keys.some(function (curKey) { return curKey == key; }); if (!exists) { this.keys.push(key) } }, _unRegisterKey: function (key) { var index = this.keys.indexOf(key); this.keys.splice(index, 1); }, _isHotKeyPressed: function () { var currentHotKey, found = false, _this = this, pressedKeys = this.keys.sort(); for (var hotKey in hotKeys) { currentHotKey = hotKeys[hotKey]; if (pressedKeys.length != currentHotKey.length) continue; if (currentHotKey.every(function (key, i) { return key == pressedKeys[i]})) { _this._trigger('hotKey', hotKey); found = true; } } return found; }, _trigger: function (event, args) { this.$el.trigger(event, args) }, _focusNextCell: function (keyCode, type) { type = type || this.cellType; var date = Datepicker.getParsedDate(this._getFocusedDate()), y = date.year, m = date.month, d = date.date; if (this._isHotKeyPressed()){ return; } switch(keyCode) { case 37: // left type == 'day' ? (d -= 1) : ''; type == 'month' ? (m -= 1) : ''; type == 'year' ? (y -= 1) : ''; break; case 38: // up type == 'day' ? (d -= 7) : ''; type == 'month' ? (m -= 3) : ''; type == 'year' ? (y -= 4) : ''; break; case 39: // right type == 'day' ? (d += 1) : ''; type == 'month' ? (m += 1) : ''; type == 'year' ? (y += 1) : ''; break; case 40: // down type == 'day' ? (d += 7) : ''; type == 'month' ? (m += 3) : ''; type == 'year' ? (y += 4) : ''; break; } var nd = new Date(y,m,d); if (nd.getTime() < this.minTime) { nd = this.minDate; } else if (nd.getTime() > this.maxTime) { nd = this.maxDate; } this.focused = nd; }, _getFocusedDate: function () { var focused = this.focused || this.selectedDates[this.selectedDates.length - 1], d = this.parsedDate; if (!focused) { switch (this.view) { case 'days': focused = new Date(d.year, d.month, new Date().getDate()); break; case 'months': focused = new Date(d.year, d.month, 1); break; case 'years': focused = new Date(d.year, 0, 1); break; } } return focused; }, _getCell: function (date, type) { type = type || this.cellType; var d = Datepicker.getParsedDate(date), selector = '.datepicker--cell[data-year="' + d.year + '"]', $cell; switch (type) { case 'month': selector = '[data-month="' + d.month + '"]'; break; case 'day': selector += '[data-month="' + d.month + '"][data-date="' + d.date + '"]'; break; } $cell = this.views[this.currentView].$el.find(selector); return $cell.length ? $cell : ''; }, _onShowEvent: function () { if (!this.visible) { this.show(); } }, _onBlur: function () { //if (!this.inFocus && this.visible) { // this.hide(); //} }, _onMouseDownDatepicker: function (e) { this.inFocus = true; }, _onMouseUpDatepicker: function (e) { this.inFocus = false; this.$el.focus() }, _onInput: function () { var val = this.$el.val(); if (!val) { this.clear(); } }, _onResize: function () { if (this.visible) { this.setPosition(); } }, _onKeyDown: function (e) { var code = e.which; this._registerKey(code); // Arrows if (code >= 37 && code <= 40) { e.preventDefault(); this._focusNextCell(code); } // Enter if (code == 13) { if (this.focused) { if (this._getCell(this.focused).hasClass('-disabled-')) return; if (this.view != this.opts.minView) { this.down() } else { var alreadySelected = this._isSelected(this.focused, this.cellType); if (!alreadySelected) { this.selectDate(this.focused); } else if (alreadySelected && this.opts.toggleSelected){ this.removeDate(this.focused); } } } } // Esc if (code == 27) { this.hide(); } }, _onKeyUp: function (e) { var code = e.which; this._unRegisterKey(code); }, _onHotKey: function (e, hotKey) { this._handleHotKey(hotKey); }, _onMouseEnterCell: function (e) { var $cell = $(e.target).closest('.datepicker--cell'), date = this._getDateFromCell($cell); // Prevent from unnecessary rendering and setting new currentDate this.silent = true; if (this.focused) { this.focused = '' } $cell.addClass('-focus-'); this.focused = date; this.silent = false; }, _onMouseLeaveCell: function (e) { var $cell = $(e.target).closest('.datepicker--cell'), date = this._getDateFromCell($cell); $cell.removeClass('-focus-'); this.silent = true; this.focused = ''; this.silent = false; }, set focused(val) { if (!val && this.focused) { var $cell = this._getCell(this.focused); if ($cell.length) { $cell.removeClass('-focus-') } } this._focused = val; if (this.silent) return; this.date = val; }, get focused() { return this._focused; }, get parsedDate() { return Datepicker.getParsedDate(this.date); }, set date (val) { if (!(val instanceof Date)) return; this.currentDate = val; if (this.inited && !this.silent) { this.views[this.view]._render(); this.nav._render(); if (this.visible && this.elIsInput) { this.setPosition(); } } return val; }, get date () { return this.currentDate }, set view (val) { this.viewIndex = this.viewIndexes.indexOf(val); if (this.viewIndex < 0) { return; } this.prevView = this.currentView; this.currentView = val; if (this.inited) { if (!this.views[val]) { this.views[val] = new Datepicker.Body(this, val, this.opts) } else { this.views[val]._render(); } this.views[this.prevView].hide(); this.views[val].show(); this.nav._render(); if (this.opts.onChangeView) { this.opts.onChangeView(val) } if (this.elIsInput && this.visible) this.setPosition(); } return val }, get view() { return this.currentView; }, get cellType() { return this.view.substring(0, this.view.length - 1) }, get minTime() { var min = Datepicker.getParsedDate(this.minDate); return new Date(min.year, min.month, min.date).getTime() }, get maxTime() { var max = Datepicker.getParsedDate(this.maxDate); return new Date(max.year, max.month, max.date).getTime() }, get curDecade() { return Datepicker.getDecade(this.date) } }; // Utils // ------------------------------------------------- Datepicker.getDaysCount = function (date) { return new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate(); }; Datepicker.getParsedDate = function (date) { return { year: date.getFullYear(), month: date.getMonth(), fullMonth: (date.getMonth() + 1) < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1, // One based date: date.getDate(), fullDate: date.getDate() < 10 ? '0' + date.getDate() : date.getDate(), day: date.getDay() } }; Datepicker.getDecade = function (date) { var firstYear = Math.floor(date.getFullYear() / 10) * 10; return [firstYear, firstYear + 9]; }; Datepicker.template = function (str, data) { return str.replace(/#\{([\w]+)\}/g, function (source, match) { if (data[match] || data[match] === 0) { return data[match] } }); }; Datepicker.isSame = function (date1, date2, type) { if (!date1 || !date2) return false; var d1 = Datepicker.getParsedDate(date1), d2 = Datepicker.getParsedDate(date2), _type = type ? type : 'day', conditions = { day: d1.date == d2.date && d1.month == d2.month && d1.year == d2.year, month: d1.month == d2.month && d1.year == d2.year, year: d1.year == d2.year }; return conditions[_type]; }; Datepicker.less = function (dateCompareTo, date, type) { return date.getTime() < dateCompareTo.getTime(); }; Datepicker.bigger = function (dateCompareTo, date, type) { return date.getTime() > dateCompareTo.getTime(); }; Datepicker.language = { ru: { days: ['Воскресенье', 'Понедельник', 'Вторник', 'Среда', 'Четверг', 'Пятница', 'Суббота'], daysShort: ['Вос','Пон','Вто','Сре','Чет','Пят','Суб'], daysMin: ['Вс','Пн','Вт','Ср','Чт','Пт','Сб'], months: ['Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь'], monthsShort: ['Янв', 'Фев', 'Мар', 'Апр', 'Май', 'Июн', 'Июл', 'Авг', 'Сен', 'Окт', 'Ноя', 'Дек'], today: 'Сегодня', clear: 'Очистить', dateFormat: 'dd.mm.yyyy', firstDay: 1 } }; $.fn[pluginName] = function ( options ) { if (Datepicker.prototype[options]) { Datepicker.prototype[options].apply(this.data(pluginName), Array.prototype.slice.call(arguments, 1)); } else { return this.each(function () { if (!$.data(this, pluginName)) { $.data(this, pluginName, new Datepicker( this, options )); } else { var _this = $.data(this, pluginName); _this.opts = $.extend(true, _this.opts, options); _this.update(); } }); } }; $(function () { $(autoInitSelector).datepicker(); }) })(window, jQuery);