Date Range Picker是一个基于JQuery的时间选择器插件,提供了丰富的功能和优秀的界面,它的官网地址http://www.daterangepicker.com
但是这个插件有一个比较坑比的是没有月选择器,只有日期和时间选择器,项目中用到了日期选择器的功能,但是在这个项目的另外一个业务又要需要月选择器,如果重新引入一个日期选择器又多了引入文件,如果重写一个功能又不划算,于是决定直接在daterangepicker这个插件上增加月范围选择器,也要保证不影响它原来功能,也不需要引入其他的框架。
因此,使用该扩展出的月份选择器前提是会使用daterangepicker本身的功能。
一.直接使用
首先要引入datarangepicker的需要的文件
<script type="text/javascript" src="https://cdn.jsdelivr.net/jquery/latest/jquery.min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/momentjs/latest/moment.min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/daterangepicker/daterangepicker.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/daterangepicker/daterangepicker.css" />
css文件:
*{
margin: 0;
padding: 0;
}
.daterangepicker .drp-buttons {
text-align: left;
}
.daterangepicker .drp-selected {
display: none;
}
div.drp-calendar.left {
margin-right: 20px!important;
}
li{
list-style: none;
}
.s-cal {
width: 150px;
margin-top: 8px;
}
div.calendar.left {
margin-right: 20px!important;
}
.s-calTitle>span {
padding-left: 5px;
padding-right: 5px;
color: #08c;
cursor: pointer;
line-height: 25px;
border-radius: 3px;
}
.s-calTitle>span:hover {
background-color: #08c;
color: #fff;
}
.s-calTitle>p {
line-height: 25px;
margin-bottom: 2px;
}
.s-calTitle,
.s-calMonth {
display: flex;
justify-content: space-between;
margin-bottom: 10px;
}
ul.s-calMonth>li {
cursor: pointer;
padding: 5px;
border-radius: 3px;
}
ul.s-calMonth>li:hover{
background-color: #EBF4FB;
}
ul.s-calMonth>li.onFocus {
background-color: #08c;
color: #fff;
}
ul.s-calMonth>li.disabled {
cursor: not-allowed;
pointer-events: none;
opacity: 0.6;
}
.s-calViewTitle {
text-align: center;
padding-top: 3px;
padding-bottom: 3px;
background-color: #f5f5f5;
border-radius: 3px;
font-weight: bold;
color: #08c;
}
注:css文件的.daterangepicker .drp-buttons,.daterangepicker .drp-selected,div.drp-calendar.left是直接覆盖daterangepicker的css样式,由于引入的框架版本不同可能会产生不同的效果,可能需要对这三个样式酌情修改,但是不影响使用。
扩展代码:
/**
* 基于Date Range Picker的月份选择器扩展
* github:https://github.com/RidingACodeToStray/daterangepicker-monthrangepicker
* @param {起始时间} s
* @param {终止时间} e
* @param {最外层的div对象} classDom
* @param {内层的span对象} idDom
* @param {显示时间格式} sformat
* @param {是否显示日历} showCalendars
* @param {配置默认可选的时间范围} ranges
* @param {是否展示自定义范围} scrl
* @param {是否使用月份选择器} monthRange
*/
var datePicker = function(s, e, classDom, idDom, sformat = 'YYYY-MM-DD', showCalendars = true, ranges, scrl = true,monthRange) {
if (!ranges) {
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')]
}
}
var start = s || moment();
var end = e || moment();
function cb(start, end) {
classDom.html(start.format(sformat) + " - " + end.format(sformat));
}
idDom.daterangepicker({
locale: {
format: sformat
},
alwaysShowCalendars: showCalendars,
showDropdowns: true,
startDate: start,
showCustomRangeLabel: scrl,
endDate: end,
opens: "right",
ranges: ranges
},
cb
);
cb(start, end);
if(monthRange){
//修改日期选择器
$('div.drp-calendar').empty().html('<div class="s-cal"><div class="s-calTitle"><span class="glyphicon glyphicon-arrow-left s-calLastYear"aria-hidden="true"></span><p>2018</p><span class="glyphicon glyphicon-arrow-right s-calNextYear"aria-hidden="true"></span></div><ul class="s-calMonth"><li data-month="01">Jan</li><li data-month="02">Feb</li><li data-month="03">Mar</li><li data-month="04">Apr</li></ul><ul class="s-calMonth"><li data-month="05">May</li><li data-month="06">Jun</li><li data-month="07">Jul</li><li data-month="08">Aug</li></ul><ul class="s-calMonth"><li data-month="09">Sep</li><li data-month="10">Oct</li><li data-month="11">Nov</li><li data-month="12">Dec</li></ul></div>');
$('div.drp-calendar.left > .s-cal').before('<div class="s-calViewTitle">Start Date</div>');
$('div.drp-calendar.right > .s-cal').before('<div class="s-calViewTitle">End Date</div>');
var timePickerDom = $('.s-timePicker'),
sYearView = $($('.s-calTitle > p')[0]),
eYearView = $($('.s-calTitle > p')[1]),
monthViewLis = $('.s-calMonth > li'),
sMonthViewLis = $($('.s-cal')[0]).find('.s-calMonth > li'),
eMonthViewLis = $($('.s-cal')[1]).find('.s-calMonth > li'),
tabs = $('div.daterangepicker > div.ranges > ul > li'),
lastTab = $('div.daterangepicker > div.ranges > ul > li:last-child');
//缓存日期
var tempSYear,
tempEyear,
tempSMonth,
tempEMonth;
//变换日历视图修改样式
function changeView(isAngle = false){
var currentSYear = sYearView.text();
var currentEYear = eYearView.text();
eMonthViewLis.removeClass('disabled');
if(isAngle){
//年份不一致判断
if(currentSYear > currentEYear){
eMonthViewLis.addClass('disabled');
}
if(currentSYear < currentEYear){
eMonthViewLis.removeClass('disabled');
}
if(currentSYear == tempSYear){
sMonthViewLis.eq(tempSMonth).addClass('onFocus');
}
if(currentEYear == tempEyear){
eMonthViewLis.eq(tempEMonth).addClass('onFocus');
}
}else{
if(tempSMonth > tempEMonth){
//如果选中起始月份较大,则将日期赋值为起始月份
eMonthViewLis.removeClass('onFocus');
eMonthViewLis.eq(tempSMonth).addClass('onFocus');
putRangeDate();
}
eMonthViewLis.each(function(index){
if((index) == Number(tempSMonth)){
return false;
}
$(this).addClass('disabled');
})
}
}
//生成日期
function putRangeDate(){
var sYearDate = $($('.s-cal')[0]).find('.s-calTitle > p').text();
var sMonthDate = $($('.s-cal')[0]).find('.s-calMonth > li.onFocus').data('month');
var eYearDate = $($('.s-cal')[1]).find('.s-calTitle > p').text();
var eMonthDate = $($('.s-cal')[1]).find('.s-calMonth > li.onFocus').data('month');
tempSYear = sYearDate;
tempEyear = eYearDate;
tempSMonth = Number(sMonthDate) - 1;
tempEMonth = Number(eMonthDate) - 1;
timePickerDom.text(sYearDate+'-'+sMonthDate+' - '+eYearDate+'-'+eMonthDate);
changeView();
}
//给View赋值样式
function putDateView(sy,ey,sm,em){
sy && sYearView.text(sy);//赋值起始年份
ey && eYearView.text(ey);//赋值终止年份
sm && sMonthViewLis.eq(sm).addClass('onFocus');//高亮起始月份
em && eMonthViewLis.eq(em).addClass('onFocus'); //高亮终止月份
}
//取日期给View赋值样式
function getRangeDate(){
var datePeriod = timePickerDom.text().split(' - ');
var sDate = datePeriod[0].split('-'); //起始年月
var eDate = datePeriod[1].split('-'); //终止年月
tempSYear = sDate[0];
tempEyear = eDate[0];
tempSMonth = Number(sDate[1]) - 1;
tempEMonth = Number(eDate[1]) - 1;
putDateView(tempSYear,tempEyear,tempSMonth,tempEMonth);
}
getRangeDate();
changeView();
//前一年
$('.s-calLastYear').click(function(e){
var startDateDom = $(e.target).next('p');
startDateDom.text(Number(startDateDom.text()) - 1);
$(this).parents('.s-cal').find('.s-calMonth > li').removeClass('onFocus');
changeView(true);
})
//后一年
$('.s-calNextYear').click(function(e){
var startDateDom = $(e.target).prev('p');
startDateDom.text(Number(startDateDom.text()) + 1);
$(this).parents('.s-cal').find('.s-calMonth > li').removeClass('onFocus');
changeView(true);
})
//选中月份
monthViewLis.click(function(){
tabs.removeClass('active');
lastTab.addClass('active');
//两个if处理使用箭头移动导致都没有选中月份的情况
if(!sMonthViewLis.hasClass('onFocus')){
sMonthViewLis.eq(0).addClass('onFocus');
}
if(!eMonthViewLis.hasClass('onFocus')){
eMonthViewLis.eq(0).addClass('onFocus');
}
$(this).parents('.s-cal').find('.s-calMonth > li').removeClass('onFocus');
$(this).addClass('onFocus');
putRangeDate();
})
}
};
如何使用:
<div id="s-timeRange" class="pull-right s-timeRange">
<i class="glyphicon glyphicon-calendar fa fa-calendar"></i>
<span class="s-timePicker"></span> <b class="caret"></b>
</div>
<script>
$(function() {
var timeRangeDom = $('#s-timeRange'),
timePickerDom = $('.s-timePicker');
datePickers(
moment().subtract(1, 'month').startOf('month'),
moment().subtract(1, 'month').endOf('month'),
timePickerDom,
timeRangeDom,
'YYYY-MM',
true,
{
'This Month': [moment().startOf('month'), moment().endOf('month')],
'Last Month': [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')],
'Last Three Months':[moment().subtract(3, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')],
'Last Year':[moment().subtract(12, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')]
},
true,
true
);
});
</script>
展现出的效果(结合bootstrap使用的项目截图):
从以上代码可以看出,这种扩展实际上是将调用daterangepicker插件功能的方法封装在一个自定义方法datePickers中,其他方法提供了各种自定义选择器模块的方法,另外该方法也提供了一个参数monthRange,若传入为false,则默认调用为时间日期选择器,如何选择参数可以根据daterangepicker官方提供的文档来配置,如果传入monthRange为true,则将当前选择器设置为月范围选择器。
二.参数说明
参数说明:
s:默认展示起始时间,静态可以自定义字符串格式,动态的可以调用moment()方法生成;
e:默认展示结束时间,静态可以自定义字符串格式,动态的可以调用moment()方法生成;
classDom:选择最外层div的jquery对象;
idDom:选择的内层的span的jquery对象;
sformat:展示时间格式,请参见Date Range Picker文档;
showCalendars:是否默认显示日历,即点击日期下拉就展开日历,默认true;
ranges:自定义下拉的日期选项,对象格式,键名为展示内容,键值为数组两个元素,分别表示起始和结束时间,详情参见参见Date Range Picker文档;
scrl:是否展示自定义日期按钮,若需要自定义日期或者使用月份范围选择器功能则需要设置为true;
monthRange:是否使用月份范围选择器功能
三.引入js文件使用
另外也可以将datePicker写到一个js文件中结合相关的css文件单独引入,在调用如何使用部分的js代码引用
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/daterangepicker/daterangepicker.css" />
<link rel="stylesheet" href="./daterangepicker.monthpicker.css">
<script type="text/javascript" src="https://cdn.jsdelivr.net/jquery/latest/jquery.min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/momentjs/latest/moment.min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/daterangepicker/daterangepicker.min.js"></script>
<script src="./daterangepicker.monthpicker.js"></script>
github地址:https://github.com/RidingACodeToStray/daterangepicker-monthrangepicker