繁体   English   中英

jquery ui datepicker上的日期范围选择器

[英]Date range picker on jquery ui 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 解决方案中,它只会将较早的日期放在第二个输入中,而不是突出显示两者之间的日期。

你的剧本正是我要找的。 我分叉了你原来的小提琴,只对你的 onSelect 做了轻微的调整,让它按照你想要的方式工作。

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>

我也在寻找一种方法来扩展 Datepicker jQuery 插件以利用 Bootstrap 样式并遇到了这个小宝石:

Dan Grossman 的Bootstrap-Date Range Picker展示了一些带有工作代码的现场示例。

这里也是GitHub项目。

最后,这是设计的简单性和强大功能的屏幕截图:

截屏

伙计,你的代码正是我所需要的!

在 Jamie Layne 的修正下,我决定用它来制作一个插件。

这是 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);

您应该访问小提琴并阅读要做的事情列表!

任何想法或一段代码表示赞赏!

谢谢我需要这种代码。 这是我的代码:

<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>

我的代码是来自其他代码的示例代码,但在日期选择、日期范围和亮点方面有所不同。 我在 JSFIDDLE 中创建并保存了一个代码

https://jsfiddle.net/kk585b4g/

我自己在寻找日期范围选择器,我找到了这个页面。 我尝试了大多数建议甚至在这里演示的想法,并将这一切变成了一个易于使用和集成的扩展: https : //github.com/BuroRaDer/DateRangePicker 尝试演示页面,看看它是如何工作的。 我想我可以把它变成一个真正的 jQuery 扩展,但现在我对它的工作方式很满意。

现场演示:

两者都是使用可用性日历模块的 Drupal 站点,现在已将其集成到其中。

我一直在寻找一个即使没有内联也能工作的版本。 我希望能够单击输入字段以启动范围日期选择器。 我能找到的所有范围日期选择器示例都是内联的(包括上面的 mcestone 和 Jamie Layne 版本,它们是此分叉代码的基础)。

这是小提琴: http : //jsfiddle.net/boson/pjffdtz2/

困难的部分似乎是让 datepicker 在未内联时处理多个输入。 如果您想在焦点上打开日期选择器,则日期选择器将无法轻松处理两个输入 - 绝对有一个“技巧”。 如果您将日期选择器与隐藏输入 (display:none) 相关联,在可见输入之前创建该隐藏输入,然后让您的可见输入在单击事件上显示日期选择器,一切都很好。

所以我接受了原来的答案,只是做了一些小改动:

  • 在 html 中,创建一个与日期选择器关联的隐藏输入。 在可见输入之前列出它。
  • 在 html 中,使用可见输入的 click 事件来显示与隐藏输入关联的日期选择器。
  • 在 Javascript datepicker onSelect 中,临时将 datepicker 置于内联模式,直到单击两个日期。 这允许您在 datepicker 关闭之前单击多个日期(范围“To”日期和“From”日期) - 这实际上将 datepicker 变成了多单击 datepicker。
  • 在日期选择器 onClose 中,关闭内联模式。 这允许某人单击输入字段以再次打开日期选择器。
  • 在 beforeShow 中,将日期选择器向下移动几个像素,以便您可以看到输入字段和日期选择器

这是代码:

 $(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>

还有很多东西需要改进。 需要更好的输入验证。 特别想让日期选择器的“完成”按钮在内联模式下工作,但日期选择器不是为这种情况设计的(当然在日期选择器中有一个可设置的完成按钮标志会很好)。 所以现在,我在输入字段旁边有一个简单的完成按钮,实际上什么都不做(除了鼓励用户将焦点从日期选择器上移开以关闭日期选择器)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM