15 июня 2016 в 01:45

jQuery UI Datepicker — добавление возможности выбора нескольких дат на одном календаре

image Всем привет, дорогие читатели Хабра!

Статья посвящена jQuery UI и его виджету выбора дат.

Часто бывает, что на странице необходимо сделать выбор периода дат (а иногда даже нескольких разрозненных дат). Но Datepicker от jQuery UI позволяет выбирать только одну дату в пределах одного календаря.

Поэтому частым решением на практике является создание двух полей ввода с контролем по типу «от и до». Также можно найти много «костыльных» способов для решения данной задачи — это нам не подходит.

Итак, наша цель — решить задачу самыми минимальными усилиями используя только jQuery UI Datepicker.

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

Для тех, кому не принципиально использовать стандартный виджет $.datepicker(), я приготовил пару ссылок, надеюсь вы также сочтете их полезными:

— Статья о PickMeUp на хабре (выбор нескольких дат, выбор периода).
— Прекрасный плагин DateTimePicker от XDSoft (выбор периода дат, возможность выбора времени и другие разнообразные фичи), стоит посмотреть

Есть и другие решения, но я не буду на них останавливаться. Если у вас есть свои любимые календари выбора дат, буду рад прочитать о них в комментариях к статье.

Описание расширения


Расширение представляет собой файл, который расширяет возможности виджета $.datepicker(), используя его объектную модель. Не влияет на работоспособность Datepicker в дефолтном режиме. Поэтому не стоит беспокоиться о том, что ваш (уже написанный) код перестанет работать или начнет функционировать иначе.

Расширение позволяет изменить поведение выбора даты в двух режимах:
  • Выбор периода (две даты: начало и окончание периода)
  • Выбор нескольких дат (массив дат)

Так как расширение планируется использовать для выбора нескольких дат, то рекомендую его применять к элементу DIV (а не INPUT), а при выборе дат заполнять соответствующие значения в поля ввода (см. примеры в конце статьи).

Новые возможности виджета


Новые параметры $.datepicker()

$('#date_range').datepicker({
  range: 'period', // возможные значения: period, multiple
  range_multiple_max: 3, // максимальное число выбранных дат в режиме "Несколько дат"
  onSelect: function(dateText, inst, extensionRange) {
    // extensionRange - добавлен возвращаемый аргумент, содержит в себе объект расширения
  }
});

// Метод "setDate" теперь может принимать массив: 2 элемента при range="period" или более элементов при range="multiple" 
// $('#date_range').datepicker('setDate', ['+2d', '+1w']);

// рекомендуется использовать событие "onSelect" для изменение значений полей формы (или переменых вашего скрипта)
// однако для более гибкого управления, можно получить объект расширения и работать с информацией о выбранных датах
var extensionRange = $('#date_range').datepicker('widget').data('datepickerExtensionRange');

console.log(extensionRange.datesText); // массив дат (дата в формате, использующимся в datepicker)
console.log(extensionRange.startDateText); // начало периода (дата в формате, использующимся в datepicker)
console.log(extensionRange.endDateText); // окончание периода (дата в формате, использующимся в datepicker)

console.log(extensionRange.dates); // массив дат (объект даты)
console.log(extensionRange.startDate); // начало периода (объект даты)
console.log(extensionRange.endDate); // окончание периода (объект даты)

Новые стили у ячеек календаря

.selected{} /* выбранныя дата */
.selected-start{} /* первая дата периода */
.selected-end{} /* последняя дата периода */
.first-of-month{} /* первая дата месяца */
.last-of-month{} /* последняя дата месяца */

Пример 1 — выбор периода
Пример 2 — выбор нескольких дат
Пример 3 — режим popup

Скачать — jquery.datepicker.extension.range.min.js
подключать необходимо сразу после скриптов jQuery UI
требуется оригинальный виджет Datepicker jQuery UI
Артем @Artemeey
карма
18,0
рейтинг 0,0
PHP разработчик
Похожие публикации
Самое читаемое Разработка

Комментарии (21)

  • +9
    Закопайте это обратно, пожалуйста
    • +1
      Не понимаю, чем вам не нравится решение использовать datepicker для выбора промежутков дат?
      Посоветуйте, пожалуйста, другое решение для datepicker, если знаете.
      • +6
        Да ради бога, используйте. Я не витаю в облаках, и понимаю, что кому-то приходится поддерживать старье на jQ UI. Но я не понимаю, почему вы и другие люди не прикладывают усилий закопать это страшное наследие куда подальше. jQ UI был страшным и ужасным еще с самого выхода. Какие-то бесконечные зависимости с непозволительным для тех времен размером, страшный дизайн, ограниченный функционал, и лишь имя jQuery принесло ему какую-то славу. В современном мире, когда есть множество компонентов на нативном js, компонентов для Reactjs, да тот же Angular UI, использование jQ UI кажется просто абсурдом. Да даже не абсурдом, а скорее кажется какой-то безнадежностью, когда человек перестает следить за современными альтернативами и просто застревает на своем уровне, используя устаревшие инструменты, но такие для себя комфортные.
        Единственная вещь которая оправдывает ваш поступок, это если вам пришлось в древний проект быстро и бюджетно добавить такой функционал, ничего не ломая. Но даже это не оправдывает этой статьи, которой не место, даже не то чтобы на хабре, а просто в современном мире. Выложили бы себе спокойно на гитхаб и жили бы спокойно. Не надо понапрасну беспокоить призраков.
        • +2
          Спасибо за развернутый ответ. Действительно дизайн jQuery UI ужасен. Но его дизайн совсем не нужно использовать в реальных проектах. Что касается новых разработок, то если разобраться, то тот же Angular UI решает иные задачи и иногда работает в связке с jQuery UI (может быт это и плохо, не уверен, на официальном сайте Angular UI представлены модули с использованием jQuery UI). Вероятно дело в том, что jQuery UI это исключительно набор инструментов для решения типовых задач. Это не фреймворк и сравнивать его с Angular (полноценным фреймворком) или Reactjs (языком шаблонов) некорректно. Конечно же, эта статья написана исключительно для тех, кто использует соответствующий плагин (виджет). Практически всегда желательно использовать тот плагин, который официально поддерживается вашим фреймворком.

          Вот один из примеров модуля Angular, основанного на том же jQuery UI — https://angular-ui.github.io/ui-sortable/
          • 0
            Да я и не сравнивал, я привел альтернативы и указал явно, что я говорю про компоненты и библиотеку angular ui, про то что angular или react сами по себе замена jq ui — такого я не говорил.
            Да у angular ui есть какие-то компоненты с использованием jq ui, это в целом нормально, но и альтернатив этим компонентам тоже много, так что никто не принуждает и не заставляет.
            Кстати, можете посмотреть в сторону extjs, если так важна единая экосистема для специфичного приложения. Но я все таки за что-то более приближенное к народу.
            • 0
              библиотеку angular ui


              С этим вы сильно мимо и дело даже не в том что там обычно тот же самый jquery ui, а в том идеология прямого манипулирования dom-ом (=jquery) идет в разрез с angular-овской, поэтому чтобы всё было красиво приходится заворачивать нужные jquery методы (=всё что напрямую изменяет dom или не соответствует идеологии) в angular-директивы, angular ui именно это и делает (т.е. без самого angular-а оно бесполезно). Кроме того, назначение самого angular-а совсем не в том чтобы выводить отдельные элементы UI. Т.е. оно в принципе не совместимо с "классическими" сайтами.
        • +2
          А какой смысл пихать «современные альтернативы» в те места, где фронтенда на сайте кот наплакал? Какой смысл пихать ангуляр и реакт туда, где поддержка нужна дешевая, а jQuery UI все и так знают? Какой смысл трястись над размером jQuey UI, если вы используя вместо него тот же clndr.js увеличите размер скриптов примерно на столько же? В угоду вашему чувству прекрасного? Так оно в списке контрагентов не фигурирует.
        • +1
          По своему опыту могу сказать, что мы перешли с отдельных компонентов (datepicker.js + date.js + sselect.js + стили для этого всего) на JQ UI скомилированный только с datepicker-ом и селектами, тк в сумме это весит меньше чем все старые компоненты вместе взятые + управлять всем этим стало гораздо удобнее. Дизайн JQ UI мы делаем свой, тк он очень простой и тянуть стандартную тему совсем нет нужды.
      • 0
        Меня в jQuery UI смущает в основном размер библиотек, которые нужно тащить с собой ради махонькой функции, которую придётся ещё и дополнять. Как временное решение или как довесок к уже имеющемуся парку аттракционов с jQuery UI, но без выбиралки дат — более-менее вариант, но легко ж гуглятся решения вообще без зависимостей и много их.
      • 0
        • +1
          Прекрасный совет, вы им сами пользовались в хоть сколько-то сложной логике? Неделю назад выбросили это чудо из проекта и заменил на jQueryUI datepicker, который что бы про него не говорили имеет одно небольшое преимущество — он отлично работает.
          А все эти на коленке написанные дейтпикеры содержат десятки багов и недоработок с которыми не справиться без изменения исходников.
          П.С. это относится и комментатору выше, советующему новомодные штуковины
        • –1
        • +1
          Супер, то есть вы советуете тянуть весь бутстрап ради пикера?
  • 0

    А не понравилось — в самый раз для древнего проекта где как раз два отдельных поля :) Правда вместо самого файла хотелось бы видеть нормальный репозиторий из которого можно заинсталить через bower...

  • 0
    • 0
      Именно для этого виджета и служит расширение, позволяя выбирать на одном календаре сразу две даты и подсвечивать выделенный период.
  • +1
    Пару слов в защиту jquery ui datepicker. Несколько месяцев назад я пытался найти ему замену с обязательным требованием accessibilty или возможность шаблонизации виджета для accessibilty, также изолированной автономностью от библиотек, в том смысле что можно скачать одним файлом архив, где было бы 2-3 файла. Увы и ах, много датепикеров и все они не подходили под эти требования. Единственным оказался этот старичок. Если не прав, то укажите либу.
    • 0
      • 0
        Его рассматривал в первую очередь, но пришлось отказаться из за accessibility и еще забыл указать требование: локализация на русский, у ui с эти все в порядке. Надо сказать что шерстил гугл в посках тщательно, собрал у себя коллекцию датепикеров. Определенно был в большом недоумениии, что в 2016 году нет простых и понятных датепикеров
  • +2
    К слову про другие дейтпикеры. Не каждый имеет возможность задать разный формат даты для показа в UI и для отправки на сервер, приходится добавлять обработку через onchange или changedate. А в данном есть опции altField и altFormat, это удобно.
  • +1
    В интернете встречал много календарей, и в каждом обнаруживались какие-то баги, которые неизвестно когда исправят (то на смартфоне что-то не нажималось, то отображалась криво то еще что-то выскакивало). jQuery в плане работы достаточно стабилен и несложно интегрируется. Этой возможности как раз не хватало. Спасибо, будем пробовать!

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