将Date Range Picker扩展选择月份范围功能

版权声明:在那最初的相遇中,我们都曾经为彼此心动过... https://blog.csdn.net/weixin_36185028/article/details/80883894

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




展开阅读全文

没有更多推荐了,返回首页