Отмена действий по умолчанию

Библиотека Pikaday интегрируется с DOM через привязку к input-элементу и набор стандартных браузерных событий: focus, click, keydown, blur. Поведение по умолчанию формируется комбинацией этих событий и внутреннего состояния календаря (open/close, selected date, render cycle). Отмена стандартных действий в этом контексте означает управление тремя слоями:

  • нативные действия HTML-элементов (input focus, ввод, сабмит формы)
  • поведение браузера (открытие виртуальной клавиатуры, прокрутка, автозаполнение)
  • реакции Pikaday на события DOM

Отмена автоматического открытия календаря

Стандартное поведение: при фокусе или клике на поле input календарь открывается автоматически.

Контроль осуществляется через настройку привязки:

Отключение автоматической привязки

const picker = new Pikaday({
  field: document.querySelector('#date'),
  bound: false
});

При bound: false библиотека перестаёт автоматически слушать события поля ввода. Открытие и закрытие полностью переводится в ручное управление через методы:

picker.show();
picker.hide();

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

Перехват клика по input и предотвращение открытия

Если требуется сохранить привязку, но отменить стандартное открытие, используется перехват DOM-события до обработки Pikaday:

const input = document.querySelector('#date');

input.addEventListener('click', (e) => {
  e.preventDefault();
  e.stopImmediatePropagation();
});

Ключевые моменты:

  • preventDefault() блокирует стандартное действие браузера
  • stopImmediatePropagation() предотвращает выполнение обработчиков Pikaday

Это эффективно подавляет открытие календаря при клике, но сохраняет возможность программного управления через show().

Отмена открытия при фокусе

Pikaday использует focus как один из триггеров открытия. Для его блокировки применяется аналогичный подход:

input.addEventListener('focus', (e) => {
  e.preventDefault();
  e.stopPropagation();
}, true);

Использование третьего аргумента true (capture phase) важно: обработчик срабатывает до внутренних событий библиотеки.

Управление поведением формы

Input с календарём часто находится внутри формы, и стандартное поведение submit может конфликтовать с логикой выбора даты.

Отмена отправки формы при выборе даты

const form = document.querySelector('form');

form.addEventListener('submit', (e) => {
  e.preventDefault();
});

Хотя это не напрямую связано с Pikaday, в большинстве интеграций выбор даты автоматически триггерит валидацию или submit через change.

Контроль события изменения значения

Pikaday обновляет значение input через onSelect. Это приводит к срабатыванию change события, что может считаться “действием по умолчанию” в бизнес-логике.

Подавление change-события

const picker = new Pikaday({
  field: document.querySelector('#date'),
  onSelect: function() {
    const value = this.getDate();

    // временное отключение реакции input
    const input = this._o.field;

    const descriptor = Object.getOwnPropertyDescriptor(
      HTMLInputElement.prototype,
      'value'
    );

    descriptor.set.call(input, value);
  }
});

Более практичный вариант — временное отключение слушателей:

let suppress = false;

input.addEventListener('change', (e) => {
  if (suppress) return;
  console.log('обычное изменение');
});

const picker = new Pikaday({
  field: input,
  onSelect: function() {
    suppress = true;
    input.value = this.toString();
    suppress = false;
  }
});

Отмена автоподстановки значения в input

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

const picker = new Pikaday({
  field: document.querySelector('#date'),
  toString(date) {
    return '';
  },
  onSelect: function(date) {
    // значение не записывается в input автоматически
  }
});

Альтернативный способ — ручное управление:

const picker = new Pikaday({
  field: document.querySelector('#date'),
  onSelect: function(date) {
    // полный контроль над записью
  }
});

Блокировка закрытия при blur

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

Подмена blur-логики

const input = document.querySelector('#date');

input.addEventListener('blur', (e) => {
  e.preventDefault();
  setTimeout(() => {
    input.focus();
  }, 0);
});

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

Управление закрытием календаря

Pikaday закрывается при клике вне области календаря. Это поведение можно изменить через onClose и внешнюю логику.

const picker = new Pikaday({
  field: document.querySelector('#date'),
  onClose: function() {
    // предотвращение повторного закрытия через show()
    setTimeout(() => {
      if (this._preventClose) {
        this.show();
      }
    }, 0);
  }
});

И переключатель состояния:

picker._preventClose = true;

Отмена навигации по клавиатуре

По умолчанию Pikaday обрабатывает стрелки, Enter и Escape.

Блокировка клавиатурных событий

input.addEventListener('keydown', (e) => {
  const blockedKeys = ['ArrowUp', 'ArrowDown', 'Escape'];

  if (blockedKeys.includes(e.key)) {
    e.preventDefault();
    e.stopPropagation();
  }
}, true);

Это предотвращает:

  • открытие календаря через клавиатуру
  • переключение дат стрелками
  • закрытие через Escape

Отключение прокрутки месяца колесом мыши

Некоторые реализации Pikaday позволяют переключать месяцы через wheel-события (в зависимости от версии и кастомизации).

Перехват wheel

const container = document.querySelector('.pika-single');

container.addEventListener('wheel', (e) => {
  e.preventDefault();
  e.stopPropagation();
}, { passive: false });

Полная изоляция поведения (режим ручного управления)

Максимальный контроль достигается отключением всех стандартных триггеров и использованием API напрямую:

const picker = new Pikaday({
  field: document.querySelector('#date'),
  bound: false,
  onSelect: function() {
    document.querySelector('#date').value = this.toString();
  }
});

document.querySelector('#openBtn').addEventListener('click', () => {
  picker.show();
});

document.querySelector('#closeBtn').addEventListener('click', () => {
  picker.hide();
});

В этом режиме:

  • отсутствует автоматическое открытие
  • отсутствует закрытие по blur
  • отсутствует скрытая синхронизация поведения
  • весь lifecycle управляется вручную

Приоритеты событий и конфликт обработчиков

Отмена действий в Pikaday часто сводится к управлению порядком выполнения событий:

  1. capture-фаза (true)
  2. нативные обработчики Pikaday
  3. bubble-фаза пользовательского кода

Использование capture-фазы позволяет перехватывать события раньше библиотеки:

input.addEventListener('click', handler, true);

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

Ограничение побочных эффектов DOM-синхронизации

При изменении даты Pikaday обновляет DOM-значение input. Это может вызывать:

  • повторные валидации
  • автосабмит формы
  • реакцию сторонних библиотек

Для изоляции применяется буферизация:

let internalUpdate = false;

const picker = new Pikaday({
  field: input,
  onSelect: function() {
    internalUpdate = true;
    input.value = this.toString();
    internalUpdate = false;
  }
});

input.addEventListener('input', (e) => {
  if (internalUpdate) return;
  // внешняя логика
});

Этот механизм разделяет внутренние изменения календаря и пользовательский ввод.

Управление жизненным циклом через API вместо событий DOM

Полная отмена стандартных действий достигается отказом от DOM-событий в пользу методов экземпляра:

  • show()
  • hide()
  • gotoDate()
  • setDate()
  • destroy()
picker.setDate(new Date(), true);
picker.hide();

Второй параметр true предотвращает триггер событий, связанных с изменением.


Контроль над стандартным поведением в Pikaday строится не на одной точке отмены, а на комбинации перехвата событий, отключения привязки, управления фазами обработки и изоляции DOM-синхронизации.