mirror of
https://github.com/frappe/air-datepicker.git
synced 2026-07-03 03:01:28 +08:00
310 lines
11 KiB
JavaScript
310 lines
11 KiB
JavaScript
;(function () {
|
|
var templates = {
|
|
days:'' +
|
|
'<div class="datepicker--days datepicker--body">' +
|
|
'<div class="datepicker--days-names"></div>' +
|
|
'<div class="datepicker--cells datepicker--cells-days"></div>' +
|
|
'</div>',
|
|
months: '' +
|
|
'<div class="datepicker--months datepicker--body">' +
|
|
'<div class="datepicker--cells datepicker--cells-months"></div>' +
|
|
'</div>',
|
|
years: '' +
|
|
'<div class="datepicker--years datepicker--body">' +
|
|
'<div class="datepicker--cells datepicker--cells-years"></div>' +
|
|
'</div>'
|
|
},
|
|
datepicker = $.fn.datepicker,
|
|
dp = datepicker.Constructor;
|
|
|
|
datepicker.Body = function (d, type, opts) {
|
|
this.d = d;
|
|
this.type = type;
|
|
this.opts = opts;
|
|
|
|
this.init();
|
|
};
|
|
|
|
datepicker.Body.prototype = {
|
|
init: function () {
|
|
this._buildBaseHtml();
|
|
this._render();
|
|
|
|
this._bindEvents();
|
|
},
|
|
|
|
_bindEvents: function () {
|
|
this.$el.on('click', '.datepicker--cell', $.proxy(this._onClickCell, this));
|
|
},
|
|
|
|
_buildBaseHtml: function () {
|
|
this.$el = $(templates[this.type]).appendTo(this.d.$content);
|
|
this.$names = $('.datepicker--days-names', this.$el);
|
|
this.$cells = $('.datepicker--cells', this.$el);
|
|
},
|
|
|
|
_getDayNamesHtml: function (firstDay, curDay, html, i) {
|
|
curDay = curDay != undefined ? curDay : firstDay;
|
|
html = html ? html : '';
|
|
i = i != undefined ? i : 0;
|
|
|
|
if (i > 7) return html;
|
|
if (curDay == 7) return this._getDayNamesHtml(firstDay, 0, html, ++i);
|
|
|
|
html += '<div class="datepicker--day-name' + (this.d.isWeekend(curDay) ? " -weekend-" : "") + '">' + this.d.loc.daysMin[curDay] + '</div>';
|
|
|
|
return this._getDayNamesHtml(firstDay, ++curDay, html, ++i);
|
|
},
|
|
|
|
_getCellContents: function (date, type) {
|
|
var classes = "datepicker--cell datepicker--cell-" + type,
|
|
currentDate = new Date(),
|
|
parent = this.d,
|
|
opts = parent.opts,
|
|
d = dp.getParsedDate(date),
|
|
render = {},
|
|
html = d.date;
|
|
|
|
if (opts.onRenderCell) {
|
|
render = opts.onRenderCell(date, type) || {};
|
|
html = render.html ? render.html : html;
|
|
classes += render.classes ? ' ' + render.classes : '';
|
|
}
|
|
|
|
switch (type) {
|
|
case 'day':
|
|
if (parent.isWeekend(d.day)) classes += " -weekend-";
|
|
if (d.month != this.d.parsedDate.month) {
|
|
classes += " -other-month-";
|
|
if (!opts.selectOtherMonths) {
|
|
classes += " -disabled-";
|
|
}
|
|
if (!opts.showOtherMonths) html = '';
|
|
}
|
|
break;
|
|
case 'month':
|
|
html = parent.loc[parent.opts.monthsField][d.month];
|
|
break;
|
|
case 'year':
|
|
var decade = parent.curDecade;
|
|
html = d.year;
|
|
if (d.year < decade[0] || d.year > decade[1]) {
|
|
classes += ' -other-decade-';
|
|
if (!opts.selectOtherYears) {
|
|
classes += " -disabled-";
|
|
}
|
|
if (!opts.showOtherYears) html = '';
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (opts.onRenderCell) {
|
|
render = opts.onRenderCell(date, type) || {};
|
|
html = render.html ? render.html : html;
|
|
classes += render.classes ? ' ' + render.classes : '';
|
|
}
|
|
|
|
if (opts.range) {
|
|
if (dp.isSame(parent.minRange, date, type)) classes += ' -range-from-';
|
|
if (dp.isSame(parent.maxRange, date, type)) classes += ' -range-to-';
|
|
|
|
if (parent.selectedDates.length == 1 && parent.focused) {
|
|
if (
|
|
(dp.bigger(parent.minRange, date) && dp.less(parent.focused, date)) ||
|
|
(dp.less(parent.maxRange, date) && dp.bigger(parent.focused, date)))
|
|
{
|
|
classes += ' -in-range-'
|
|
}
|
|
|
|
if (dp.less(parent.maxRange, date) && dp.isSame(parent.focused, date)) {
|
|
classes += ' -range-from-'
|
|
}
|
|
if (dp.bigger(parent.minRange, date) && dp.isSame(parent.focused, date)) {
|
|
classes += ' -range-to-'
|
|
}
|
|
|
|
} else if (parent.selectedDates.length == 2) {
|
|
if (dp.bigger(parent.minRange, date) && dp.less(parent.maxRange, date)) {
|
|
classes += ' -in-range-'
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if (dp.isSame(currentDate, date, type)) classes += ' -current-';
|
|
if (parent.focused && dp.isSame(date, parent.focused, type)) classes += ' -focus-';
|
|
if (parent._isSelected(date, type)) classes += ' -selected-';
|
|
if (!parent._isInRange(date, type) || render.disabled) classes += ' -disabled-';
|
|
|
|
return {
|
|
html: html,
|
|
classes: classes
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Calculates days number to render. Generates days html and returns it.
|
|
* @param {object} date - Date object
|
|
* @returns {string}
|
|
* @private
|
|
*/
|
|
_getDaysHtml: function (date) {
|
|
var totalMonthDays = dp.getDaysCount(date),
|
|
firstMonthDay = new Date(date.getFullYear(), date.getMonth(), 1).getDay(),
|
|
lastMonthDay = new Date(date.getFullYear(), date.getMonth(), totalMonthDays).getDay(),
|
|
daysFromPevMonth = firstMonthDay - this.d.loc.firstDay,
|
|
daysFromNextMonth = 6 - lastMonthDay + this.d.loc.firstDay;
|
|
|
|
daysFromPevMonth = daysFromPevMonth < 0 ? daysFromPevMonth + 7 : daysFromPevMonth;
|
|
daysFromNextMonth = daysFromNextMonth > 6 ? daysFromNextMonth - 7 : daysFromNextMonth;
|
|
|
|
var startDayIndex = -daysFromPevMonth + 1,
|
|
m, y,
|
|
html = '';
|
|
|
|
for (var i = startDayIndex, max = totalMonthDays + daysFromNextMonth; i <= max; i++) {
|
|
y = date.getFullYear();
|
|
m = date.getMonth();
|
|
|
|
html += this._getDayHtml(new Date(y, m, i))
|
|
}
|
|
|
|
return html;
|
|
},
|
|
|
|
_getDayHtml: function (date) {
|
|
var content = this._getCellContents(date, 'day');
|
|
|
|
return '<div class="' + content.classes + '" ' +
|
|
'data-date="' + date.getDate() + '" ' +
|
|
'data-month="' + date.getMonth() + '" ' +
|
|
'data-year="' + date.getFullYear() + '">' + content.html + '</div>';
|
|
},
|
|
|
|
/**
|
|
* Generates months html
|
|
* @param {object} date - date instance
|
|
* @returns {string}
|
|
* @private
|
|
*/
|
|
_getMonthsHtml: function (date) {
|
|
var html = '',
|
|
d = dp.getParsedDate(date),
|
|
i = 0;
|
|
|
|
while(i < 12) {
|
|
html += this._getMonthHtml(new Date(d.year, i));
|
|
i++
|
|
}
|
|
|
|
return html;
|
|
},
|
|
|
|
_getMonthHtml: function (date) {
|
|
var content = this._getCellContents(date, 'month');
|
|
|
|
return '<div class="' + content.classes + '" data-month="' + date.getMonth() + '">' + content.html + '</div>'
|
|
},
|
|
|
|
_getYearsHtml: function (date) {
|
|
var d = dp.getParsedDate(date),
|
|
decade = dp.getDecade(date),
|
|
firstYear = decade[0] - 1,
|
|
html = '',
|
|
i = firstYear;
|
|
|
|
for (i; i <= decade[1] + 1; i++) {
|
|
html += this._getYearHtml(new Date(i , 0));
|
|
}
|
|
|
|
return html;
|
|
},
|
|
|
|
_getYearHtml: function (date) {
|
|
var content = this._getCellContents(date, 'year');
|
|
|
|
return '<div class="' + content.classes + '" data-year="' + date.getFullYear() + '">' + content.html + '</div>'
|
|
},
|
|
|
|
_renderTypes: {
|
|
days: function () {
|
|
var dayNames = this._getDayNamesHtml(this.d.loc.firstDay),
|
|
days = this._getDaysHtml(this.d.currentDate);
|
|
|
|
this.$cells.html(days);
|
|
this.$names.html(dayNames)
|
|
},
|
|
months: function () {
|
|
var html = this._getMonthsHtml(this.d.currentDate);
|
|
|
|
this.$cells.html(html)
|
|
},
|
|
years: function () {
|
|
var html = this._getYearsHtml(this.d.currentDate);
|
|
|
|
this.$cells.html(html)
|
|
}
|
|
},
|
|
|
|
_render: function () {
|
|
this._renderTypes[this.type].bind(this)();
|
|
},
|
|
|
|
_update: function () {
|
|
var $cells = $('.datepicker--cell', this.$cells),
|
|
_this = this,
|
|
classes,
|
|
$cell,
|
|
date;
|
|
$cells.each(function (cell, i) {
|
|
$cell = $(this);
|
|
date = _this.d._getDateFromCell($(this));
|
|
classes = _this._getCellContents(date, _this.d.cellType);
|
|
$cell.attr('class',classes.classes)
|
|
});
|
|
},
|
|
|
|
show: function () {
|
|
this.$el.addClass('active');
|
|
this.acitve = true;
|
|
},
|
|
|
|
hide: function () {
|
|
this.$el.removeClass('active');
|
|
this.active = false;
|
|
},
|
|
|
|
// Events
|
|
// -------------------------------------------------
|
|
|
|
_handleClick: function (el) {
|
|
var date = el.data('date') || 1,
|
|
month = el.data('month') || 0,
|
|
year = el.data('year') || this.d.parsedDate.year;
|
|
// Change view if min view does not reach yet
|
|
if (this.d.view != this.opts.minView) {
|
|
this.d.down(new Date(year, month, date));
|
|
return;
|
|
}
|
|
// Select date if min view is reached
|
|
var selectedDate = new Date(year, month, date),
|
|
alreadySelected = this.d._isSelected(selectedDate, this.d.cellType);
|
|
|
|
if (!alreadySelected) {
|
|
this.d._trigger('clickCell', selectedDate);
|
|
} else if (alreadySelected && this.opts.toggleSelected){
|
|
this.d.removeDate(selectedDate);
|
|
}
|
|
|
|
},
|
|
|
|
_onClickCell: function (e) {
|
|
var $el = $(e.target).closest('.datepicker--cell');
|
|
|
|
if ($el.hasClass('-disabled-')) return;
|
|
|
|
this._handleClick.bind(this)($el);
|
|
}
|
|
};
|
|
})();
|