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
Поделиться с друзьями
-->

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


  1. Evgeny42
    15.06.2016 03:15
    +9

    Закопайте это обратно, пожалуйста


    1. Artemeey
      15.06.2016 03:17
      +1

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


      1. Evgeny42
        15.06.2016 03:33
        +6

        Да ради бога, используйте. Я не витаю в облаках, и понимаю, что кому-то приходится поддерживать старье на jQ UI. Но я не понимаю, почему вы и другие люди не прикладывают усилий закопать это страшное наследие куда подальше. jQ UI был страшным и ужасным еще с самого выхода. Какие-то бесконечные зависимости с непозволительным для тех времен размером, страшный дизайн, ограниченный функционал, и лишь имя jQuery принесло ему какую-то славу. В современном мире, когда есть множество компонентов на нативном js, компонентов для Reactjs, да тот же Angular UI, использование jQ UI кажется просто абсурдом. Да даже не абсурдом, а скорее кажется какой-то безнадежностью, когда человек перестает следить за современными альтернативами и просто застревает на своем уровне, используя устаревшие инструменты, но такие для себя комфортные.
        Единственная вещь которая оправдывает ваш поступок, это если вам пришлось в древний проект быстро и бюджетно добавить такой функционал, ничего не ломая. Но даже это не оправдывает этой статьи, которой не место, даже не то чтобы на хабре, а просто в современном мире. Выложили бы себе спокойно на гитхаб и жили бы спокойно. Не надо понапрасну беспокоить призраков.


        1. Artemeey
          15.06.2016 04:22
          +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/


          1. Evgeny42
            15.06.2016 04:36

            Да я и не сравнивал, я привел альтернативы и указал явно, что я говорю про компоненты и библиотеку angular ui, про то что angular или react сами по себе замена jq ui — такого я не говорил.
            Да у angular ui есть какие-то компоненты с использованием jq ui, это в целом нормально, но и альтернатив этим компонентам тоже много, так что никто не принуждает и не заставляет.
            Кстати, можете посмотреть в сторону extjs, если так важна единая экосистема для специфичного приложения. Но я все таки за что-то более приближенное к народу.


            1. LastDragon
              15.06.2016 09:16

              библиотеку angular ui


              С этим вы сильно мимо и дело даже не в том что там обычно тот же самый jquery ui, а в том идеология прямого манипулирования dom-ом (=jquery) идет в разрез с angular-овской, поэтому чтобы всё было красиво приходится заворачивать нужные jquery методы (=всё что напрямую изменяет dom или не соответствует идеологии) в angular-директивы, angular ui именно это и делает (т.е. без самого angular-а оно бесполезно). Кроме того, назначение самого angular-а совсем не в том чтобы выводить отдельные элементы UI. Т.е. оно в принципе не совместимо с "классическими" сайтами.


        1. PerlPower
          15.06.2016 12:09
          +2

          А какой смысл пихать «современные альтернативы» в те места, где фронтенда на сайте кот наплакал? Какой смысл пихать ангуляр и реакт туда, где поддержка нужна дешевая, а jQuery UI все и так знают? Какой смысл трястись над размером jQuey UI, если вы используя вместо него тот же clndr.js увеличите размер скриптов примерно на столько же? В угоду вашему чувству прекрасного? Так оно в списке контрагентов не фигурирует.


        1. simpel
          16.06.2016 23:21
          +1

          По своему опыту могу сказать, что мы перешли с отдельных компонентов (datepicker.js + date.js + sselect.js + стили для этого всего) на JQ UI скомилированный только с datepicker-ом и селектами, тк в сумме это весит меньше чем все старые компоненты вместе взятые + управлять всем этим стало гораздо удобнее. Дизайн JQ UI мы делаем свой, тк он очень простой и тянуть стандартную тему совсем нет нужды.


      1. Denai
        15.06.2016 04:51

        Меня в jQuery UI смущает в основном размер библиотек, которые нужно тащить с собой ради махонькой функции, которую придётся ещё и дополнять. Как временное решение или как довесок к уже имеющемуся парку аттракционов с jQuery UI, но без выбиралки дат — более-менее вариант, но легко ж гуглятся решения вообще без зависимостей и много их.


      1. vtrushin
        15.06.2016 14:37

        1. Skull
          15.06.2016 15:31
          +1

          Прекрасный совет, вы им сами пользовались в хоть сколько-то сложной логике? Неделю назад выбросили это чудо из проекта и заменил на jQueryUI datepicker, который что бы про него не говорили имеет одно небольшое преимущество — он отлично работает.
          А все эти на коленке написанные дейтпикеры содержат десятки багов и недоработок с которыми не справиться без изменения исходников.
          П.С. это относится и комментатору выше, советующему новомодные штуковины



        1. DenimTornado
          15.06.2016 20:45
          +1

          Супер, то есть вы советуете тянуть весь бутстрап ради пикера?


  1. LastDragon
    15.06.2016 09:01

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


  1. tarpedo
    15.06.2016 10:20

    1. Artemeey
      15.06.2016 10:22

      Именно для этого виджета и служит расширение, позволяя выбирать на одном календаре сразу две даты и подсвечивать выделенный период.


  1. lavkasnov
    15.06.2016 11:03
    +1

    Пару слов в защиту jquery ui datepicker. Несколько месяцев назад я пытался найти ему замену с обязательным требованием accessibilty или возможность шаблонизации виджета для accessibilty, также изолированной автономностью от библиотек, в том смысле что можно скачать одним файлом архив, где было бы 2-3 файла. Увы и ах, много датепикеров и все они не подходили под эти требования. Единственным оказался этот старичок. Если не прав, то укажите либу.


    1. ilyaplot
      15.06.2016 12:31

      1. lavkasnov
        15.06.2016 12:39

        Его рассматривал в первую очередь, но пришлось отказаться из за accessibility и еще забыл указать требование: локализация на русский, у ui с эти все в порядке. Надо сказать что шерстил гугл в посках тщательно, собрал у себя коллекцию датепикеров. Определенно был в большом недоумениии, что в 2016 году нет простых и понятных датепикеров


  1. michael_vostrikov
    15.06.2016 18:47
    +2

    К слову про другие дейтпикеры. Не каждый имеет возможность задать разный формат даты для показа в UI и для отправки на сервер, приходится добавлять обработку через onchange или changedate. А в данном есть опции altField и altFormat, это удобно.


  1. Atamovich
    16.06.2016 11:53
    +1

    В интернете встречал много календарей, и в каждом обнаруживались какие-то баги, которые неизвестно когда исправят (то на смартфоне что-то не нажималось, то отображалась криво то еще что-то выскакивало). jQuery в плане работы достаточно стабилен и несложно интегрируется. Этой возможности как раз не хватало. Спасибо, будем пробовать!