为了实现 bootstrap中daterangepicker组件的使用(一) 中的需求,我对demo进行了定制,具体需求可以参见:bootstrap中daterangepicker组件的使用(一) : https://blog.csdn.net/liuying1802028915/article/details/84401953
此demo的作用是根据两个变量动态算出默认的开始日期和结束日期,也就是说在日期控件打开的时候,默认的开始日期和结束日期都会默认的在日期控件中选中,并且他们中间的日期也会选中.如下图所示:
接下来直接粘代码了:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script>
var customTimePeriodType = "1"; //customTimePeriodType表示 选的是7天 1个月还是2个月 1代表7天 2代表1个月 3代表2个月 customTimePeriodType影响的是日期范围的长度
var customTimeGranularity = "1"; //customTimeGranularity 选的是哪个事件粒度 日 周还是月 1代表日 2代表周 3代表月 customTimeGranularity影响的是最后一天从那天算起
var defaultStartDate = null;
</script>
<title>在选择事件范围时,选择一个日期根据选择的左面还是右面,进行自动匹配开始日期和结束日期</title>
<link rel="stylesheet" href="css/bootstrap.min.css">
<link rel="stylesheet" href="css/daterangepicker.css">
<script src="js/jquery-2.2.3.min.js"></script>
<script src="js/moment.js"></script>
<script src="js/daterangepicker.js"></script>
<script type="text/javascript">
$(function () {
defaultStartDate = getPageStartDate();
//单个时间插件
$("input[name='date1']").daterangepicker(
{
singleDatePicker: true,//设置为单个的datepicker,而不是有区间的datepicker 默认false
showDropdowns: true,//当设置值为true的时候,允许年份和月份通过下拉框的形式选择 默认false
autoUpdateInput: false,//1.当设置为false的时候,不给与默认值(当前时间)2.选择时间时,失去鼠标焦点,不会给与默认值 默认true
timePicker24Hour : true,//设置小时为24小时制 默认false
timePicker : false,//可选中时分 默认false
locale: {
format: "YYYY-MM-DD",
separator: " - ",
daysOfWeek: ["日","一","二","三","四","五","六"],
monthNames: ["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"]
}
}
).on('cancel.daterangepicker', function(ev, picker) {
$("#date1").val("请选择日期");
$("#submitDate").val("");
}).on('apply.daterangepicker', function(ev, picker) {
$("#submitDate").val(picker.startDate.format('YYYY-MM-DD'));
$("#date1").val(picker.startDate.format('YYYY-MM-DD'));
});
//区间时间插件
$("input[name='date2']").daterangepicker(
{
autoUpdateInput: false,
startDate: getPageStartDate(),
endDate: getPageEndDate(),
maxDate: getPageMaxDate(),
locale: {
format: "YYYY-MM-DD",
separator: " - ",
applyLabel: "确认",
cancelLabel: "清空",
fromLabel: "开始时间",
toLabel: "结束时间",
customRangeLabel: "自定义",
daysOfWeek: ["日","一","二","三","四","五","六"],
monthNames: ["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],
}
}
).on('cancel.daterangepicker', function(ev, picker) {
$("#date2").val("请选择日期范围");
$("#startTime").val("");
$("#endTime").val("");
}).on('apply.daterangepicker', function(ev, picker) {
$("#startTime").val(picker.startDate.format('YYYY-MM-DD'));
$("#endTime").val(picker.endDate.format('YYYY-MM-DD'));
$("#date2").val(picker.startDate.format('YYYY-MM-DD')+" 至 "+picker.endDate.format('YYYY-MM-DD'));
});
});
//获取日期控件上最大可选的一天
function getPageMaxDate(){
//moment() 表示今天
var _maxDate = moment().subtract(1, 'days');//最大可选的日期默认是今天的前一天
if(customTimeGranularity == 1){
_maxDate = moment().subtract(1, 'days');//最大可选的日期是今天的前一天
}else if(customTimeGranularity == 2){
_maxDate = moment().subtract(8, 'days');//最大可选的日期是今天的前8天
}else if(customTimeGranularity == 3){
_maxDate = moment().subtract(31, 'days');//最大可选的日期是今天的前31天
}
return _maxDate;
}
//根据customTimePeriodType 和 customTimeGranularity 参数 获取默认选中的开始日期
function getPageStartDate(){
var _date = moment().subtract(8, 'days');
if(customTimePeriodType == 1){//日期长度 为 7天
if(customTimeGranularity == 1){//时间粒度 为 日
_date = moment().subtract(8, 'days');
}else if(customTimeGranularity == 2){//时间粒度 为 周
_date = moment().subtract(15, 'days');
}else if(customTimeGranularity == 3){//时间粒度 为 月
_date = moment().subtract(39, 'days');
}
}else if(customTimePeriodType == 2){//日期长度 为 1个月
if(customTimeGranularity == 1){//时间粒度 为 日
_date = moment().subtract(31, 'days');
}else if(customTimeGranularity == 2){//时间粒度 为 周
_date = moment().subtract(39, 'days');
}else if(customTimeGranularity == 3){//时间粒度 为 月
_date = moment().subtract(61, 'days');
}
}else if(customTimePeriodType == 3){//日期长度 为 2个月
if(customTimeGranularity == 1){//时间粒度 为 日
_date = moment().subtract(61, 'days');
}else if(customTimeGranularity == 2){//时间粒度 为 周
_date = moment().subtract(69, 'days');
}else if(customTimeGranularity == 3){//时间粒度 为 月
_date = moment().subtract(91, 'days');
}
}
var _date1 = new Date(_date);
return _date1;
}
//根据customTimePeriodType 和 customTimeGranularity 参数 获取默认选中的结束日期
function getPageEndDate(){
var _date = moment().subtract(1, 'days');
if(customTimePeriodType == 1){//日期长度 为 7天
if(customTimeGranularity == 1){//时间粒度 为 日
_date = moment().subtract(1, 'days');
}else if(customTimeGranularity == 2){//时间粒度 为 周
_date = moment().subtract(8, 'days');
}else if(customTimeGranularity == 3){//时间粒度 为 月
_date = moment().subtract(31, 'days');
}
}else if(customTimePeriodType == 2){//日期长度 为 1个月
if(customTimeGranularity == 1){//时间粒度 为 日
_date = moment().subtract(1, 'days');
}else if(customTimeGranularity == 2){//时间粒度 为 周
_date = moment().subtract(8, 'days');
}else if(customTimeGranularity == 3){//时间粒度 为 月
_date = moment().subtract(31, 'days');
}
}else if(customTimePeriodType == 3){//日期长度 为 2个月
if(customTimeGranularity == 1){//时间粒度 为 日
_date = moment().subtract(1, 'days');
}else if(customTimeGranularity == 2){//时间粒度 为 周
_date = moment().subtract(8, 'days');
}else if(customTimeGranularity == 3){//时间粒度 为 月
_date = moment().subtract(31, 'days');
}
}
var _date2 = new Date(_date);
return _date2;
}
function getFormatDay(dateTemp){
var date11 = new Date(dateTemp);
var seperator = "-";
var year = date11.getFullYear();
var month = date11.getMonth()+1;
var day = date11.getDate();
if(month >= 1 && month <= 9){
month = "0"+month;
}
if(day >= 1 && day <= 9){
day = "0"+day;
}
var currentDay = year + seperator + month + seperator + day;
return currentDay;
}
</script>
</head>
<body>
<div>
我是一个DateRangePicker的小练习
</div>
<div class="form-group">
<label>单个</label>
<div>
<input type="text" name="date1" id="date1" class="form-control" style="width: 20%;">
<input type="hidden" id = "submitDate" name="submitDate" class="form-control" />
</div>
</div>
<div class="form-group">
<label>区间</label>
<div>
<input type="text" name="date2" id="date2" class="form-control" style="width: 20%;">
<input type="hidden" id = "startTime" name="startTime" class="form-control" />
<input type="hidden" id = "endTime" name="endTime" class="form-control" />
</div>
</div>
</body>
</html>
如上代码所示,打开区间的日期控件的代码是:
//区间时间插件
$("input[name='date2']").daterangepicker(
{
autoUpdateInput: false,
startDate: getPageStartDate(),
endDate: getPageEndDate(),
maxDate: getPageMaxDate(),
locale: {
format: "YYYY-MM-DD",
separator: " - ",
applyLabel: "确认",
cancelLabel: "清空",
fromLabel: "开始时间",
toLabel: "结束时间",
customRangeLabel: "自定义",
daysOfWeek: ["日","一","二","三","四","五","六"],
monthNames: ["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],
}
}
).on('cancel.daterangepicker', function(ev, picker) {
$("#date2").val("请选择日期范围");
$("#startTime").val("");
$("#endTime").val("");
}).on('apply.daterangepicker', function(ev, picker) {
$("#startTime").val(picker.startDate.format('YYYY-MM-DD'));
$("#endTime").val(picker.endDate.format('YYYY-MM-DD'));
$("#date2").val(picker.startDate.format('YYYY-MM-DD')+" 至 "+picker.endDate.format('YYYY-MM-DD'));
});
其中
startDate参数 可以使用一个函数获得:getPageStartDate()
同理:
endDate参数 可以使用一个函数获得:getPageEndDate()
maxDate参数 可以使用一个函数获得:getPageMaxDate()
其中:
function getPageStartDate(){
var _date = moment().subtract(8, 'days');
if(customTimePeriodType == 1){//日期长度 为 7天
if(customTimeGranularity == 1){//时间粒度 为 日
_date = moment().subtract(8, 'days');
}else if(customTimeGranularity == 2){//时间粒度 为 周
_date = moment().subtract(15, 'days');
}else if(customTimeGranularity == 3){//时间粒度 为 月
_date = moment().subtract(39, 'days');
}
}else if(customTimePeriodType == 2){//日期长度 为 1个月
if(customTimeGranularity == 1){//时间粒度 为 日
_date = moment().subtract(31, 'days');
}else if(customTimeGranularity == 2){//时间粒度 为 周
_date = moment().subtract(39, 'days');
}else if(customTimeGranularity == 3){//时间粒度 为 月
_date = moment().subtract(61, 'days');
}
}else if(customTimePeriodType == 3){//日期长度 为 2个月
if(customTimeGranularity == 1){//时间粒度 为 日
_date = moment().subtract(61, 'days');
}else if(customTimeGranularity == 2){//时间粒度 为 周
_date = moment().subtract(69, 'days');
}else if(customTimeGranularity == 3){//时间粒度 为 月
_date = moment().subtract(91, 'days');
}
}
var _date1 = new Date(_date);
return _date1;
}
其中 默认的开始日期是根据 customTimePeriodType 和 customTimeGranularity 这两个参数算出来的,其中又用到了
moment().subtract(8, 'days'); 函数 这两个函数是 moment.js 中的函数,也是封装好的直接可以使用,具体细节这里就不多说了,需要看源码,或者官网的demo
至于getPageEndDate() 函数 和 getPageMaxDate() 我就不细说了,同 getPageStartDate() 一样.
二.并且这个demo中海油一个功能是:
根据点击选择的日期自动算出剩下的日期(开始日期或结束日期)
什么意思呢,让我给你细细道来,首先 看到了上图的日期控件 有两个月份,默认有一个事件范围,这个时间范围是7天, 开始日期是2018-10-12 结束日期是2018-10-19 那么我点击左侧日历中的一个日期,就把点击的日期作为开始日期,长度7天来算出结束日期,也就是说,假如我点击了3号,如下所示:
自己算出了结束日期是2018-10-10,那么我点击的是右侧日历也就是说11月份的某个日期呢,比如我点击了2018-11-15 ,如下所示:
他会将点击选择的2018-11-15这一天作为结束日期,以7天为长度算出开始日期是2018-11-08 并且显示在日期控件上,这个需求蛋疼吧,我刚开始拿到的时候也是一脸懵逼,不知道怎么做,显示印了一个laydate的组件,demo很简单,但是蛋疼的是他的源码没开放,源码是压缩过后的,我是没有找到未压缩版的源码,不能进行修改,所以没法实现这样的所能,所幸的是我找到了bootstrap中daterangepicker这个组件,他的源码是开源的,可以进行修改,接下来我就把修改过后的源码粘过来供大家参考.
主要进行修改的源码部分是
clickDate() 函数,也就是说组件中点击一个日期的函数,在这个函数中,通过点击的日期算出算出剩下的开始日期或者结束日期,在通过这个组件的setStartDate() 函数 和 setEndDate() 函数即可进行定制.倒也不是很难,接下来我就把代码放上来:
clickDate: function(e) {
if (!$(e.target).hasClass('available')) return;
// debugger;
var sss = customTimePeriodType;
var title = $(e.target).attr('data-title');
var row = title.substr(1, 1);
var col = title.substr(3, 1);
var cal = $(e.target).parents('.calendar');
var date = cal.hasClass('left') ? this.leftCalendar.calendar[row][col] : this.rightCalendar.calendar[row][col];
// var dateTemp = cal.hasClass('left') ? this.leftCalendar.calendar[row][col] : this.rightCalendar.calendar[row][col]; //当时这样写,后面对dateTemp对象 subtract处理后,date的值也会跟着变化 所以得克隆一下,也就是下一句
var dateTemp = date.clone();//clone()后 对dateTemp 对象进行 subtrace处理后 date 不会变 满足我的需求
//根据需求,下面是对daterangepicker控件的修改
var clickLeftOrRight = "left";//clickLeftOrRight 参数表示点击的日期是日期左边控件的还是右边控件的 默认是左边
if(cal.hasClass('left')){
clickLeftOrRight = "left";
}
if(cal.hasClass('right')){
clickLeftOrRight = "right";
}
var _startDay = defaultStartDate;
var dateTemp2 = date.clone();
var startDay = new Date(_startDay);
var clickDay = new Date(dateTemp2);
var flag = false;
var _timePeriod = -7;
if(clickLeftOrRight == "left"){//clickLeftOrRight 如果为left 表示点击的是左边的日期 那么点击的日期就是开始日期 往后推算结束日期
if(customTimePeriodType == 1){
_timePeriod = -7;
}else if(customTimePeriodType == 2){
_timePeriod = -30;
}else if(customTimePeriodType == 3){
_timePeriod = -60;
}
}else if(clickLeftOrRight == "right"){//clickLeftOrRight 如果为righth 表示点击的是右边的日期 那么点击的日期就是结束日期 往前推算开始日期
if(customTimePeriodType == 1){
_timePeriod = 7;
}else if(customTimePeriodType == 2){
_timePeriod = 30;
}else if(customTimePeriodType == 3){
_timePeriod = 60;
}
}else{
return;
}
var afterTimePeriodDate = null; //afterTimePeriodDate 为 根据点击的日期推算的日期
var startRelateEnd = false;//默认是结束时间大于开始时间,如果结束时间小于开始时间 则将startRelateEnd 参数置为true
if(clickLeftOrRight == "left"){
if(clickDay.getTime() > startDay.getTime()){
alert("所选日期不能小于默认范围的开始日期");
return;
}else{
afterTimePeriodDate = dateTemp.subtract(_timePeriod, 'days');
var endDay = new Date(afterTimePeriodDate);
if(clickDay && endDay && clickDay.getTime() > endDay.getTime()){
startRelateEnd = true;
}
flag = true;
}
}else if(clickLeftOrRight == "right"){
afterTimePeriodDate = dateTemp.subtract(_timePeriod, 'days');
var endDay = new Date(afterTimePeriodDate);
if(clickDay && endDay && clickDay.getTime() > endDay.getTime()){
startRelateEnd = true;
}
flag = true;
}else{
return;
}
//
// this function needs to do a few things:
// * alternate between selecting a start and end date for the range,
// * if the time picker is enabled, apply the hour/minute/second from the select boxes to the clicked date
// * if autoapply is enabled, and an end date was chosen, apply the selection
// * if single date picker mode, and time picker isn't enabled, apply the selection immediately
//
if (this.endDate || date.isBefore(this.startDate, 'day')) {
if (this.timePicker) {
var hour = parseInt(this.container.find('.left .hourselect').val(), 10);
if (!this.timePicker24Hour) {
var ampm = this.container.find('.left .ampmselect').val();
if (ampm === 'PM' && hour < 12)
hour += 12;
if (ampm === 'AM' && hour === 12)
hour = 0;
}
var minute = parseInt(this.container.find('.left .minuteselect').val(), 10);
var second = this.timePickerSeconds ? parseInt(this.container.find('.left .secondselect').val(), 10) : 0;
date = date.clone().hour(hour).minute(minute).second(second);
}
// this.endDate = null;
if(!startRelateEnd){//startRelateEnd 为true时 表示结束时间 小于 开始时间 startRelateEnd为false时表示结束时间大于开始时间
this.setStartDate(date.clone());
if(flag){
this.setEndDate(afterTimePeriodDate.clone());
}
}else{
this.setStartDate(afterTimePeriodDate.clone());
if(flag){
this.setEndDate(date.clone());
}
}
} else if (!this.endDate && date.isBefore(this.startDate)) {
//special case: clicking the same date for start/end,
//but the time of the end date is before the start date
this.setEndDate(this.startDate.clone());
} else {
if (this.timePicker) {
var hour = parseInt(this.container.find('.right .hourselect').val(), 10);
if (!this.timePicker24Hour) {
var ampm = this.container.find('.right .ampmselect').val();
if (ampm === 'PM' && hour < 12)
hour += 12;
if (ampm === 'AM' && hour === 12)
hour = 0;
}
var minute = parseInt(this.container.find('.right .minuteselect').val(), 10);
var second = this.timePickerSeconds ? parseInt(this.container.find('.right .secondselect').val(), 10) : 0;
date = date.clone().hour(hour).minute(minute).second(second);
}
this.setEndDate(date.clone());
if (this.autoApply) {
this.calculateChosenLabel();
this.clickApply();
}
}
if (this.singleDatePicker) {
this.setEndDate(this.startDate);
if (!this.timePicker)
this.clickApply();
}
this.updateView();
},
其中都有注释,我这里就不多说了,稍后我会把整个的源码放到github上