Обработчик onDraw в библиотеке Pikaday вызывается каждый
раз, когда календарь полностью отрисовывается или перерисовывается. Это
касается как первичной инициализации виджета, так и любых последующих
обновлений интерфейса, связанных с изменением состояния календаря.
Перерисовка происходит при изменении месяца, года, диапазона дат, а
также при программном управлении состоянием пикера. Важно, что
onDraw относится не к выбору даты, а именно к жизненному
циклу отображения календарной сетки.
Обработчик задаётся в конфигурации экземпляра календаря:
new Pikaday({
field: document.getElementById('date'),
onDraw: function() {
// логика при отрисовке календаря
}
});
Функция вызывается в контексте экземпляра календаря, то есть
this внутри обработчика указывает на текущий объект
пикера.
Через this доступны основные свойства и методы:
this.el — корневой DOM-элемент календаряthis.currentMonth — текущий отображаемый месяцthis.currentYear — текущий отображаемый годthis.getDate() — выбранная дата (если есть)this.config — объект конфигурацииКонтекст важен, так как onDraw часто используется для
динамического изменения внешнего вида уже построенной DOM-структуры.
onDraw срабатывает в следующих случаях:
minDate и
maxDateКаждый вызов означает, что DOM календаря был пересоздан или обновлён, и любые кастомные изменения интерфейса необходимо применять заново.
onDrawТак как рендер календаря в Pikaday является динамическим, любые
прямые изменения DOM должны выполняться внутри onDraw,
иначе они будут потеряны при следующей перерисовке.
Типичный пример: добавление кастомных классов к ячейкам дней.
new Pikaday({
field: document.getElementById('date'),
onDraw: function() {
const cells = this.el.querySelectorAll('.pika-day');
cells.forEach(cell => {
const day = parseInt(cell.textContent, 10);
if (day === 1) {
cell.classList.add('is-first-day');
}
if (day % 2 === 0) {
cell.classList.add('is-even');
}
});
}
});
Любая логика стилизации должна быть идемпотентной: повторный вызов
onDraw не должен накапливать состояния без очистки.
Каждый вызов onDraw фактически означает новый DOM-слой
для сетки календаря. Это приводит к важному правилу: изменения,
внесённые вне onDraw, не сохраняются.
Пример неправильного подхода:
const picker = new Pikaday({ field: input });
const cells = document.querySelectorAll('.pika-day');
cells.forEach(c => c.classList.add('highlight'));
Такой код неустойчив, потому что при следующей отрисовке все изменения исчезнут.
Корректный подход — всегда работать внутри onDraw.
При использовании minDate и maxDate
происходит автоматическое изменение состояния ячеек календаря.
onDraw позволяет расширить эту логику, например, добавляя
визуальные маркеры недоступных дат.
new Pikaday({
field: document.getElementById('date'),
minDate: new Date(2026, 0, 1),
maxDate: new Date(2026, 11, 31),
onDraw: function() {
const cells = this.el.querySelectorAll('.pika-day');
cells.forEach(cell => {
const day = parseInt(cell.textContent, 10);
if (cell.classList.contains('is-disabled')) {
cell.setAttribute('title', 'Дата недоступна');
}
});
}
});
Здесь важно учитывать, что библиотека уже добавляет базовые классы
состояния, а onDraw лишь дополняет их.
onDraw может использовать текущее состояние календаря
для вычислений отображения. Например, выделение выходных или
событий:
const holidays = [1, 2, 3];
new Pikaday({
field: document.getElementById('date'),
onDraw: function() {
const cells = this.el.querySelectorAll('.pika-day');
cells.forEach(cell => {
const day = parseInt(cell.textContent, 10);
if (holidays.includes(day)) {
cell.classList.add('is-holiday');
}
});
}
});
Такой подход часто используется для интеграции с внешними источниками данных, где визуальные метки накладываются после стандартного рендера.
Поскольку onDraw вызывается часто, любые тяжёлые
операции внутри него влияют на отзывчивость интерфейса.
Критические моменты:
onDraw недопустимыthis.el.querySelectorAllОптимизированный пример:
new Pikaday({
field: input,
onDraw: function() {
const el = this.el;
const cells = el.querySelectorAll('.pika-day');
for (let i = 0; i < cells.length; i++) {
const cell = cells[i];
const value = +cell.textContent;
if (value > 25) {
cell.classList.add('is-late-month');
}
}
}
});
При расширении интерфейса календаря через стили или сторонние скрипты
onDraw становится точкой синхронизации состояния DOM.
Особенно это важно при:
new Pikaday({
field: input,
onDraw: function() {
const days = this.el.querySelectorAll('.pika-day');
days.forEach(d => {
if (d.dataset.event === 'true') {
d.innerHTML += '<span class="dot"></span>';
}
});
}
});
Любое изменение innerHTML требует осторожности, так как
может конфликтовать с внутренней разметкой Pikaday.
onDrawЧасто встречающиеся проблемы:
Правильная стратегия — считать onDraw чистой точкой
синхронизации, а не местом построения логики приложения.
onDraw тесно связан с внутренними методами обновления
состояния. Любое изменение месяца, года или диапазона приводит к полной
перерисовке, и, соответственно, повторному вызову обработчика.
Это означает, что вся кастомизация интерфейса должна быть
детерминированной: одинаковое состояние календаря всегда должно
приводить к одинаковому DOM после выполнения onDraw.