带有手动输入和动态最小日期的 jQuery UI 日期选择器

Posted

技术标签:

【中文标题】带有手动输入和动态最小日期的 jQuery UI 日期选择器【英文标题】:jQuery UI datepicker with manual entry and dynamic min-date 【发布时间】:2019-08-08 23:18:38 【问题描述】:

我的页面上有一些日期选择器,可以通过选择器或手动输入来填充。有一些规则应该适用于这些日期选择器,但我不知道如何动态解决这个问题。

问题 1 日期 2 不应早于日期 1。日期 3 不应早于 1 和 2。 这目前适用于日期选择器,但不适用于手动输入。如果日期是手动输入的并且早于最小日期,则该字段应留空。

问题 2 如果第一个日期发生变化(如之前的更早日期),则第二个日期的最小日期也应更新。 这同样适用于第三个日期选择器。

该页面上可以有 1-x 个日期选择器!

let d = new Date();
let nextValidDate = d.getDate() + "." + (d.getMonth() + 1) + "." + d.getFullYear();

$(document).on("blur change", ".datepicker", function () 
    nextValidDate = $(this).datepicker("getDate");
);

$(document).on('focus', '.datepicker',
    function () 
        $(this).datepicker(
            numberOfMonths: 1,
            firstDay: 1,
            changeMonth: true,
            changeYear: true,
            dateFormat: 'dd.mm.yy',
            minDate: nextValidDate
        );

        $(this).datepicker('show');
    );


$(document).on('blur', '.datepicker', function () 
    if ($(this).val().length >= 2) 
        parseInputDate(this);
    
);



function parseInputDate(elm) 
    var currDate = new Date(),
        monDt = (('0' + currDate.getMonth() + 1).slice(-2) + ('0' + currDate.getDate()).slice(-2)), // get current month+date to compare
        inputVal = $(elm).val().match(/\d2/gi); // split date components into array of [dd,mm,yy,yy]

    // another date validation, by comparing parameters and date object result 
    var isValidDate = function (yyyy, mm, dd) 
        var dt = new Date(yyyy, parseInt(mm, 10) - 1, dd);
        return (dt.getFullYear() + '-' + ('0' + (dt.getMonth() + 1)).slice(-2) + '-' + ('0' + dt.getDate()).slice(-2)) == yyyy + '-' + mm + '-' + dd;
    

    if (inputVal != null && inputVal.length >= 2) 
        var year = currDate.getFullYear();

        if (monDt > (inputVal[1] + inputVal[0])) year++;
        // generate formatted text based on date component count
        // add date validation to catch invalid dates using (new Date('yyyy-mm-dd')).getTime() which will return NaN on invalid date

        var result = (inputVal.length == 2 && isValidDate(year, inputVal[1], inputVal[0]) && inputVal[0] + '.' + inputVal[1] + '.' + year) ||
            (inputVal.length == 3 && isValidDate('20' + inputVal[2], inputVal[1], inputVal[0]) && inputVal[0] + '.' + inputVal[1] + '.20' + inputVal[2]) ||
            (inputVal.length == 4 && isValidDate(inputVal[2] + inputVal[3], inputVal[1], inputVal[0]) && inputVal[0] + '.' + inputVal[1] + '.' + inputVal[2] + inputVal[3]) ||
            ''; // set empty on invalid dates

        $(elm).val(result);
        nextValidDate = result;
     else 
        $(elm).val('')
    ;
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<link href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css" rel="stylesheet"/>

<div>
  <label for="date1">Date 1:</label>
  <input type="text" class="datepicker" id="date1">
</div>
<div>
  <label for="date2">Date 2:</label>
  <input type="text" class="datepicker" id="date2">
</div>
<div>
  <label for="date3">Date 3:</label>
  <input type="text" class="datepicker" id="date3">
</div>

【问题讨论】:

【参考方案1】:

考虑这个例子:http://jqueryui.com/datepicker/#date-range

我们可以像这样设置您的代码:

$(function() 
  var dateFormat = 'dd.mm.yy';

  function getDate(el) 
    var date;
    try 
      date = $.datepicker.parseDate(dateFormat, el.value);
     catch (error) 
      date = null;
    
    return date;
  

  function checkMinDate(el) 
    var date = getDate(el);
    var minDate = $(el).datepicker("option", "minDate");
    var test;
    try 
      test = (date >= minDate);
     catch (error) 
      test = false;
    
    return test;
  

  $(".datepicker").datepicker(
    numberOfMonths: 1,
    firstDay: 1,
    changeMonth: true,
    changeYear: true,
    dateFormat: dateFormat,
    minDate: 0
  ).on("change", function(e) 
    e.preventDefault();
    var td = getDate(this);
    var dpid = $(this).attr("id");
    var dpi = parseInt(dpid.slice(dpid.indexOf("-") + 1));
    $("#date-" + (dpi + 1)).prop("disabled", false).datepicker("option", 
      minDate: td,
      defaultDate: td
    );
    if (!checkMinDate(this)) 
      this.value = "";
      return false;
    
    return true;
  );
  $(".datepicker:not(:eq(0))").prop("disabled", true);
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<link href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css" rel="stylesheet" />

<div class="date-wrapper">
  <div>
    <label for="date1">Date 1:</label>
    <input type="text" class="datepicker" id="date-1">
  </div>
  <div>
    <label for="date2">Date 2:</label>
    <input type="text" class="datepicker" id="date-2">
  </div>
  <div>
    <label for="date3">Date 3:</label>
    <input type="text" class="datepicker" id="date-3">
  </div>
  <div>
    <label for="date3">Date 4:</label>
    <input type="text" class="datepicker" id="date-4">
  </div>
  <div>
    <label for="date3">Date 5:</label>
    <input type="text" class="datepicker" id="date-5">
  </div>
</div>

我相信这符合您的标准:

之前的日期字段应小于或“早于”当前日期字段。 之前的所有日期都应小于此日期字段。 如果 a 日期发生变化,则以下日期的最小日期也应更新。

函数getDate() 接收一个元素并检测它是否包含字符串格式的日期(基于日期格式)并返回一个与该日期或null 相等的日期对象。

函数checkMinDate()是帮助我们检测手动输入的日期。它根据 minDate 值检查手动输入的日期。如果它大于或等于minDate,它将返回 true。如果小于minDate,则返回false。

在我们的change 回调中,我们使用.preventDefault() 来停止当前操作。这对于我们想要测试输入内容的类型事件很有帮助。我们可以稍后返回truefalse 以允许事件进行。如果checkMinDate不为真,我们可以清除该值并返回假。

希望有帮助!

【讨论】:

其中包含一些不错的想法,谢谢。但是我绝对必须将给定示例中的 parseDate 函数包含到您的代码中。必须找出,如何..

以上是关于带有手动输入和动态最小日期的 jQuery UI 日期选择器的主要内容,如果未能解决你的问题,请参考以下文章

用于 DataTypeCheck 的 jQuery UI datetimepicker 和 ASP.NET CompareValidator

如何动态更改 jquery ui 滑块的最小值、最大值?

为啥 jQuery UI 的日期选择器会与动态 DOM 发生冲突?

jquery里自带的时间控件,怎么禁止手动输入,只能选取控件上的日期,而且是两个时间控件选择一个时间段

带有动态错误消息的jquery验证添加方法[重复]

带有ng-repeat的表中的最小和最大日期jquery datepicker