Примеры

На этой странице собраны небольшие примеры того, как работает и на что способен Air Datepicker.

Базовые примеры

С опциями по умолчанию

new AirDatepicker('#input');

Статичный календарь

Для того, чтобы календарь был постоянно видимый, нужно его проинициализировать не на текстовом поле, или передать параметр {inline: true}

new AirDatepicker('#div');

// Or init with {inline: true} on <input> or <div> elements

new AirDatepicker('#input', {
    inline: true
})

Выбор даты при инициализации

Для выбора даты используйте опцию selectedDates. На принимает массив дат, строк или чисел. Подробнее можно ознакомится в разделе документации. Давайте выберем сегодняшнюю дату.

new AirDatepicker('#el', {
    selectedDates: [new Date()]
})

Выбор месяца

Для возможности выбора только месяца без конкретного числа, можно использовать комбинацию из опций view и minView - с помощью первой мы устанавливаем текущее представление календаря, а с помощью второй задаем минимально возможное представление.

new AirDatepicker('#el', {
    view: 'months',
    minView: 'months',
    dateFormat: 'MMMM yyyy'
})

Режим для мобильных устройств

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

new AirDatepicker('#el', {
    isMobile: true,
    autoClose: true,
});

Позиционирование

Позиция календаря задается с помощью параметра position - он может быть как строкой так и функцией.

Простое позиционирование

Базовое позиционирование задается через строку - "'основная ось 'второстепенная ось'". Например, покажем календарь справа от текстового поля:

new AirDatepicker('#el', {
    position: 'right center'
})

Использование Popper.js

Если требуется более сложное позиционирование, например когда нужно чтобы календарь перепрыгивал на другу сторону текстового поля при скролле и т.п. можно использовать ручное позиционирование - с помощью функции и сторонних библиотек

В следующем примере обработаем позицию с помощью библиотеки Popper.js. Попробуйте проскролить страницу дальше.

import AirDatepicker from 'air-datepicker';
import {createPopper} from '@popperjs/core';

new AirDatepicker('#el', {
    container: '#scroll-container',
    visible: true,
    position({$datepicker, $target, $pointer, done}) {
        let popper = createPopper($target, $datepicker, {
            placement: 'top',
            modifiers: [
                {
                    name: 'flip',
                    options: {
                        padding: {
                            top: 64
                        }
                    }
                },
                {
                    name: 'offset',
                    options: {
                        offset: [0, 20]
                    }
                },
                {
                    name: 'arrow',
                    options: {
                        element: $pointer
                    }
                }
            ]
        })
        
        /*
		 Возвращаем функцию, которая вызывается при срабатывании `hide()`,
		 она обязательно должна вызвать функцию `done()`
 		 для завершения процесса скрытия календаря 
		*/
        return function completeHide() {
            popper.destroy();
            done();
        }    
    }
})
При использовании Popper.js, Air Datepicker автоматически повернет указатель в нужном направлении! 😎

Создание анимации появления и скрытия

Air Datepicker позволяет добавить свои анимации появления и скрытия. Вы также можете сделать это своими руками или же использовать любую библиотеку для анимаций.

Для следующего примера возьмем библиотеку anime.js и объединим ее с Popper.js

import AirDatepicker from 'air-datepicker';
import {createPopper} from '@popperjs/core';
import anime from 'animejs';

new AirDatepicker('#el', {
    position({$datepicker, $target, $pointer, isViewChange, done}) {
        let popper = createPopper($target, $datepicker, {
            placement: 'bottom',
            onFirstUpdate: state => {
                !isViewChange && anime.remove($datepicker);

                $datepicker.style.transformOrigin = 'center top';

                !isViewChange && anime({
                    targets: $datepicker,
                    opacity: [0, 1],
                    rotateX: [-90, 0],
                    easing: 'spring(1.3, 80, 5, 0)',
                })

            },
            modifiers: [
                {
                    name: 'offset',
                    options: {
                        offset: [0, 10]
                    }
                },
                {
                    name: 'arrow',
                    options: {
                        element: $pointer,
                    }
                },
                {
                    name: 'computeStyles',
                    options: {
                        gpuAcceleration: false,
                    },
                },
            ]
        });

        return () => {
            anime({
                targets: $datepicker,
                opacity: 0,
                rotateX: -90,
                duration: 300,
                easing: 'easeOutCubic'
            }).finished.then(() => {
                popper.destroy();
                done();
            })
        }
    }}
)

Диапазон дат

Для того, чтобы выбрать диапазон дат, передайте параметр {range: true}. После выбора обеих дат, можно скорректировать выбор просто перетаскивая активные даты.

new AirDatepicker('#input', {
    range: true,
    multipleDatesSeparator: ' - '
});

Запрет на выбор диапазона

Иногда есть необходимость запретить пользователю выбирать диапазон дат, если в нем есть недопустимые ячейки, для этого можно воспользоваться опциями onBeforeSelect и onFocus, а также небольшой стилизацией нашего диапазона. Попробуйте выбрать диапазон от 10 Июля до 16:

import AirDatepicker from 'air-datepicker';

import isWithinInterval  from 'date-fns/isWithinInterval';
import isEqual  from 'date-fns/isEqual';

const disabledDate = new Date('2023-07-13T00:00:00');

// Проверяем, находится ли недопустимая дата в диапазоне
const isDisabledDateIsInRange = ({date, datepicker}) => {
    const selectedDate = datepicker.selectedDates[0];
    if (selectedDate && datepicker.selectedDates.length === 1) {
        const sortedDates = [selectedDate, date].toSorted((a, b) => {
            if (a.getTime() > b.getTime()) {
                return 1;
            }
            return -1;
        })

        return (isWithinInterval(disabledDate, {
            start: sortedDates[0],
            end: sortedDates[1]
        }))
    }
}

new AirDatepicker('#el', {
    startDate: '2023-07-19',
    range: true,
    onBeforeSelect: ({date, datepicker}) => {
        // Не даем выбрать дату, если недопустимая дата в диапазоне
        return !isDisabledDateIsInRange({date, datepicker});
    },
    onFocus: ({date, datepicker}) => {
        if (isDisabledDateIsInRange({date, datepicker}) || isEqual(date, disabledDate)) {
           datepicker.$datepicker.classList.add('-disabled-range-')
        } else {
           datepicker.$datepicker.classList.remove('-disabled-range-')
        }
    }
    onRenderCell: ({date}) => {
        if (date.toLocaleDateString() === disabledDate.toLocaleDateString()) {
            return {
                disabled: true
            }
        }
    }}

});

.air-datepicker.-disabled-range- {
    --adp-cell-background-color-in-range: #eeeeee;
    --adp-cell-background-color-selected: #d0d0d0;
}

Минимальная и максимальные даты

Для манипуляции с минимально возможной и максимально возможной датой используйте опции minDate и maxDate. В сочетании с функцией update() можно реализовать выбор дат только в ограниченном диапазоне.

let dpMin, dpMax;

dpMin = new AirDatepicker('#el1', {
    onSelect({date}) {
        dpMax.update({
            minDate: date
        })
    }
})

dpMax = new AirDatepicker('#el2', {
    onSelect({date}) {
        dpMin.update({
            maxDate: date
        })
    }
})

Выбор времени

Передайте {timepicker: true} для выбора времени. По умолчанию устанавливается текущее время пользователя. Стартовое значение даты и времени можно регулировать с помощью параметра startDate.

new AirDatepicker('#input', {
    timepicker: true,
});

Формат времени

Формат времени задается в объекте локализации или в опции {timeFormat: '...'}. Для отображения времени в 12-ти часовом варианте, используйте символы 'h' или 'hh'. Чтобы отобразить период дня добавьте 'aa' или 'AA'.

new AirDatepicker('#input', {
    timepicker: true,
    timeFormat: 'hh:mm AA'
});

Настройка часов и минут

Время регулируется несколькими опциями, это minHours, maxHours, minMinutes, maxMinutes. Также можно настраивать шаг шкалы выбора времени с помощью hoursStep, minutesStep.

Давайте попробуем ограничивать выбор часов с 8 до 19 и добавить шаг выбора минут в значение 5.


new AirDatepicker({
    inline: true,
    timepicker: true,
    minHours: 9,
    maxHours: 18,
    minutesStep: 5
})

Содержимое ячеек

Air Datepicker позволяет изменять содержимое ячеек как угодно. Содержание, классы и статус (активный/не доступный для выбора) регулируются с помощью опции {onRenderCell: ({date, cellType}) => {})}.

В следующем примере заменим содержимое ячеек из списка дат на произвольную эмоджи, плюс поменяем активный цвет фона таких ячеек

let today = new Date();

new AirDatepicker('#inline-div', {
    // Handle render process
    onRenderCell({date, cellType}) {
        let dates = [1, 5, 7, 10, 15, 20, 25],
            emoji = ['💕', '😃', '🍙', '🍣', '🍻', '🎉', '🥁'],
            isDay = cellType === 'day',
            _date = date.getDate(),
            shouldChangeContent = isDay && dates.includes(_date),
            randomEmoji = emoji[Math.floor(Math.random() * emoji.length)];
    
        return {
            html: shouldChangeContent ? randomEmoji : undefined,
            classes: shouldChangeContent ? '-emoji-cell-' : undefined,
            attrs: {
                title: shouldChangeContent ? randomEmoji : ''
            }
        }
    },
    
    // Select 10th day of the month
    selectedDates: new Date(today.getFullYear(), today.getMonth(), 10)
});
.-emoji-cell- {
    --adp-cell-background-color-selected: #ffb8ff;
    --adp-cell-background-color-selected-hover: #fda5fd;
}

Изменение заголовков

В Air Datepicker есть возможность изменять подписи в навигации календаря. Можно использовать как статические варианты, так и динамические - передав функцию в соответствующую опцию. Вы можете использовать как html тэги, так и специальные токены для форматирования их в дату.

Статичный заголовок

new AirDatepicker('#el', {
    navTitles: {
        days: '<strong>yyyy</strong> <i>MMMM</i>',
        months: 'Select month of <strong>yyyy</strong>'    
    }
})

Динамический заголовок

new AirDatepicker('#el', {
    navTitles: {
        days(dp) {
            if (dp.selectedDates.length) {
                let date = dp.selectedDates[0];
                return `<small>
                   Вы выбрали  ${dp.formatDate(date, 'dd MMMM yyyy')}
                </small>`;
            }
            
            return 'Выберите дату';
        }
    }
})

Добавление кнопок

Для удобства выбора конкретной даты, или для очистки выбранных данных можно добавить кнопки в тело календаря. Вы можете добавить одну из предустановленных кнопок или же создать свою. Подробнее можно почитать в в разделе документации.

Предустановленные кнопки

Для добавления кнопок воспользуйтесь опцией buttons - она принимает массив строк или массив объектов с описанием кнопки.

new AirDatepicker('#el', {
    buttons: ['today', 'clear']
})

Создание своих кнопок

Для создания своих кнопок нужно передать структуру, описывающую контент кнопки и ее поведение. Давайте создадим кнопку, которая включает и выключает модуль выбора времени:

new AirDatepicker('#el', {
    buttons: [
        {
            content(dp) {
                return dp.opts.timepicker 
                    ? 'Выключить выбор времени'
                    : 'Включить выбор времени'
            },
            onClick(dp) {
                let viewDate = dp.viewDate;
                let today = new Date();
                
                // Since timepicker takes initial time from 'viewDate', set up time here, 
                // otherwise time will be equal to 00:00 if user navigated through datepicker
                viewDate.setHours(today.getHours());
                viewDate.setMinutes(today.getMinutes());

                dp.update({
                    timepicker: !dp.opts.timepicker,
                    viewDate
                })
            }
        }
    ]
})