В основе работы календаря лежит система ограничений, определяющая допустимый диапазон дат и правила доступности отдельных дней. В Pikaday такие ограничения не являются статичными: они могут изменяться в любой момент после инициализации экземпляра календаря, что делает библиотеку пригодной для сценариев с зависимыми датами, бизнес-правилами и внешними данными.
Ключевые механизмы ограничений:
minDate)maxDate)disableDayFn)Эти параметры не фиксируются навсегда при создании экземпляра и могут быть изменены через API или прямое обновление свойств с последующим пересчётом состояния календаря.
Наиболее распространённый сценарий динамических ограничений — изменение допустимого диапазона выбора.
Минимальная дата ограничивает выбор слева от календаря:
picker.setMinDate(new Date(2026, 0, 10));
После вызова метод пересчитывает доступные ячейки, исключая все даты до указанной.
Внутренне происходит:
Аналогично задаётся верхняя граница:
picker.setMaxDate(new Date(2026, 11, 31));
При этом все даты позже указанной становятся недоступными для выбора и визуально блокируются.
Частый сценарий — два связанных календаря (например, дата начала и дата окончания периода). При изменении одной даты необходимо динамически корректировать ограничения второй.
startPicker.on('select', function () {
endPicker.setMinDate(this.getDate());
});
Логика:
endPicker.on('select', function () {
startPicker.setMaxDate(this.getDate());
});
Такая схема обеспечивает строгую согласованность диапазона без дополнительной валидации на уровне формы.
В некоторых случаях ограничения формируются на основе внешних данных: ответа API, пользовательских прав, календаря занятости.
fetch('/api/availability')
.then(res => res.json())
.then(data => {
picker.setMinDate(new Date(data.min));
picker.setMaxDate(new Date(data.max));
});
Особенность такого подхода:
Помимо диапазонов используется функция постраничного контроля доступности дат.
const picker = new Pikaday({
disableDayFn: function (date) {
return date.getDay() === 0 || date.getDay() === 6;
}
});
Здесь логика определяет, что выходные недоступны.
Хотя прямого сеттера для disableDayFn нет, поведение
можно менять через замену функции и перерисовку:
picker.config.disableDayFn = function (date) {
return blockedDates.includes(date.toISOString().slice(0, 10));
};
picker.draw();
Ключевой момент:
draw()При динамическом изменении параметров важно обеспечить актуализацию UI.
Используются методы:
picker.draw();
picker.gotoToday();
draw() пересобирает текущую визуальную сетку календаря,
учитывая новые ограничения.
В сложных интерфейсах ограничения часто зависят от состояния формы:
Пример:
select.addEventListener('change', function () {
if (this.value === 'premium') {
picker.setMinDate(new Date(2026, 0, 1));
picker.setMaxDate(new Date(2026, 11, 31));
} else {
picker.setMinDate(new Date());
picker.setMaxDate(null);
}
});
Особенности:
null снимает ограничениеПри изменении ограничений важно учитывать уже выбранную дату. Pikaday не всегда автоматически сбрасывает некорректное значение, поэтому применяется дополнительная проверка:
const selected = picker.getDate();
picker.setMinDate(new Date(2026, 5, 1));
if (selected && selected < picker.getMinDate()) {
picker.setDate(null);
}
Это предотвращает ситуацию, когда текущий выбор оказывается вне допустимого диапазона.
При изменении min/max календарь может сохранять текущий месяц, если он остаётся валидным. Это поведение важно для UX:
Пример сценария:
maxDate на августВ продвинутых сценариях используются сразу несколько механизмов:
minDate, maxDate)disableDayFn)Пример комплексной логики:
function applyRules(rules) {
picker.setMinDate(new Date(rules.min));
picker.setMaxDate(new Date(rules.max));
picker.config.disableDayFn = function (date) {
return rules.disabled.includes(date.toISOString().split('T')[0]);
};
picker.draw();
}
Такой подход позволяет централизовать управление ограничениями и обновлять их в одном месте.
При интенсивных обновлениях важно учитывать стоимость перерисовки:
setMinDate и setMaxDate триггерят
перерасчётdraw() могут быть дорогимиОптимизированный подход:
picker.setMinDate(min);
picker.setMaxDate(max);
picker.config.disableDayFn = fn;
picker.draw();
Вместо:
picker.setMinDate(min);
picker.draw();
picker.setMaxDate(max);
picker.draw();
Снятие ограничений реализуется через null:
picker.setMinDate(null);
picker.setMaxDate(null);
Это возвращает календарь в состояние полного диапазона, но сохраняет
остальные правила, включая disableDayFn.
Хотя ограничения не зависят напрямую от локализации, визуальное восприятие может меняться:
При динамическом изменении ограничений важно учитывать, что пересчёт сетки всегда использует текущие локализационные настройки экземпляра.