Для очередного проекта понадобился виджет для выбора даты. Очевидным, по крайней мере для меня, решением было jQuery UI Datepicker
. Но когда позже понадобилось выбирать не одну дату, а диапазон, я попал в тупик. В API не было ни какого упоминания о такой возможности. Поисковики все как один выдавали какие-то «самоделки» далеко не первой свежести.
Копнув глубже исходники Datepicker, я все-таки обнаружил возможность выбора диапазона. Реализуется все логика через событие «onSelect».
У экземпляра Datepicker есть флаг stayOpen
. Если его установить внутри события, то календарь не закроется после клика, а занесет выбранную дату в поле rangeStart
и позволит выбрать еще дату. Когда будет выбран конец диапазона, нужно сбросить флаг stayOpen
и обновить содержимое текстового поля.
Внимание! Плагин актуален только для jQuery UI 1.7.x. Для последних версий нужно использовать другую редакцию этого плагина.
(function ($) {
$.fn.daterange = function () {
// опции
var opts = $.extend({
"dateFormat": "dd.mm.yy",
"changeMonth": false,
"changeYear": false,
"numberOfMonths": 2,
"rangeSeparator": "-"
}, arguments[0] || {}, {
// обработчики событий datepicker
// закрытие
"onClose": function (dateText, inst) {
if ($.isFunction(opts.callback)) {
opts.callback.apply(this, arguments);
}
},
// выбор даты
"onSelect": function (dateText, inst) {
var textStart;
if (!inst.rangeStart) {
inst.stayOpen = true;
} else {
inst.stayOpen = false;
textStart = $.datepicker.formatDate(opts.dateFormat, inst.rangeStart);
if (textStart !== dateText) {
$(this).val(textStart + " " +
opts.rangeSeparator + " " + dateText);
}
}
}
});
return this.each(function () {
var input = $(this);
if (input.is("input")) {
input.datepicker(opts);
}
});
};
}(jQuery));
Еще одно событие, которое может пригодиться, это «onClose». Оно будет сгенерировано в момент закрытия календаря. В плагине я просто делегирую все исполнение внешнему обработчику, но на практике мне удобно было добавить туда больше функционала.
Плагин может быть проинициализирован любыми параметрами
, которые используются в Datepicker. Так как обработчик события «onClose» переопределяется, то вместо него используется поле callback.
Второе дыхание
Обновлено 2013-06-19
Для последних версий jQuery UI вместо stayOpen
нужно использовать флаг inline
. Однако это только запретит календарю закрыться. Нужно ещё позаботиться о сохранении первой выбранной даты.
(function ($) {
$.fn.daterange = function () {
// опции
var opts = $.extend({
"dateFormat": "dd.mm.yy",
"changeMonth": false,
"changeYear": false,
"numberOfMonths": 2,
"rangeSeparator": "-"
}, arguments[0] || {}, {
// обработчики событий datepicker
// закрытие
"onClose": function (dateText, inst) {
if ($.isFunction(opts.callback)) {
opts.callback.apply(this, arguments);
}
},
// выбор даты
"onSelect": function (dateText, inst) {
var textStart;
if (!inst.rangeStart) {
inst.inline = true;
inst.rangeStart = dateText;
} else {
inst.inline = false;
textStart = inst.rangeStart;
if (textStart !== dateText) {
$(this).val(textStart + " " +
opts.rangeSeparator + " " + dateText);
inst.rangeStart = null;
}
}
}
});
return this.each(function () {
var input = $(this);
if (input.is("input")) {
input.datepicker(opts);
}
});
};
}(jQuery));