Зачем нужны datepicker'ы? Ясно, что нормальному пользователю не влом набрать дату цифрами с клавиатуры. Но заказчики сайтов требуют для будущих посетителей всё больше и больше "удобств". Вот и появляются на свет всякие инструменты для тыканья мышкой...

Календарь javascript (datepicker)

В сети полно чудовищных скриптов для наглядного выбора даты с помощью указателя мыши. Эти скрипты не могут быть не чудовищными по определению, так как созданы для позорной задачи: облегчить жизнь пользователям, не желающим набирать даты цифрами, с клавиатуры. Ну, и программистам, в общем, тоже – чтоб не встать в ступор от введённой с точками даты ("15.06.2011"), когда серверный скрипт знает только чёрточки ("15-06-2011").

Долго я не хотел заниматься этим datepicker'ом. Но клиенты задолбали, и вот наступило "а придётся". Ну, как я уже сказал в начале (не удержался), готовые скрипты в сети в большинстве своём оказались чудовищны. Календарь jQuery, наиболее полный по функционалу, был отбракован из-за чудовищности самой jQuery (ничего личного! :-)). То же и по другим библиотекам – религия не позволяет мне загружать сайты клиентов сотнями килобайт лишнего кода, когда можно обойтись парой сотен строк.

Календарь, о котором речь, – как раз такой случай: весь код занимает немногим более 200 строк (7 К). Вот дистрибутив: calendar_ir2.zip, для работы нужны файлы calendar.js и calendar.css (calendar.htm – для примера).

Подключение

1. Добавить к HEAD HTML-страницы две строчки:

2. Полям ввода (input), в которые надо вставлять даты, назначить класс "date" (<input name='' class='date'>)

Алгоритмы

Массив календаря (месяцы, даты и дни недели) создаётся на один год. При загрузке – на текущий год, при выборе года – на выбранный год.

При щелчке по полю ввода (гм... и при активации с помощью Tab тоже) отрисовывается календарь на месяц. Помещается над полем ввода (если есть место) или под полем ввода (если сверху места не хватает, или если позицию клика определить нельзя).

По умолчанию отрисовывается текущий месяц, при выборе месяца – выбранный месяц.

При щелчке по дате дата вставляется в поле ввода. При потере фокуса полем ввода календар исчезает. При нажатии escape – тоже исчезает.

Объект календаря не цепляется к полям ввода – к ним цепляется только onclick, по которому отрисовывается календарь – по умолчанию (текущий год и месяц) или, если дата была выбрана, месяц и год выбранной даты.

В объект window.dict.calendar можно помещать две вещи:

1) разделитель даты (например, чёрточку или точку): dict.calendar.div = '.';

2) массив знаменательных дат и праздников (можно присылать его с сервера):

Знаменательные даты из массива отлавливаются при создании объекта календаря и соответствующие числа помечаются ма-аленькой красненькой меткой, лежащей в папке дистрибутива img, а также датам добавляется title с названием праздника.

Ну, что ещё... Вся локализация определяется в объекте lang внутри функции календаря: формат даты (d-m-Y), названия дней недели, начало недели (понедельник)... Это всё легко можно заменить на чужие реалии. Но зачем?

Рабочий пример: http://ir2.ru/static/calendar.htm

D.M., admin

Комментарии

Леонид 14.05.2015 21:12:10

Простите, может не все внимательно прочитал, но не нашел ответ на такой вопрос. Я с JS не дружу. Но календарь понравился и при использовании его много плюсов, но есть проблема. Если дата выбирается из календаря, то при повторном смены даты в этом поле календарь показывает ту дату, которая была выставлена, а вот если в поле даты уже была вписана дата ранее (другим способом), то при смене, календарь открывается не на ту дату, которая была в поле, а на текущую. Как сделать, чтобы дата в календаре открывалась та, которая уже была записана в этом поле? Особенно неудобно, когда нужно снова выбирать месяц и год. Заранее спасибо.

Дилетант 07.05.2015 01:01:03

funnybunny, уточняю: initCalendar(null, el) – null – это событие браузера (которого в данном случае нет)

Дилетант 07.05.2015 00:44:53

funnybunny, если вы создаёте объекты на javascript, то вызывать функцию initCalendar можно из любого созданного вами объекта – просто написать где-нибудь в середине кода волшебное слово initCalendar(el), где el – это html-элемент input, к которому следует привязать календарь

funnybunny 25.04.2015 13:20:16

Дилетант, Подскажите, initCalendar из какого объекта вызывать?

Дилетант 24.04.2015 13:58:09

Василий, надо назначать события для Body с помощью функции addLoadEvent (а не просто писать body.onload=...)

Дилетант 24.04.2015 13:55:41

funnybunny, надо допиливать руками: пробежаться в цикле по нужным элементам (инпутам) и для каждого элемента вызвать функцию initCalendar(null, el), где el – текущий элемент, к которому надо привязать Календарь

Дилетант 24.04.2015 13:52:54

EURO_KOLYAN, да, можно такой тип свободной лицензии использовать (как бы неявно предполагается из контекста статьи)

funnybunny 23.04.2015 15:02:20

Подскажите, пожалуйста, как этот datepicker к динамически создаваемым элементам привязывать: – если в html прописать – работает; – если элемент по js событию создается – нет

EURO_KOLYAN 21.03.2015 09:42:51

какой тип лицензии в дипломе прописать на использование этого календарика?? GNU LESSER GENERAL PUBLIC LICENSE ?

Пахан 28.10.2014 00:53:05

После перехода на зимнее время перестал работать календарь, на компе где не установлен апдэйт KB2998527 – все отображается нормально!

Хрен 27.10.2014 23:54:28

Перестал работать!!!

Ванька 19.02.2014 06:56:28

Тезка! Благодарю за простой и дельный код. Сам лично стараюсь уйти от загрузки лишних кодов без исключительной надобности, и уж тем более библиотек типа jQuery.

Василий 14.11.2013 03:38:07

D.M., admin Большое спасибо, давно искал что-то подобное. Но вот вопрос: если для body страницы назначено событие onload, то календарь не отображается. Убираем onload – и всё опять работает хорошо. Пробовал в нескольких браузерах – эффект один и тот же.

Андрей 16.09.2013 17:04:56

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

Дилетант 21.09.2013 00:12:37

passer-by,

не надо в тэге писать onClick='functionName()', в современных сайтах так редко делают. Это называется "ненавязчивый javascript" – поищите в Яндексе эту фразу.

Дилетант 21.09.2013 00:16:16

Андрей,

это ж столет назад писалось, я уже не помню. На первый взгляд, в файле calendar.js есть параметр:

year_offset = 5

А начальный год, видимо, текущий. Надо найти его в коде и заменить на любой другой.

passer-by 11.09.2013 02:54:30

Так как JS я знаю не очень хорошо, пока не разобрался что заставляет появиться календарь при нажатии на <input>. Из того что видел раньше в теге input писали обычно onClick='functionName()'. А здесь ничего подобного нет. Проясните плиз. Такое ощущение, что при загрузке страницы в память также грузится файл calendar.js...

Дилетант 14.05.2013 02:41:58

Serj, минус перед функцией, чтобы она сразу выполнилась (немедленно после загрузки) и исчезла из памяти (ну, кроме глобальных переменных). Читайте об этом подробнее на сайте javascript.ru

Сергей 03.05.2013 01:43:28

Спасибо. То, что надо. Свистелки и перделки фтопку.

Serj 16.04.2013 19:48:16

В файле calendar.js на 15 строке: "-function ()", за чем минус перед функцией и почему без него ни чего не работает?))) спасибо.

Доброволец 27.03.2013 18:25:11

Для неКодер и Пчеловод

Чтобы "левые" строки не добавлялись в список месяцев, можно добавить в функцию buildField после строки

for (id in idxs) {

строку

if (!idxs.hasOwnProperty(id)) continue;

Доброволец 27.03.2013 18:21:24

Отличный календарь, спасибо

неКодер 07.03.2013 05:03:09

to Пчеловод Я чтобы долго не разбираться, тупо и программистски некрасиво ограничил формирование списка элементов 12тью элементами (см. ф-цию buildField) var i=0; for (id in idxs) { if(i < 12){params = {value:id} ac(buildEl2('option', params, idxs[id]), el)} i++ }

Пчеловод 27.01.2013 04:13:50

А можно ка-то подружить календарь с Mootools? При использовании на странице в подключенным mootools в список месяцев добавляется несколько строк с определением функций на JS.

serjcat 27.12.2012 00:17:34

Вариант календаря на jquery divhack.com/node/76 =)

-- фтопку жикверь

Дилетант 09.11.2012 22:50:20

Да ничего страшного. Где уж там "резковато". Посмотрите, как отвечают на каком-нибудь phpclub.ru.

Ярослав, а выбор времени – это как? выпадающий список из 60-ти минут?..

Трофим 09.11.2012 00:06:10

Возможно, я несколько резковато ответил, Дилетант. Не обижайтесь. Спасибо за подсказку. Что касается подсчета количества дней, постараюсь эту задачу реализовать на JS. Негоже по всякой мелочевке гонять на сервер. Относительно остальных задач, есть один сайт, где это можно подсмотреть. Просто пока руки не дошли до анализа.

Ярослав 08.11.2012 06:59:10

Спасибо за отличный и простой скрипт.

было бы не плохо сделать выбор времени)

Дилетант 08.11.2012 02:49:39

Trofim, почём вы знаете, что я не разработчик. Это ведь бывает очень по-разному. Сегодня вы лицо официальное, а завтра, глядишь, и совсем наоборот...

Скрипт подсчёта дней есть здесь на php: http://ir2.ru/static/Propis.php (описание функции time-diff: propis.aspx). Если надо именно на js, посмотрите на форуме http://javascript.ru/forum/, там, где-то в разделе "Готовые решения" я видел.

Trofim 03.11.2012 00:02:16

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

Дилетант 02.11.2012 17:41:28

Trofim, я бы сказал, что это, скорее, ошибка. Такие вещи обычно рассчитывают на стороне сервера, используя информацию, хранимую в БД. Потому что там слишком много параметров. А если надо отображать результаты вычислений без перезагрузки страницы, то использовать ajax.

Дилетант 28.10.2012 17:17:24

Alex,

там где-то в начале кода есть объект lang, а в нём функция makeDate. Это зачаток мультиязычности. Чтобы вырастить его в норм. дерево, надо удалить текст функции, написать там взамен: "makeDate: [Имя_моей_функции]", ну, а уже в своей функции вы можете определять какой угодно формат вывода даты.

Да. А лучше, конечно, весь объект lang определять снаружи Календаря (его вообще можно присылать с сервера).

Trofim 31.10.2012 11:00:26

Наверное, хамство с моей сторны, но нельзя ли выложить код с кнопкой (количество дней), при нажатии на которую выдавалось бы количество дней в выбранном интервале. Про подсчет стоимости за выбранный период и выбор валюты расчета я вообще молчу. Такая вещь может пригодиться на сайте гостиницы. Чтобы посетитель мог на странице прикинуть стоимость проживания.

лесник 23.10.2012 19:35:54

Андрей,

Календарь не стоит на месте, ему требуются всё новые и новые настройки, здесь я их не меняю (использую новые наработки на рабочих сайтах). Вот, попытался выдрать последнюю версию, выкладываю: http://ir2.ru/static/calendar2.htm

Alex 24.10.2012 00:20:40

А как вывести дату в новой версии в формате YYYY-MM-DD ?

Андрей 14.10.2012 07:44:50

Так! А как сделать чтобы календарь при клике на поле ввода считывал дату и отображал уже выделенную дату? К примеру если я вручную сразу задаю поля или потом изменяю, то после клика текущей дате календарь отображает по умолчанию (текущий год и месяц). Доработайте плиз :)

АндрейТ 27.09.2012 03:08:03

Спасибо, довно искал такой простой скрипт календаря.

лесник 11.09.2012 19:18:57

Саша, вроде бы, даже Яндекс пока не придумал, как ленивому пользователю найти информацию чисто тычками мыши (совсем без клавиатуры). Я лишь немного задел эту тему (чтоб с чего-то начать разговор). Ну, полемически преувеличил...

Саша 04.09.2012 00:32:30

"Зачем нужны datepicker'ы? Ясно, что нормальному пользователю не влом набрать дату цифрами с клавиатуры."

Интересная логика, однако. А зачем тогда вообще делать сайты? Ясно ведь, что нормальному пользователю не влом до всего на свете додуматься самому, и все сделать своими руками. А мы только время зря тратим.

лесник 08.08.2012 17:55:22

Роман,

календарь закрывается по клавише Esc. Видимо, на вашем железе виртуальная клавиатура закрывается с помощью того же кода. Можно убрать из кода календаря одну строчку, и он не будет закрываться по "коду 27" – Esc. Найдите там у себя эту строчку и удалите её:

if (27 == e.keyCode) {hidTemp()}

Роман 31.07.2012 06:18:50

Все здорово! Одна проблема, если смотришь сайт с IPAD, при установке фокуса в поле выскакивает виртуальная клавиатура, которая в режиме ландшафт перекрывает календарь. Если ее закрыть, закрывается и календарь. Можно это как-то побороть?

mr.ivannn 22.07.2012 02:52:25

Супер! Спс!

лесник 21.02.2012 20:15:10

Ваня, а то ж! Это всё Пыхе спасибо (http://pyha.ru/), там помогли отладить работу скрипта.

Ваня 20.02.2012 21:41:42

Отличная работа! Как раз искал календарь с минимумом кода. И подключение простейшее, и код несложно подправить под себя.