选择预定义范围时防止 Daterangepicker 关闭

Prevent Daterangepicker from closing when predefined range selected

我正在使用 Dan Grossman 的 DateRangePicker 插件为用户提供一种方法来 select 我网站上特定功能的预定义和自定义日期范围。我有它的工作,但我有一个困扰我的问题,我一直无法解决。

当用户点击预定义的日期范围时,bootstrap 下拉菜单关闭。这导致用户必须重新打开日期选择器并单击 "apply" 按钮才能执行该功能。

我希望下拉菜单在单击预定义的日期范围后保持打开状态。如果用户对范围满意,则可以快速单击应用按钮。

我试过以下方法:

$(function() {
    $(document).on('click', '.ranges li', function(e) {
        e.preventDefault();
    });
});

这有效地阻止了下拉菜单的关闭,但它不会执行 "clickRange" 函数以在适当的输入中设置开始和结束日期。

只需尝试使用此代码,其中 config-demo 是文本框的 ID,您可以替换文本框 ID:

$(function () {
     $(document).on('click', '.ranges li', function (e) {
         $("#config-demo").focus();
     });
});

当您 select 范围不是 "Custom Range" 时,只显示调用 show() 函数。

您可以使用以下代码:

 $(function() {
  var listItem,applyClicked=false;
  /* $(document).on('click', '.ranges li', function(e) {
   e.preventDefault();
  }); */

  var start = moment().subtract(29, 'days');
  var end = moment();

  function cb(start, end) {
   /* console.log(start.format('MMMM D, YYYY') + ' - '
     + end.format('MMMM D, YYYY')); */
   $('#reportrange span').html(
     start.format('MMMM D, YYYY') + ' - '
       + end.format('MMMM D, YYYY'));
  }

  $('#reportrange').daterangepicker(
    {
     startDate : start,
     endDate : end,
     ranges : {
      'Today' : [ moment(), moment() ],
      'Yesterday' : [ moment().subtract(1, 'days'),
        moment().subtract(1, 'days') ],
      'Last 7 Days' : [ moment().subtract(6, 'days'),
        moment() ],
      'Last 30 Days' : [ moment().subtract(29, 'days'),
        moment() ],
      'This Month' : [ moment().startOf('month'),
        moment().endOf('month') ],
      'Last Month' : [
        moment().subtract(1, 'month').startOf('month'),
        moment().subtract(1, 'month').endOf('month') ]
     }
    }, cb);

  $(".ranges ul li").click(function() {
   listItem = $(this).text();
  });
  $(".range_inputs ").click(function() {
   applyClicked=true;
  });

  $('#reportrange').on('apply.daterangepicker', function(ev, picker) {
   console.log(listItem +" : "+ applyClicked);
   if(listItem!="Custom Range" && !applyClicked){
    picker.show();
    applyClicked=false;
   }
    
   //ev.preventDefault();

  });

  cb(start, end);

 });
<!-- Include Required Prerequisites -->
<script type="text/javascript"
 src="//cdn.jsdelivr.net/jquery/1/jquery.min.js"></script>
<script type="text/javascript"
 src="//cdn.jsdelivr.net/momentjs/latest/moment.min.js"></script>
<link rel="stylesheet" type="text/css"
 href="//cdn.jsdelivr.net/bootstrap/latest/css/bootstrap.css" />

<!-- Include Date Range Picker -->
<script type="text/javascript"
 src="//cdn.jsdelivr.net/bootstrap.daterangepicker/2/daterangepicker.js"></script>
<link rel="stylesheet" type="text/css"
 href="//cdn.jsdelivr.net/bootstrap.daterangepicker/2/daterangepicker.css" />



<div id="reportrange" class="pull-right"
  style="background: #fff; cursor: pointer; padding: 5px 10px; border: 1px solid #ccc; width: 100%">
  <i class="glyphicon glyphicon-calendar fa fa-calendar"></i>&nbsp; <span></span>
  <b class="caret"></b>
 </div>

如果您还需要什么,请告诉我。

does not really work except the initial run, as Elijah pointed out in his

这也取决于默认范围选项的文本值。由于它的脆弱性,这是一种糟糕的编程实践。在这种情况下,如果您使用多种语言的小部件,该解决方案 失效。

我开发了以下解决方案,想在这里分享;

initDateRangePicker($('input'))

function initDateRangePicker($input) {

  $input.daterangepicker({
    alwaysShowCalendars: true,
    ranges: {
      'Today': [moment(), moment()],
      'Yesterday': [moment().subtract(1, 'days'), moment().subtract(1, 'days')],
      'Last 7 Days': [moment().subtract(6, 'days'), moment()],
      'Last 30 Days': [moment().subtract(29, 'days'), moment()],
      'This Month': [moment().startOf('month'), moment().endOf('month')],
    }
  })

  $input.on('apply.daterangepicker', function(ev, picker) {
    if (rangeClicked) picker.show()
  })

  let rangeClicked = false

  // we want picker to remain open when after selecting a custom range
  $('.daterangepicker').not('.custom-events-attached').not('.custom-events-attached')
    // mark picker instance(s) as processed, so we won't attach duplicate events in the future
    .addClass('custom-events-attached')

    // clicking anywhere on the picker will reset our state
    // this is not a problem since this click event will always be fired after `apply.daterangepicker`
    .click(() => rangeClicked = false)

    // selecting one of the ranges will let us know that we want to keep our picker open
    // on the next `apply` event
    .find('.ranges').find('li').click(() => {
      rangeClicked = true
    })
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-daterangepicker/3.0.5/daterangepicker.min.css" rel="stylesheet" />

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-daterangepicker/3.0.5/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-daterangepicker/3.0.5/daterangepicker.min.js"></script>

<input type="text" name="date-range">