这次开始的项目是PC版的,貌似有2年没正儿八经的折腾PC端了。
言归正传,这次功能中有个选择日期段的功能,本来不麻烦的事情,但是PM非要参照另外一个网站的效果来做,把别人代码扒下来一看,我去,08年的插件,很多功能不能满足当前,PM非要那效果,时间又TM有限,就又找了个国外的插件daterangepicker,基于bootstrap,跟需求长得很像,功能非常强大,需求都能满足,但是...但是,PM和测试说不好用。。。折腾了半天源代码,优化了下,时间来不及只能凑合用着。
重新动手写了个。依赖jquery和moment.js(主要处理日期,如果自己处理也可以不需要),
先看效果图
使用方法:
var daterangepicker = new DateRangePicker(); daterangepicker.init({ "ele": $("#daterange"), "pos":"left", "min_date": "1990-01-01", "format": "YYYY:MM:DD", "updateDateFn":function(){ console.log(daterangepicker.getDate()) } });
基本思路是:
创建一个日期选择构造函数
function DateRangePicker() { this.start_picker = null; this.end_picker = null; }
初始化日期构造函数,日期段由两个单独的日期选择组成,当起始日期和结束日期变化时要调用构造函数的updateDate方法,通知日期发生了变化。
DateRangePicker.prototype.init = function(opts) { var self = this; this.opts = $.extend({ "pos":"left",//日历位置,靠左或靠右 "min_date":"1970-01-01",//最小日期 "updateDateFn":function(){//日期更新回调 } }, opts || {}); this.createCalendarWrap(); this.$wrap=this.opts.ele.parents(".ui-datepicker"); this.start_picker = new DatePicker();//起始日期日历 this.end_picker = new DatePicker();//结束日期日历 this.start_picker.init({ "container": this.$wrap.find(".calendar-container"), "min_date":self.opts.min_date, "yearOffset": 20, "updateCallback": function(){ self.updateDate(); } }); this.end_picker.init({ "container": this.$wrap.find(".calendar-container2"), "yearOffset": 20, "min_date":self.opts.min_date, "updateCallback": function(){ self.updateDate(); } }); this.bindEvent(); };
处理日期发生变化的情况,比如起始日期大于结束日期,要进行互换。
DateRangePicker.prototype.updateDate = function() { var self = this; var start_date = moment(self.start_picker.currentDate).format(self.opts.format); var end_date = moment(self.end_picker.currentDate).format(self.opts.format); var start_date_time=new Date(self.start_picker.currentDate).getTime(); var end_date_time=new Date(self.end_picker.currentDate).getTime(); if(start_date_time>new Date().getTime()){ self.start_picker.setCurrentDate(new Date()); } if(end_date_time>new Date().getTime()){ self.end_picker.setCurrentDate(new Date()); } if(start_date_time>end_date_time){ self.opts.ele.val(end_date + "~" + start_date); }else{ self.opts.ele.val(start_date + "~" + end_date); } $(".ui-daterangepicker-range li").removeClass("active"); self.opts.updateDateFn.call(null,this.getDate());//日期更新后重新获取当前的起始和结束日期 };
获取起始和结束日期
//获取起始日期和结束日期段,起始日期若大于结束日期则互换 DateRangePicker.prototype.getDate = function() { var start_date=Math.min(this.start_picker.currentDate.getTime(),this.end_picker.currentDate.getTime()); var end_date=Math.max(this.start_picker.currentDate.getTime(),this.end_picker.currentDate.getTime()); start_date=moment(start_date).format(this.opts.format); end_date=moment(end_date).format(this.opts.format); return { "start_date":start_date, "end_date": end_date }; };
提供动态设置当前起始日期和结束日期的方法
//设置起始日期和结束日期 DateRangePicker.prototype.setDate = function(start_date, end_date) { this.start_picker.setCurrentDate(new Date(start_date)); this.end_picker.setCurrentDate(new Date(end_date)); this.updateDate(); };
创建一个容器,因为日期选择要刚好在日期文本框下面,在日期文本框外面包一层方便定位。
//创建日期段容器 DateRangePicker.prototype.createCalendarWrap = function() { var $parent=this.opts.ele.parents(".ui-datepicker"); var h=$parent.height(),w=$parent.width(); var wrap = ''; $parent.append(wrap); };' + '开始日期
' + '结束日期
' + '
' + '- 今日
' + '- 昨日
' + '- 最近7日
' + '- 最近30日
' + '
接下来是单个日期选择的处理
定义构造函数和初始化
function DatePicker() { this.opts = null; this.today = new Date(); //今天 this.todayDate=this.today.getDate(); this.currentDate = new Date(); //当前选中日期 } DatePicker.prototype.init = function(opts) { var opts = $.extend({ 'min_date':"1970-01-01", "yearOffset": 20//默认往前推20年 }, opts || {}); this.opts = opts; this.renderCalendar(); this.bindEvent(); };
事件处理
DatePicker.prototype.bindEvent = function() { var self = this; self.opts.container.on("change", ".year-select", function() { self.renderSelectedDate(); }); //选中月份 self.opts.container.on("change", ".month-select", function() { self.renderSelectedDate(); }); //下一月 self.opts.container.on("click", ".next-btn", function(e) { e.stopPropagation(); var cur_date =self.currentDate.setMonth(self.currentDate.getMonth()+1);; self.setCurrentDate(cur_date); }); //上一月 self.opts.container.on("click", ".prev-btn", function(e) { e.stopPropagation(); var cur_date = self.currentDate.setMonth(self.currentDate.getMonth()-1); self.setCurrentDate(cur_date); }); //选择日历中某一天 self.opts.container.on("click", ".date-item", function() { if (!$(this).hasClass("disabled")) { var _day = $(this).attr("date"); var cur_date = self.currentDate.setDate(_day); self.setCurrentDate(cur_date); } }); };
定义临时存储的当前日期,默认日期是今天,但是选择的时候当前日期会变化。
//临时被选中的日期 DatePicker.prototype.tempActiveDate=(function(){ var _date=new Date(); return { getDate: function() { return _date; }, setDate:function(date){ _date=new Date(date); } }; })();
年月下拉框变化时更新日期
//设置下拉框选中的日期 DatePicker.prototype.renderSelectedDate = function() { var _year = this.opts.container.find(".year-select").val(); var _mOnth= this.opts.container.find(".month-select").val(); var _day = this.currentDate.getDate(); var cur_date = new Date(_year, _month, _day); this.setCurrentDate(cur_date); };
渲染日历框架,日历固定为42格,7列6行,星期从一到天
//渲染日历框架 DatePicker.prototype.renderCalendar = function() { var calendar_header = this.renderHeader(); var calendar_days = '
日 | 一 | 二 | 三 | 四 | 五 | 六 |
---|---|---|---|---|---|---|
渲染日历的头部,包括上月、下月按钮,年月的下拉框
//渲染日历头部 DatePicker.prototype.renderHeader = function() { var _year = this.today.getFullYear(); var _mOnth= this.today.getMonth() + 1; var current_year = this.currentDate.getFullYear(); var current_mOnth= this.currentDate.getMonth(); var mOnthArr= ["一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一", "十二"]; var min_year=(new Date(this.opts.min_date)).getFullYear();//最小年份 var start_year=current_year - this.opts.yearOffset>=min_year&#63;current_year - this.opts.yearOffset:min_year;//下拉框起始年份 var yearSelect=""; //如果已经是最小日期,不显示上月按钮 if (current_year <= min_year && current_month <= 0) { yearSelect+='>'; } return "" + yearSelect + monthSelect + ""; };
//渲染日历数据 DatePicker.prototype.renderCalendarData = function() { var self = this; var _year = this.currentDate.getFullYear(); //当前年 var _mOnth= this.currentDate.getMonth() + 1; //当前月 var _firstDay = new Date(_year, _month - 1, 1); //当前月第一天 var tds = this.opts.container.find(".calendar_body td"); var header = self.renderHeader(); this.opts.container.find(".calendar_header").html(header); tds.each(function(index, item) { var _thisDate = new Date(_year, _month - 1, index + 1 - _firstDay.getDay()); var _thisDay = _thisDate.getDate(); var _thisMOnth= _thisDate.getMonth() + 1; var _thisDateTime=_thisDate.getTime(); $(item).html(_thisDay).attr("date", _thisDay).removeClass("active").removeClass("disabled").removeClass("today"); //当前月并且当前选中日期高亮 if (_thisDay == self.tempActiveDate.getDate().getDate() && _thisMOnth== _month) { $(item).addClass("active"); } //今天日期样式 if (_thisDay == self.todayDate) { $(item).addClass("today"); } //非当前月或者大于今天的日期禁用 if (_thisMonth !== _month || _thisDateTime>self.today.getTime()) { $(item).addClass("disabled").removeClass('active today'); } //如果选择的日期大于今天,则日期重置 if (_thisDateTime>self.today.getTime() && _thisDay == self.todayDate) { $(item).addClass("active"); self.currentDate = _thisDate; } }); }; //设置当前日期 DatePicker.prototype.setCurrentDate = function(date) { this.tempActiveDate.setDate(date); this.currentDate = this.tempActiveDate.getDate(); this.renderCalendarData(); if(this.opts.updateCallback){ this.opts.updateCallback.call(null,this.currentDate); } };
js完整代码
function DatePicker() { this.opts = null; this.today = new Date(); //今天 this.todayDate=this.today.getDate(); this.currentDate = new Date(); //当前选中日期 } DatePicker.prototype.init = function(opts) { var opts = $.extend({ 'min_date':"1970-01-01", "yearOffset": 20//默认往前推20年 }, opts || {}); this.opts = opts; this.renderCalendar(); this.bindEvent(); }; DatePicker.prototype.bindEvent = function() { var self = this; self.opts.container.on("change", ".year-select", function() { self.renderSelectedDate(); }); //选中月份 self.opts.container.on("change", ".month-select", function() { self.renderSelectedDate(); }); //下一月 self.opts.container.on("click", ".next-btn", function(e) { e.stopPropagation(); var cur_date =self.currentDate.setMonth(self.currentDate.getMonth()+1);; self.setCurrentDate(cur_date); }); //上一月 self.opts.container.on("click", ".prev-btn", function(e) { e.stopPropagation(); var cur_date = self.currentDate.setMonth(self.currentDate.getMonth()-1); self.setCurrentDate(cur_date); }); //选择日历中某一天 self.opts.container.on("click", ".date-item", function() { if (!$(this).hasClass("disabled")) { var _day = $(this).attr("date"); var cur_date = self.currentDate.setDate(_day); self.setCurrentDate(cur_date); } }); }; //临时被选中的日期 DatePicker.prototype.tempActiveDate=(function(){ var _date=new Date(); return { getDate: function() { return _date; }, setDate:function(date){ _date=new Date(date); } }; })(); //设置下拉框选中的日期 DatePicker.prototype.renderSelectedDate = function() { var _year = this.opts.container.find(".year-select").val(); var _mOnth= this.opts.container.find(".month-select").val(); var _day = this.currentDate.getDate(); var cur_date = new Date(_year, _month, _day); this.setCurrentDate(cur_date); }; //渲染日历框架 DatePicker.prototype.renderCalendar = function() { var calendar_header = this.renderHeader(); var calendar_days = '
日 | 一 | 二 | 三 | 四 | 五 | 六 |
---|---|---|---|---|---|---|
开始日期
结束日期
HTML:
CSS
* { margin: 0; padding: 0; } body{font:14px "微软雅黑";} li { list-style: none; } .ui-datepicker{ display: inline-block; position: relative; } .ui-calendar { margin: 10px; width: 260px; } .single-calendar{ border:1px solid #ccc; text-align: center; box-shadow: 0 0 3px rgba(0,0,0,0.25); } .ui-calendar select { padding: 3px 10px; margin: 0 10px; } .calendar_header { margin: 10px 0; text-align: center; } .calendar-table { border-collapse: collapse; } .calendar-table td { padding: 5px 10px; cursor: pointer; text-align: center; border-radius:3px; } .calendar-table td.today { color: #337ab7; } .calendar-table td.active { background: #337ab7; color:#fff; } .calendar-table td.disabled { color: #ccc; cursor: default; } .ui-calendar .next-btn, .ui-calendar .prev-btn { padding:1px 4px; border:1px solid transparent; border-radius:3px; font-weight: bold; cursor: pointer; } .ui-calendar .next-btn:hover,.ui-calendar .prev-btn:hover{ border-color:#ccc; box-shadow: 0 0 3px rgba(0,0,0,0.25); } .ui-daterangepicker-wrap { position: absolute; top:0; width: 740px; border: 1px solid #ccc; border-radius:3px; box-shadow: 0 0 3px rgba(0,0,0,0.25); background: #fff; overflow: hidden; z-index:1000; display: none; } .calendar-title{ text-align: center; } .ui-daterangepicker-wrap .ui-calendar { float: left; } .ui-daterangepicker-range{ width: 150px; float: right; margin: 10px; } .ui-daterangepicker-range ul{ margin-bottom:20px; } .ui-daterangepicker-range li { margin:5px 0; padding: 5px 10px; border-radius:3px; background: #f5f5f5; cursor: pointer; } .ui-daterangepicker-range li:hover,.ui-daterangepicker-range li.active { background: #337ab7; color:#fff; } .ui-daterangepicker-range .range-btn{ width:60px; height: 30px; margin-right: 10px; border:1px solid #e5e5e5; border-radius:3px; background: none; cursor: pointer; } .ui-daterangepicker-range .range-confirm{ background: #337ab7; border-color:#337ab7; color:#fff; }
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持!