datepicker时间范围选择器兼容ie8
简单说明
这是我第一次写博客,其实自己接触前端时间不久,写出来的东西可能比较浅薄,只是希望把自己在项目中遇到的问题和困难,都记录下来。虽然可能对于大家来说都不是困难和问题。好啦,废话不多说,开始。
datepicker的使用
项目中遇到的要选择时间范围的需求,并且要求界面是这样的。
首先想到的就是使用两个datepicker来实现。
下面展示html代码片
.
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="format-detection" content="telephone=no" />
<title>datepicker使用</title>
<!-- Bootstrap -->
<link href="./css/bootstrap.min.css" rel="stylesheet" />
<link href="./css/font-awesome.min.css" rel="stylesheet">
<!-- lulu ui -->
<link href="./css/ui.css" rel="stylesheet" />
<!-- custom -->
<link href="./css/custom.css" rel="stylesheet" />
<link href="./datepicker/datepicker3.css" rel="stylesheet" />
</head>
<body id="container_list">
<div style="padding-top: 10px;padding-left: 10px;">
<div class="f_fl" style="width:400px;">
<span for="remoteIp" class="labelW" style="width: 80px;">查询日期</span>
<span class="ui-input ui-date-range-input label-content" style="width: 320px;">
<div class="input-group f_fl date" style="width:153px;">
<div class="input-group-addon">
<i class="fa fa-calendar"></i>
</div>
<input type="text" autocomplete="off" class="form-control pull-right" id="datestart">
</div>
<span class="f_fl" style="width:4%;text-align:center;line-height:34px;">-</span>
<div class="input-group f_fl date" style="width:153px;">
<div class="input-group-addon">
<i class="fa fa-calendar"></i>
</div>
<input type="text" autocomplete="off" class="form-control pull-right" id="dateend">
</div>
</span>
</div>
</div>
<!-- jquery -->
<script src="./js/jquery1.8.js" type="text/javascript"></script>
<!-- 日期 -->
<script src="./datepicker/bootstrap-datepicker.js"></script>
<script src="./datepicker/locales/bootstrap-datepicker.zh-CN.js"></script>
<!-- index -->
<script src="./js/statisticPage.js" type="text/javascript"></script>
</body>
</html>
样式我使用了luluui的样式,可以下载luluui的包。自己写的样式很简单。
css代码片
.
.f_fl {
float: left;
}
.labelW {
width: 80px;
float: left;
text-align: right;
line-height: 34px;
padding-right: 10px;
}
重点就是js的代码了。
一开始我的js代码是这样的。
1.需求是只能选择到半年前的时间,所以startDate的时间设置成了半年前。
2.时间范围选择要符合常理,所以可以使用changeDate来控制。
js代码片
.
// 显示日历
$('#datestart').datepicker({
autoclose: true,
language: 'zh-CN',
format: 'yyyy-mm-dd',
showMeridian: true,
initialDate: new Date(),
todayHighlight: true,
forceParse: true,
clearBtn: false, //清除按钮
endDate: new Date(),
startDate: new Date(new Date().getTime() - 1000 * 60 * 60 * 24 * 182),
}).on('changeDate', function (ev) {
if ($('#dateend').val()) {
var selDate = new Date(ev.date);
var enDate = new Date($('#datestart').val());
var slYear = selDate.getFullYear();
var slMonth = selDate.getMonth();
var slDate = selDate.getDate();
var enYear = enDate.getFullYear();
var enMonth = enDate.getMonth();
var enDa = enDate.getDate();
if (slYear != enYear || slMonth != enMonth || slDate != enDa) {
if (new Date(ev.date).getTime() - new Date(($('#dateend').val())).getTime() > 0) {
var newStartTime = new Date($('#dateend').val()).getTime() - 1000 * 60 * 60 * 24
$('#datestart').datepicker('setDate', new Date(newStartTime))
}
}
}
});
$('#dateend').datepicker({
autoclose: true,
language: 'zh-CN',
format: 'yyyy-mm-dd',
showMeridian: true,
initialDate: new Date(),
todayHighlight: true,
forceParse: true,
clearBtn: true, //清除按钮
startDate: new Date(new Date().getTime() - 1000 * 60 * 60 * 24 * 182),
endDate: new Date(),
})
.on('changeDate', function (ev) {
if ($('#datestart').val()) {
var selDate = new Date(ev.date);
var stDate = new Date($('#datestart').val());
var slYear = selDate.getFullYear();
var slMonth = selDate.getMonth();
var slDate = selDate.getDate();
var stYear = stDate.getFullYear();
var stMonth = stDate.getMonth();
var stDa = stDate.getDate();
if (slYear != stYear || slMonth != stMonth || slDate != stDa) {
if (new Date(ev.date).getTime() - new Date($('#datestart').val()).getTime() < 0) {
var newEndTime = new Date($('#datestart').val()).getTime() + 1000 * 60 * 60 * 24
$('#dateend').datepicker('setDate', new Date(newEndTime))
}
}
}
});
//设置默认值
function setDefaultTime() {
var dateTime = new Date();
var year = dateTime.getFullYear();
var month = dateTime.getMonth() + 1;
var day = dateTime.getDate();
today = year + '-' + month + '-' + day;
$('#datestart,#dateend').datepicker('setDate',new Date(today)); //设置默认日期
}
setDefaultTime();
这样时间插件基本可以使用,但是在ie浏览器在下:
1.时间是没有初始化。
2.changeDate似乎没有生效。原因是因为ie下,new Date不支持“-”形式的日期。于是我们把“-”替换成“/”。
把js代码修改一下:
1.setDefaultTime函数里面的初始化修改:
$('#datestart,#dateend').datepicker('setDate',new Date(today)); //设置默认日期
改成:
$('#datestart').val(today);
$('#dateend').val(today);
2.changeDate里面进行修改(记得只要有*newDate()*地方都要修改):
var stDate = new Date($('#datestart').val());
改成:
var str = $('#datestart').val();
var stDate = new Date(str.replace(/-/g, '/'));
为了不影响其他浏览器的使用,可以专门做一个ie浏览器的判断,只有ie才执行替换。
js代码片
.
// 显示日历
$('#datestart').datepicker({
autoclose: true,
language: 'zh-CN',
format: 'yyyy-mm-dd',
showMeridian: true,
initialDate: new Date(),
todayHighlight: true,
forceParse: true,
clearBtn: false, //清除按钮
endDate: new Date(),
startDate: new Date(new Date().getTime() - 1000 * 60 * 60 * 24 * 182),
}).on('changeDate', function (ev) {
if ($('#dateend').val()) {
var selDate = new Date(ev.date);
var str = $('#dateend').val();
var enDate = new Date(str.replace(/-/g, '/'));
var slYear = selDate.getFullYear();
var slMonth = selDate.getMonth();
var slDate = selDate.getDate();
var enYear = enDate.getFullYear();
var enMonth = enDate.getMonth();
var enDa = enDate.getDate();
var testBrowser = appInfo();
var browerName = testBrowser.appname;
var exite = browerName.indexOf("ie");
// 若包含msie则返回0 不包含返回-1,
if (exite == -1) {
if (slYear != enYear || slMonth != enMonth || slDate != enDa) {
if (new Date(ev.date).getTime() - new Date(($('#dateend').val())).getTime() > 0) {
var newStartTime = new Date($('#dateend').val()).getTime() - 1000 * 60 * 60 * 24
$('#datestart').datepicker('setDate', new Date(newStartTime))
}
}
} else {
// 执行下一步
if (slYear != enYear || slMonth != enMonth || slDate != enDa) {
if (new Date(ev.date).getTime() - new Date($('#dateend').val().replace(/-/g, '/')).getTime() > 0) {
var newStartTime = new Date($('#dateend').val().replace(/-/g, '/')).getTime() - 1000 * 60 * 60 * 24
$('#datestart').datepicker('setDate', new Date(newStartTime))
}
}
}
}
});
function appInfo() {
var browser = {
appname: 'unknown',
version: 0
},
userAgent = window.navigator.userAgent.toLowerCase(); // 使用navigator.userAgent来判断浏览器类型
//msie,firefox,opera,chrome,netscape
if (/(msie|firefox|opera|chrome|netscape)\D+(\d[\d.]*)/.test(userAgent)) {
browser.appname = RegExp.$1;
browser.version = RegExp.$2;
} else if (/version\D+(\d[\d.]*).*safari/.test(userAgent)) { // safari
browser.appname = 'safari';
browser.version = RegExp.$2;
}
return browser;
}
最重要的修改
到这里,你在ie8下你会发现一个bug,一旦选择的结束值小于开始值的时候,或者开始值大于结束值时,输入框内会出现两个值,就类似这样:
结束值小于开始值:
开始值小于结束值:
这是因为bootstrap-datepicker.js里面的getFormattedDate函数:
getFormattedDate: function(format){
if (format === undefined)
format = this.o.format;
var lang = this.o.language;
return $.map(this.dates, function(d){
return DPGlobal.formatDate(d, format, lang);
}).join(this.o.multidateSeparator);
},
假设有一个开始日期“2020-05-26”,现在选择结束日期为“2020-05-25”。
1.在谷歌浏览器下,会先进行一次“2020-05-25”的赋值选择,然后在做onchang的判断,选择为符合规范的“2020-05-26”。
2.在ie下,this.dates里面会存两个值,“2020-05-25”和“2020-05-26”,因此显示在界面上的就是两个值。
我们只需要修改一下代码,就不会出现了:
getFormattedDate: function(format){
if (format === undefined)
format = this.o.format;
var lang = this.o.language;
var arr = [];
arr.push(this.dates[this.dates.length-1])
return $.map(arr, function(d){
return DPGlobal.formatDate(d, format, lang);
}).join(this.o.multidateSeparator);
},
这样就实现了datepicker兼容ie8。