这次开始的项目是PC版的,貌似有2年没正儿八经的折腾PC端了。
言归正传,这次功能 中有个选择日期段的功能 ,本来不麻烦的事情,但是PM非要参照另外一个 网站的效果 来做,把别人代码 扒下来一看,我去,08年的插件 ,很多功能 不能满足当前,PM非要那效果 ,时间又TM有限,就又找了个国外的插件 datera ngepicker,基于bootstrap,跟需求长得很像,功能 非常强大,需求都能满足,但是...但是,PM和测试说不好用。。。折腾了半天源代码 ,优化了下,时间来不及只能凑合用着。
重新动手写了个。依赖jquery和moment.js(主要处理日期,如果自己处理也可以不需要),
先看效果 图
rush:js;">
var da
tera ngepicker = new Da
tera ngePicker();
da
tera ngepicker.init({
"ele": $("#da
tera nge"),"pos":"left","min_date": "1990-01-01","format": "YYYY:MM:DD","updateDateFn":function(){
console.log(da
tera ngepicker.getDate())
}
});
基本思路是:
rush:js;">
function Da
tera ngePicker() {
this.start_picker = null;
this.end_picker = null;
}
初始化日期构造函数 ,日期段由两个单独的日期选择组成,当起始日期和结束日期变化时要调用 构造函数 的updateDate方法 ,通知 日期发生了变化。
rush:js;">
Da
tera ngePicker.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"),"updateCallback": function(){
self.updateDate();
}
});
this.bindEvent();
};
处理日期发生变化的情况,比如起始日期大于结束日期,要进行互换。
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-da
tera ngepicker-range li").removeClass("active");
self.opts.updateDateFn.call(null,this.getDate());//日期更新后重新
获取 当前的起始和结束日期
};
获取 起始和结束日期
rush:js;">
//
获取 起始日期和结束日期段,起始日期若大于结束日期则互换
Da
tera ngePicker.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
};
};
提供动态设置当前起始日期和结束日期的方法
rush:js;">
//设置起始日期和结束日期
Da
tera ngePicker.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();
};
创建一个 容器,因为日期选择要刚好在日期文本框下面,在日期文本框外面包一层方便定位。
rush:js;">
//创建日期段容器
Da
tera ngePicker.prototype.createCalendarWrap = function() {
var $parent=this.opts.ele.parents(".ui-datepicker");
var h=$parent.height(),w=$parent.width();
var wrap = '
terangepicker-wrap" style="top:'+h+'px;'+this.opts.pos+':0">
' +
'
' +
'
terangepicker-range">
' +
'' +
' ' +
' ' +
' ' +
' ' +
'
';
$parent.append(wrap);
};
接下来是单个日期选择的处理
定义构造函数 和初始化
rush: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();
};
事件处理
rush:js;">
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("
dis abled")) {
var _day = $(this).attr("date");
var cur_date = self.currentDate.setDate(_day);
self.setCurrentDate(cur_date);
}
});
};
定义临时存储的当前日期,默 认日期是今天,但是选择的时候当前日期会变化。
rush:js;">
//临时被选中的日期
DatePicker.prototype.tempActiveDate=(function(){
var _date=new Date();
return {
getDate: function() {
return _date;
},setDate:function(date){
_date=new Date(date);
}
};
})();
年月下拉框变化时更新日期
rush:js;">
//设置下拉框选中的日期
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行,星期从一到天
rush:js;">
//渲染日历框架
DatePicker.prototype.renderCalendar = function() {
var calendar_header = this.renderHeader();
var calendar_days = '
日一 二 三 四 五 六 ';
var calendar_body = '
渲染日历的头部,包括 上月、下月按钮,年月的下拉框
=min_year?current_year - this.opts.yearOffset:min_year;//下拉框起始年份
var yearSelect="";
//如果已经是最小日期,
不显示 上月按钮
if (current_year <= min_year && current_month <= 0) {
yearSelect+='
' + i + '';
} else {
yearSelect += '';
}
}
yearSelect += ' ';
var monthSelect = '
disabled";
}
}else{
state="dis abled";
}
monthSelect += '' + monthArr[i] + '月 ';
}
if (current_year >= _year && current_month+1 >= _month) {
monthSelect += ' ';
}else{
monthSelect += '
';
}
return "";
};
self.today.getTime()) {
$(item).addClass("
dis abled").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);
}
};
rush: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",opts || {});
this.opts = opts;
this.renderCalendar();
this.bindEvent();
};
DatePicker.prototype.bindEvent = function() {
var self = this;
self.opts.container.on("change",function() {
if (!$(this).hasClass("
dis abled")) {
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,_day);
this.setCurrentDate(cur_date);
};
//渲染日历框架
DatePicker.prototype.renderCalendar = function() {
var calendar_header = this.renderHeader();
var calendar_days = '
日一 二 三 四 五 六 ';
var calendar_body = '
=min_year?current_year - this.opts.yearOffset:min_year;//下拉框起始年份
var yearSelect="";
//如果已经是最小日期,
不显示 上月按钮
if (current_year <= min_year && current_month <= 0) {
yearSelect+='
' + i + '';
} else {
yearSelect += '';
}
}
yearSelect += ' ';
var monthSelect = '
disabled";
}
}else{
state="dis abled";
}
monthSelect += '' + monthArr[i] + '月 ';
}
if (current_year >= _year && current_month+1 >= _month) {
monthSelect += ' ';
}else{
monthSelect += '
';
}
return "";
};
//渲染日历数据
DatePicker.prototype.renderCalendarData = function() {
var self = this;
var _year = this.currentDate.getFullYear(); //当前年
var _month = this.currentDate.getMonth() + 1; //当前月
var _f
irs tDay = new Date(_year,this.currentDate);
}
};
//日期段由两个单独日期实例组成
function Datera ngePicker() {
this.start_picker = null;
this.end_picker = null;
}
Datera ngePicker.prototype.init = function(opts) {
var self = this;
this.opts = $.extend({
"pos":"left",//最小日期
"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"),"updateCallback": function(){
self.updateDate();
}
});
this.bindEvent();
};
Datera ngePicker.prototype.bindEvent = function() {
var self = this;
var start_picker = self.start_picker,end_picker = self.end_picker;
this.opts.ele.on("focus",function(){
self.$wrap.find(".ui-datera ngepicker-wrap").show();
});
$(".ui-datera ngepicker-range").on("click","[range-key]",function() {
var _year = start_picker.currentDate.getFullYear();
var _month = start_picker.currentDate.getMonth();
var range = $(this).attr("range-key");
var start_day = start_picker.todayDate,end_day = end_picker.todayDate
switch (range) {
case "今日":
start_day = new Date(moment());
break;
case "昨日":
start_day = new Date(moment().subtract(1,'days'));
break;
case "最近7日":
start_day = new Date(moment().subtract(6,'days'));
break;
case "最近30日":
start_day = new Date(moment().subtract(30,'days'));
break;
}
self.setDate(start_day,new Date())
$(this).addClass("active").siblings("[range-key]").removeClass("active");
});
$("html").on("click",function(e){
var $target=$(e.target);
if($target.closest(".ui-datera ngepicker-wrap").length==0&&$target[0]!=self.opts.ele[0]){
self.$wrap.find(".ui-datera ngepicker-wrap").hide();
}
});
};
Datera ngePicker.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-datera ngepicker-range li").removeClass("active");
self.opts.updateDateFn.call(null,this.getDate());
};
//获取 起始日期和结束日期段,"end_date": end_date
};
};
//设置起始日期和结束日期
Datera ngePicker.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();
};
//创建日期段容器
Datera ngePicker.prototype.createCalendarWrap = function() {
var $parent=this.opts.ele.parents(".ui-datepicker");
var h=$parent.height(),w=$parent.width();
var wrap = '<div class="ui-datera ngepicker-wrap" style="top:'+h+'px;'+this.opts.pos+':0"><div class="ui-calendar"><p class="calendar-title">开始日期
<div class="calendar-container">
' +
'<div class="ui-calendar"><p class="calendar-title">结束日期<div class="calendar-container2">