en.javascript.info/archive/widget-tasks/4-double-calendar-with-arrows/solution.view/datepicker.js
2015-02-21 14:58:02 +03:00

130 lines
3.2 KiB
JavaScript

/**
* options:
* value Date или объект {year,month,day}} -- дата, для которой показывать календарь
* если в объекте указаны только {year,month}, то день не выбран
*/
function DatePicker(options) {
var elem;
var calendarLeft;
var calendarRight;
var calendarCache = {};
var showYear, showMonth;
var selectedYear, selectedMonth, selectedDay;
var self = this;
parseValue(options.value);
showYear = selectedYear;
showMonth = selectedMonth;
// -------------
this.getElement = function() {
if (!elem) render();
return elem;
};
this.getValue = function() {
if (!selectedDay) return null;
return new Date(selectedYear, selectedMonth, selectedDay);
};
function parseValue(value) {
if (value instanceof Date) {
selectedYear = value.getFullYear();
selectedMonth = value.getMonth();
selectedDay = value.getDate();
} else {
selectedYear = value.year;
selectedMonth = value.month;
selectedDay = value.day;
}
}
function getCalendar(year, month) {
var key = '' + year + month;
var calendar;
if (!calendarCache[key]) {
calendar = calendarCache[key] = new Calendar({
value: {year: year, month: month}
});
$(calendar).on("select", onCalendarSelect);
} else {
calendar = calendarCache[key];
}
var value = {
year: year,
month: month,
// если календарь отображает текущий выбранный месяц, то передать и день для выбора
day: (year == selectedYear && month == selectedMonth) ? selectedDay : null
};
calendar.setValue(value, true);
return calendar;
}
function onCalendarSelect(e) {
parseValue(e.value);
if (e.target == calendarLeft) {
calendarRight.clearValue();
} else {
calendarLeft.clearValue();
}
$(self).triggerHandler({
type: "select",
value: e.target.getValue()
});
}
function render() {
elem = $('<div class="datepicker"/>').html(
_.template(options.template)()
);
elem.on('mousedown', '.next-link', onNextLinkMouseDown);
elem.on('mousedown', '.prev-link', onPrevLinkMouseDown);
renderCalendars();
}
function renderCalendars() {
calendarLeft = getCalendar(showYear, showMonth);
// использую children().detach() вместо empty(),
// т.к. empty() убивает обработчики на календаре
elem.find('.calendar-left-holder').children().detach().end()
.append(calendarLeft.getElement());
var dateNextMonth = new Date(showYear, showMonth + 1);
calendarRight = getCalendar(dateNextMonth.getFullYear(), dateNextMonth.getMonth());
elem.find('.calendar-right-holder').children().detach().end()
.append(calendarRight.getElement());
}
function onNextLinkMouseDown() {
showMonth++;
if (showMonth > 11) {
showMonth = 0;
showYear++;
}
renderCalendars();
return false;
}
function onPrevLinkMouseDown() {
showMonth--;
if (showMonth < 0) {
showMonth = 11;
showYear--;
}
renderCalendars();
return false;
}
}