今天做运营后台处理IE浏览器问题时,发现bootstrap-datetimepicker这个插件,在IE8中总是闪退,选不了时间,害得我折腾了一天,才想到解决方案,记录一下。
引入插件:
bootstrap-datetimepicker.css
moment-with-locales.min.js
bootstrap-datetimepicker.js
<input size="10" name="user_birth" type="text" id="user_birth" value="" readonly class="form_datetime">
刚开始我以为是IE不支持datetimepicker里面的方法,想着去换个版本试试。
http://www.bootcdn.cn/bootstrap-datetimepicker/
http://eonasdan.github.io/bootstrap-datetimepicker/Changelog/
下载了最新版本的4.17.37和4.0.0,因为在版本记录中看到这一句话,感觉像是解决这个问题的,于是一试。
4.0.0
Changes for using the component
-
hide()
,show()
,toggle()
,enable()
,disable()
and the rest of setter functions now support chaining.
结果引入后,各种报错,但都是js函数(trim、reduce、indexOf)不支持导致,如果是多个函数组合的语句,则可单个删除每个试一下。此外有介绍
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
解决办法:
String.prototype.trim=function(){return this.replace(/(^\s*)|(\s*$)/g,"");}
if (!Array.prototype.reduce) { Array.prototype.reduce = function(callback) { 'use strict'; if (this == null) { throw new TypeError('Array.prototype.reduce called on null or undefined'); } if (typeof callback !== 'function') { throw new TypeError(callback + ' is not a function'); } var t = Object(this), len = t.length >>> 0, k = 0, value; if (arguments.length == 2) { value = arguments[1] } else { while (k < len && !(k in t)) { k++ } if (k >= len) { throw new TypeError('Reduce of empty array with no initial value'); } value = t[k++] } for (; k < len; k++) { if (k in t) { value = callback(value, t[k], k, t) } } return value } }; if (!Array.prototype.indexOf) Array.prototype.indexOf = function(elt) { var len = this.length >>> 0; var from = Number(arguments[1]) || 0; from = (from < 0) ? Math.ceil(from) : Math.floor(from); if (from < 0) from += len; for (; from < len; from++) { if (from in this && this[from] === elt) return from } return -1 };结果辛辛苦苦解决了函数问题,还是不行,我心已碎...
没办法了,已经折腾几小时了,再不解决,这周日过来加班又白忙活了,且问题又没有解决。
只能慢慢调试了,万恶的IE,调试好麻烦...
终于找到问题所在了,在点了user_birth之后,其实是有弹出日历框,但是马上又消失了,开始在插件bootstrap-datetimepicker.js中找hide相关的代码,在line 1277行左右如下:
picker.hide = function (e) {
...
picker.widget.hide();
...
应该就是这行代码引起的了,可是chrome也是同段代码呀,怎么不闪退呢,于是在这里断点,发现IE在日历出来后,准备去选择日期时马上跳进来了,哪里引起的呢?搜索picker.hide(),在line 906处有
'blur': $.proxy(picker.hide, this)
看样子是绑定的blur事件,原来选日期时直接触发了user_birth的blur事件,无法理解怎么会去触发这个事件,
http://love2java.iteye.com/blog/436915
上面有介绍,“输入框的blur事件发生在其它控件focus事件之前,所以在blur事件中设置的其它控件获取焦点无效,目前无法做到兼容。”
那怎么解决呢,想到可以用计数器手动去控制hide,于是在插件中加了一个参数
line 76 var dpgId = 0,ieflag = 0, //ieflag为添加的
在picker.hide函数内将原来的picker.widget.hide();
替换为:
if ((navigator.userAgent.indexOf('MSIE') >= 0)
&& (navigator.userAgent.indexOf('Opera') < 0)){
// alert('你是使用IE');
if(++ieflag > 1){
picker.widget.hide();
ieflag = 0;
}
}else{
picker.widget.hide();
}
因为只是IE的问题,故针对IE特殊处理。
OK了吗?看似解决了,于是开心地去测试一下,结果IE里面选择了日期,再点空白处后datetimepicker不能自动隐藏了,这可咋整,除非选择日期后,再点击一次input,再点空白处,让其触发一次blur事件,这样不科学呀,体验何来。
后来想了一个暂时的办法,绑定body.click事件,触发blur事件。在head加入
if ((navigator.userAgent.indexOf('MSIE') >= 0) && (navigator.userAgent.indexOf('Opera') < 0)){
$('body').click(function(){
$('.form_datetime').blur();
});
先顶用一下,后面再看看有没有更好的办法,毕竟这样依赖body点击事件太不靠谱了。
发表评论