Параметр onOpen

Событие onOpen в Pikaday представляет собой callback, вызываемый в момент, когда календарный интерфейс становится видимым для пользователя. Это одна из ключевых точек жизненного цикла виджета, позволяющая внедрять дополнительную логику непосредственно в момент активации datepicker.

Момент вызова и поведение

onOpen срабатывает каждый раз, когда календарь переходит в состояние отображения. Это происходит:

  • при фокусе на input (если используется showOn: 'focus')
  • при клике на поле ввода (если включён режим showOn: 'button' или кастомный триггер)
  • при программном вызове метода picker.show()

Важно, что onOpen вызывается уже после того, как DOM-структура календаря создана и вставлена в документ, но до активного взаимодействия пользователя с датами.

Сигнатура и контекст выполнения

Callback onOpen не принимает аргументов, однако внутри функции доступен контекст экземпляра Pikaday через this.

Типичная сигнатура:

onOpen: function () {
    // this -> экземпляр Pikaday
}

Через this доступны все публичные методы и свойства экземпляра:

  • this.el — связанный input-элемент
  • this.isVisible — состояние видимости
  • this.getDate() — текущая выбранная дата
  • this.setDate() — установка значения
  • this.hide() / this.show() — управление отображением

Базовое использование

Наиболее простой сценарий применения onOpen — фиксация факта открытия календаря или выполнение побочных действий:

const picker = new Pikaday({
    field: document.getElementById('date'),
    onOpen: function () {
        console.log('Календарь открыт');
    }
});

В данном случае callback используется как точка наблюдения за состоянием компонента без вмешательства в его поведение.

Инициализация динамических данных при открытии

Часто onOpen применяется для ленивой подготовки данных. Например, загрузка доступных дат с сервера:

const picker = new Pikaday({
    field: document.getElementById('date'),
    onOpen: function () {
        if (!this.availableDates) {
            fetch('/api/available-dates')
                .then(res => res.json())
                .then(data => {
                    this.availableDates = data;
                    this.draw();
                });
        }
    }
});

Здесь используется ленивый подход: данные подгружаются только при первом открытии, а затем кэшируются внутри экземпляра.

Управление состоянием UI при открытии

onOpen часто применяется для синхронизации внешнего интерфейса с состоянием календаря. Например, подсветка активного поля или блокировка других элементов:

const picker = new Pikaday({
    field: document.getElementById('date'),
    onOpen: function () {
        this.el.classList.add('datepicker-focused');
        document.body.classList.add('calendar-active');
    }
});

Такой подход позволяет связывать визуальное состояние календаря с глобальным UI.

Работа с позиционированием и DOM-изменениями

В некоторых сценариях календарь требует корректировки позиционирования после открытия, особенно при кастомных контейнерах или overflow-ограничениях.

const picker = new Pikaday({
    field: document.getElementById('date'),
    bound: false,
    container: document.getElementById('calendar-container'),
    onOpen: function () {
        const rect = this.el.getBoundingClientRect();

        this.el.style.position = 'absolute';
        this.el.style.top = `${rect.bottom + window.scrollY}px`;
        this.el.style.left = `${rect.left + window.scrollX}px`;
    }
});

Здесь onOpen используется как точка корректировки геометрии уже отрендеренного элемента.

Взаимодействие с методами show/hide

При программном управлении календарём через show() и hide() важно учитывать, что onOpen вызывается именно при show(), но не при каждом изменении состояния вручную внутри логики.

picker.onO pen = function () {
    if (this._suppressOpenCallback) return;

    console.log('Открытие календаря');
};

picker._suppressOpenCallback = true;
picker.show();
picker._suppressOpenCallback = false;

Такой паттерн используется для временного подавления побочных эффектов при программных манипуляциях.

Использование для интеграции с внешними компонентами

onOpen часто становится мостом между Pikaday и сторонними UI-библиотеками, например модальными окнами или системами валидации.

const picker = new Pikaday({
    field: document.getElementById('date'),
    onOpen: function () {
        window.dispatchEvent(new CustomEvent('datepicker:open', {
            detail: {
                element: this.el
            }
        }));
    }
});

Такой подход позволяет централизованно реагировать на открытие календаря в других частях приложения.

Особенности повторных открытий

onOpen вызывается при каждом открытии календаря, включая повторные. Это важно учитывать при работе с ресурсозатратными операциями:

  • нельзя без контроля выполнять повторные fetch-запросы
  • нежелательно пересоздавать тяжелые DOM-структуры
  • следует использовать кэширование внутри экземпляра

Корректный подход:

onOpen: function () {
    if (this._initialized) return;

    this._initialized = true;
    this.prepareHeavyResources();
}

Взаимодействие с состоянием выбора даты

Хотя onOpen не связан напрямую с выбором даты, он часто используется для подготовки интерфейса в зависимости от уже выбранного значения:

onOpen: function () {
    const selected = this.getDate();

    if (selected) {
        this.gotoDate(selected);
    }
}

Это позволяет открывать календарь сразу на нужном месяце, синхронизированном с текущим значением input.

Ограничения и типичные ошибки

При использовании onOpen встречаются типовые проблемы:

  • выполнение логики до полной готовности DOM (ошибка доступа к элементам календаря вне контекста this.el)
  • многократная инициализация обработчиков событий без очистки
  • изменение состояния, вызывающее перерисовку, приводящее к повторным side-effect эффектам

Корректная работа требует учета того, что onOpen — это не инициализация компонента, а событие перехода в состояние видимости.

Комбинация с другими callback’ами

onOpen часто используется совместно с:

  • onClose — для симметричной очистки состояния
  • onSelect — для реакций на выбор даты после открытия
  • onDraw — для кастомизации рендера после открытия

Пример связки:

new Pikaday({
    field: document.getElementById('date'),

    onOpen: function () {
        this.el.classList.add('open');
    },

    onClose: function () {
        this.el.classList.remove('open');
    },

    onSelect: function () {
        console.log('Дата выбрана:', this.getDate());
    }
});

Такая комбинация формирует полный цикл управления состоянием календаря через события жизненного цикла.