Диапазон выбора даты на jQuery пользовательского интерфейса управления datepicker
Я создал выбор диапазона дат с помощью jQuery ui, где вы можете использовать один и тот же встроенный календарь для выбора даты.
смотрите мою скрипку здесь:http://jsfiddle.net/kVsbq/4/
JS
$(".datepicker").datepicker({
minDate: 0,
numberOfMonths: [12, 1],
beforeShowDay: function (date) {
var date1 = $.datepicker.parseDate($.datepicker._defaults.dateFormat, $("#input1").val());
var date2 = $.datepicker.parseDate($.datepicker._defaults.dateFormat, $("#input2").val());
return [true, date1 && ((date.getTime() == date1.getTime()) || (date2 && date >= date1 && date <= date2)) ? "dp-highlight" : ""];
},
onSelect: function (dateText, inst) {
var date1 = $.datepicker.parseDate($.datepicker._defaults.dateFormat, $("#input1").val());
var date2 = $.datepicker.parseDate($.datepicker._defaults.dateFormat, $("#input2").val());
if (!date1 || date2) {
$("#input1").val(dateText);
$("#input2").val("");
$(this).datepicker();
} else {
$("#input2").val(dateText);
$(this).datepicker();
}
}
});
то, что я хочу сделать, это селектор диапазона, как это:http://jsfiddle.net/D3wLX/1/
если выбрать более раннюю дату, то более ранняя дата автоматически становится первой датой в диапазоне и средние даты выделены. Прямо сейчас в моем оригинальном решении jQuery ui он просто поместит более раннюю дату во второй ввод и не выделит даты между ними.
7 ответов
ваш сценарий был именно тем, что я искал. Я раздвоил твою оригинальную скрипку и сделал лишь небольшую поправку к твоему выбору, чтобы заставить ее работать так, как ты хотел.
onSelect: function(dateText, inst) {
var date1 = $.datepicker.parseDate($.datepicker._defaults.dateFormat, $("#input1").val());
var date2 = $.datepicker.parseDate($.datepicker._defaults.dateFormat, $("#input2").val());
var selectedDate = $.datepicker.parseDate($.datepicker._defaults.dateFormat, dateText);
if (!date1 || date2) {
$("#input1").val(dateText);
$("#input2").val("");
$(this).datepicker();
} else if( selectedDate < date1 ) {
$("#input2").val( $("#input1").val() );
$("#input1").val( dateText );
$(this).datepicker();
} else {
$("#input2").val(dateText);
$(this).datepicker();
}
}
то, что отсутствовало в исходном разделе, было просто проверкой для сравнения текущего выбранного значения даты с тем, которое уже было захвачено.
вот моя раздвоенная скрипка: http://jsfiddle.net/sWbfk/
Я нашел ответ здесь:
http://www.benknowscode.com/2012/11/selecting-ranges-jquery-ui-datepicker.html
большой учебник
$.datepicker._defaults.onAfterUpdate = null;
var datepicker__updateDatepicker = $.datepicker._updateDatepicker;
$.datepicker._updateDatepicker = function( inst ) {
datepicker__updateDatepicker.call( this, inst );
var onAfterUpdate = this._get(inst, 'onAfterUpdate');
if (onAfterUpdate)
onAfterUpdate.apply((inst.input ? inst.input[0] : null),
[(inst.input ? inst.input.val() : ''), inst]);
}
$(function() {
var cur = -1, prv = -1;
$('#jrange div')
.datepicker({
//numberOfMonths: 3,
changeMonth: true,
changeYear: true,
showButtonPanel: true,
beforeShowDay: function ( date ) {
return [true, ( (date.getTime() >= Math.min(prv, cur) && date.getTime() <= Math.max(prv, cur)) ? 'date-range-selected' : '')];
},
onSelect: function ( dateText, inst ) {
var d1, d2;
prv = cur;
cur = (new Date(inst.selectedYear, inst.selectedMonth, inst.selectedDay)).getTime();
if ( prv == -1 || prv == cur ) {
prv = cur;
$('#jrange input').val( dateText );
} else {
d1 = $.datepicker.formatDate( 'mm/dd/yy', new Date(Math.min(prv,cur)), {} );
d2 = $.datepicker.formatDate( 'mm/dd/yy', new Date(Math.max(prv,cur)), {} );
$('#jrange input').val( d1+' - '+d2 );
}
},
onChangeMonthYear: function ( year, month, inst ) {
//prv = cur = -1;
},
onAfterUpdate: function ( inst ) {
$('<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" data-handler="hide" data-event="click">Done</button>')
.appendTo($('#jrange div .ui-datepicker-buttonpane'))
.on('click', function () { $('#jrange div').hide(); });
}
})
.position({
my: 'left top',
at: 'left bottom',
of: $('#jrange input')
})
.hide();
$('#jrange input').on('focus', function (e) {
var v = this.value,
d;
try {
if ( v.indexOf(' - ') > -1 ) {
d = v.split(' - ');
prv = $.datepicker.parseDate( 'mm/dd/yy', d[0] ).getTime();
cur = $.datepicker.parseDate( 'mm/dd/yy', d[1] ).getTime();
} else if ( v.length > 0 ) {
prv = cur = $.datepicker.parseDate( 'mm/dd/yy', v ).getTime();
}
} catch ( e ) {
cur = prv = -1;
}
if ( cur > -1 )
$('#jrange div').datepicker('setDate', new Date(cur));
$('#jrange div').datepicker('refresh').show();
});
});
.wrapper {
height: 600px;
}
#jrange input {
width: 200px;
}
#jrange div {
font-size: 9pt;
}
.date-range-selected > .ui-state-active,
.date-range-selected > .ui-state-default {
background: none;
background-color: lightsteelblue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div class="wrapper">
<div id="jrange" class="dates">
<input />
<div></div>
</div>
</div>
чувак, твой код-это то, что мне нужно!
и с исправлением Джейми Лейна я решил использовать его для создания плагина.
вот ссылка для jsfiddle:http://jsfiddle.net/dxLRm/35/ (ссылка обновлена 2014/01/01)
Так как я должен показать некоторый код, вот что у меня есть:
(function ($) {
$.prototype.rangedatepicker = function (o,x,y) {
var dp = $.datepicker,
cl = dp.markerClassName,
di = 'data-rdp-i',
df = 'data-rdp-f';
switch(o)
{
case 'option':
return $(this).datepicker('option');
case 'hide':
return $(this).datepicker('hide');
case 'show':
return $(this).datepicker('show');
case 'getInitialDate':
return dp.parseDate($(this).eq(0).datepicker('option','dateFormat'),$(this).eq(0).attr(di)||'');
case 'getFinalDate':
return dp.parseDate($(this).eq(0).datepicker('option','dateFormat'),$(this).eq(0).attr(df)||'');
case 'getRange':
var ini=dp.parseDate($(this).eq(0).datepicker('option','dateFormat'),$(this).eq(0).attr(di)||''),
fin=dp.parseDate($(this).eq(0).datepicker('option','dateFormat'),$(this).eq(0).attr(df)||'');
return (!ini&&!fin)?null:[ini,fin];
case 'getNumDays':
var ini=dp.parseDate($(this).eq(0).datepicker('option','dateFormat'),$(this).eq(0).attr(di)||''),
fin=dp.parseDate($(this).eq(0).datepicker('option','dateFormat'),$(this).eq(0).attr(df)||'');
return (ini+0==0||fin+0==0)?0:Math.round((fin-ini)/86400000)+1;
case 'removeRange':
return $(this).attr(di,'').attr(df,'').datepicker('setDate',null);
case 'destroy':
return $(this).removeAttr(di).removeAttr(df).datepicker('destroy');
case 'serialize':
return this[0].id+'_initial='+this[0].getAttribute(di)+'&'+this[0].id+'_final='+this[0].getAttribute(df);
default:
var defaults={
allowSelectOneDay: false,
alwaysSetDateToFirstDay: true,
rangeEnabled: true,
rangeClass: 'ui-state-default ui-state-active'//'dp-highlight'
};
o = $.extend({}, defaults, $.datepicker._defaults, o);
return $(this).each(function () {
if (!$.datepicker) return;
var t = this,
hd = !! ((' ' + t.className + ' ').indexOf(' ' + cl + ' ') + 1);
$(t).datepicker($.extend({}, o, {
beforeShowDay: function (d) {
if (o.rangeEnabled) {
var d1 = dp.parseDate(o.dateFormat, t.getAttribute(di) || ''),
d2 = dp.parseDate(o.dateFormat, t.getAttribute(df) || ''),
y = (function (d) {
try {
return o.beforeShowDay.call(t, d);
} catch (e) {}
})(d) || [true, '', null],
x = ((y && y[0] !== false) || !y) && d1 && ((d.getTime() == d1.getTime()) || (d2 && d >= d1 && d <= d2));
return (!d1||!d2)?y||[true,'',null]:[y[0]&&x, (x ? o.rangeClass || defaults.rangeClass : '') + (y[1] ? ' ' + y[1] : ''), y[2]];
} else {
return (function (d) {
try {
return o.beforeShowDay.call(t, d);
} catch (e) {}
})(d) || [true, '', null];
}
},
onSelect: function (dt, x) {
if (o.rangeEnabled) {
var i = t.getAttribute(di) || '',
f = t.getAttribute(df) || '',
d1 = dp.parseDate(o.dateFormat, i),
d2 = dp.parseDate(o.dateFormat, f),
s = dp.parseDate(o.dateFormat, dt);
if ((dt == i && dt == f) || (!o.allowSelectOneDay && ((dt == i && !f) || (dt == f && !i)))) {
t.removeAttribute(di);
t.removeAttribute(df);
$(t).datepicker('setDate', null);
} else if (!d1 || d2) {
t.setAttribute(di, dt);
t.removeAttribute(df);
o.alwaysSetDateToFirstDay && $(t).datepicker('setDate', s);
} else if (s < d1) {
t.setAttribute(df, i);
t.setAttribute(di, dt);
o.alwaysSetDateToFirstDay && $(t).datepicker('setDate', s);
} else {
t.setAttribute(df, dt);
o.alwaysSetDateToFirstDay && $(t).datepicker('setDate', d1);
}
} else {
t.removeAttribute(di);
t.removeAttribute(df);
$(t).datepicker('setDate', dp.parseDate(o.dateFormat, dt));
}
try {
if($(t).datepicker('getDate'))o.onSelect.call(t, dt, x);
} catch (e) {}
}
}));
});
}
};
})(window.jQuery);
вы должны получить доступ к скрипке и прочитать список дел!
любая идея или часть кода оценены!
Я также искал способ расширить плагин Datepicker jQuery для использования стиля Bootstrap и наткнулся на этот маленький драгоценный камень:
Bootstrap-Выбор Диапазона Дат Дэн Гроссман показывает некоторые живые примеры с рабочим кодом.
тут Проект GitHub как хорошо.
наконец, вот скриншот простоты и мощности дизайна:
глядя на выбор диапазона дат сам, я нашел эту страницу. Я попробовал большинство предложенных идей и даже продемонстрировал здесь и превратил все это в простое в использовании и интеграции расширение:https://github.com/BuroRaDer/DateRangePicker. Попробуйте демо-страницу, чтобы увидеть, как это работает. Думаю, я мог бы превратить его в настоящее расширение jQuery, но пока доволен тем, как он работает.
демо:
оба сайта Drupal используют модуль календаря доступности, в который он был интегрирован в настоящее время.
Я искал версию, которая будет работать, даже если она не встроена. Я хотел иметь возможность нажимать на поля ввода, чтобы запустить диапазон datepicker. Все примеры Range datepicker, которые я мог найти, были встроены (включая версии mcestone и Jamie Layne выше, которые являются основой для этого раздвоенного кода).
вот скрипка:http://jsfiddle.net/boson/pjffdtz2/
трудная часть, кажется, получает datepicker для обработки нескольких входные сигналы когда не inlined. Datepicker не будет легко обрабатывать два входа, если вы хотите открыть datepicker в фокусе - определенно был "трюк". Если вы связываете datepicker со скрытым входом (display:none), создайте этот скрытый вход перед видимыми входами, а затем ваши видимые входы покажут datepicker на событии click, все хорошо.
поэтому я взял оригинальный ответ и просто сделал несколько незначительных изменений:
- в html создайте связанный скрытый ввод с элемент datepicker. Перечислите его до видимых входов.
- в html используйте событие click видимых входов, чтобы показать datepicker, связанный со скрытым входом.
- в Javascript datepicker onSelect временно поместите datepicker в встроенный режим, пока обе даты не будут нажаты. Это позволяет вам нажимать на несколько дат до закрытия datepicker (диапазон " до "даты и" от " даты) - это по существу превращает datepicker в multiclick datepicker.
- в datepicker onClose выключите встроенный режим. Это позволяет кому-то щелкнуть по полям ввода, чтобы снова открыть datepicker.
- в beforeShow переместите datepicker вниз на несколько пикселей, чтобы вы могли видеть поля ввода и datepicker
вот код:
$(function() {
$(".rangepicker").datepicker({
minDate: 0,
numberOfMonths: [2, 1],
beforeShow: function (input, inst) {
var rect = input.getBoundingClientRect();
setTimeout(function () {
inst.dpDiv.css({ top: rect.top + 40, left: rect.left + 0 });
}, 0);
},
beforeShowDay: function(date) {
var date1 = $.datepicker.parseDate($.datepicker._defaults.dateFormat, $("#input1").val());
var date2 = $.datepicker.parseDate($.datepicker._defaults.dateFormat, $("#input2").val());
var isHighlight =
date1 && ((date.getTime() == date1.getTime()) || (date2 && date >= date1 && date <= date2));
return [true, isHighlight ? "dp-highlight" : ""];
},
onSelect: function(dateText, inst) {
var date1 = $.datepicker.parseDate($.datepicker._defaults.dateFormat, $("#input1").val());
var date2 = $.datepicker.parseDate($.datepicker._defaults.dateFormat, $("#input2").val());
var selectedDate = $.datepicker.parseDate($.datepicker._defaults.dateFormat, dateText);
if (!date1 || date2) {
$("#input1").val(dateText);
$("#input2").val("");
} else if (selectedDate < date1) {
$("#input2").val($("#input1").val());
$("#input1").val(dateText);
} else {
$("#input2").val(dateText);
}
$(this).data('datepicker').inline = true;
$(this).datepicker();
},
onClose: function() {
// Since we went inline as soon as the date input was clicked
// (to leave the datepicker up for both dates selection),
// turn inline back off again so date input click will once again
// display the datepicker
$(this).data('datepicker').inline = false;
}
});
});
.dp-highlight .ui-state-default {
background: #484;
color: #FFF;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<input type="text" id="input1_1" class="rangepicker" style="display: none">
<p>
Dates:
<label><b>To:</b></label>
<input type="text" id="input1" onclick="$('.rangepicker').datepicker('show');">
<label><b>From:</b></label>
<input type="text" id="input2" onclick="$('.rangepicker').datepicker('show');">
<button id="done">Done</button>
</p>
много вещей осталось улучшить. Требуется лучшая проверка ввода. Особенно хотелось бы получить кнопку datepicker "готово" для работы в встроенном режиме, но datepicker не был разработан для этого сценария (конечно, было бы неплохо иметь флаг кнопки "Готово" в datepicker). Итак, на данный момент у меня есть дрянная кнопка рядом с полями ввода, которая фактически ничего не делает (кроме поощрения пользователя снять фокус с datepicker, чтобы закрыть datepicker).
Спасибо, мне нужен такой код. Вот мой код:
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<link rel="stylesheet" href="/resources/demos/style.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<div id="Datepicker"></div>
<p>
<label><b>Checkin:</b></label> <label id="checkinDate"></label>
<label><b>Checkout:</b></label> <label id="checkoutDate"></label>
</p>
/** Display Checkin Datepicker and Checkout DatePicker */
<script>
datePicker();
function datePicker(){
$(document).ready(function(){
$( "#Datepicker" ).datepicker({
dateFormat: "MM d, yy",
minDate: 0,
maxDate: "+3M +0D",
beforeShowDay: dateRange,
onSelect: DRonSelect
});
});
}
function dateRange(date){
var date1 = $.datepicker.parseDate("MM d, yy", $("#checkinDate").text());
var date2 = $.datepicker.parseDate("MM d, yy", $("#checkoutDate").text());
var isHighlight = date1 && ((date.getTime() == date1.getTime()) || (date2 && date >= date1 && date <= date2));
$(document).ready(function(){
// $("td.dp-highlight").text("Y");
});
return [true, isHighlight ? "dp-highlight" : ""];
}
function DRonSelect(dateText, inst) {
var date1 = $.datepicker.parseDate("MM d, yy", $("#checkinDate").text());
var date2 = $.datepicker.parseDate("MM d, yy", $("#checkoutDate").text());
if (!date1 || date2) {
$("#checkinDate").text(dateText);
$("#checkoutDate").text("");
$("#Datepicker").datepicker();
}
else {
if ( $.datepicker.parseDate("MM d, yy", $("#checkinDate").text()) >=
$.datepicker.parseDate("MM d, yy", dateText)) {
$("#checkinDate").text(dateText);
$("#checkoutDate").text("");
$("#Datepicker").datepicker();
}
else {
$("#checkoutDate").text(dateText);
$("#Datepicker").datepicker();
}
}
}
</script>
мой код-это пример кода из других, но отличается выбором даты, диапазоном дат и higlights. Я создал и сохранил код в JSFIDDLE