愉快的三天

场景:

两级弹框,第一级是bootstrap的modal,里面有一个jqgrid,第二级是jqgrid添加记录的弹框

第二级弹框中的textarea在IE9中不能换行,而在chrome中可以


Day 1

bootstrap的modal和jqgrid全部在实验室环境中搭建起来,比较麻烦,先考虑别的办法

因为IE9调试工具太弱了,看看firefox有没有同样的问题

发现firefox中的问题是textarea不能聚焦

以前遇到过不能获得焦点的问题,跟tabindex有关,把tabindex删掉,没作用

发现一级弹框中加了元素级别的textarea样式,删掉,没作用

因为这个框是jqgrid弹出来的,查看jqgrid源码,有没有劫持回车事件,没有

firefox中逐个删除页面元素,发现可以让textarea获得焦点,可能是元素的问题

把一级对话框内中的jqgrid删掉,再用控制台命令添加纯html二级弹框,还是有问题,说明不是jqgrid的问题

考虑到删除元素会改变子元素的样式,可能是样式问题

firefox中删除所有样式,发现可以获得焦点了,是样式问题

逐步缩小范围,发现是一级弹框有一个行内样式所致,删掉后,可以获得焦点了

但是在IE9中仍然不可换行

解决了firefox不能聚焦的问题


Day 2

现在Chrome和Firefox都没问题了,只好硬着头皮用IE9调试了,鉴于昨天的结论,先从样式角度考虑

发现一级弹框去掉所有样式,就可以换行了

但是聚焦不到特定的某一条样式上,怀疑是脏乱的样式加成结果导致CSS解析器出错了

发现在错误的样式下,只要隐藏对话框也是可换行的,可能是浏览器计算位置时出错了

因为bootstrap样式层叠的太多了,既然不知道哪个样式是错的,那就用正确的样式手写生成原来的样子,也是个办法

生成过程中发现其他样式都去掉,display:block;position:fixed;z-index:1030;就能复现问题,可能是浏览器计算z-index错了

用IE9调试工具修改页面源码,就没问题了。因为页面重绘,重新计算了位置,也可能是事件都删掉了

页面太乱了,清理一下,把页面杂乱的标签都删掉,尤其是script片段,没作用

把link标签都删掉,没问题了。应该是某个样式表的问题,定位到是bootstrap.css或ui.jqgrid.css的问题,这两个删一个问题就复现

把一级弹框的所有父元素保留,删除页面中所有其他的html,问题还存在。但是IE9调试工具中点Refresh就没问题了,IE9调试工具不可靠

不能过度依赖调试工具了,得想办法把本地服务器端运行起来,不然剩下的办法只能是实验室环境中把网页重新静态构建起来了

找到一个可行的解决方案,弹出第二级对话框时,把第一级隐藏掉


Day 3

搭建本机环境,把服务器端运行起来

删掉一级弹框中的所有代码,控制台命令弹出二级纯html弹框,没作用

先用控制台命令弹出二级纯html弹框,再在页面点击弹出一级弹框,没作用

控制台命令弹出二级纯html弹框,再控制台命令弹出一级纯html弹框,好了,应该是一级弹框弹出的过程中做了什么

发现是bootstrap的modal('show')这条语句弹出的框有问题

因为IE9不容易跟源码,所以先不看源码,在实验室环境中,造一个一模一样modal,然后二级弹框果然出问题了,并且firefox和chrome都无法获得焦点

实验室环境中复现了问题,问题快解决了

找到bootstrap的modal插件的官方例子,弹出二级弹框,没问题

对比有问题的代码,发现只要modal-body中包含<button>就能复现问题,定位为bootstrap的问题

考虑解决方案,把服务器中的所有button都换成div,还是有问题,而实验室没问题,说明IE9不太稳定

控制台删掉所有的button,结果好了

看看是哪个button影响的,发现总是最后一个button影响的

用补丁方式,先造一个隐藏的button,然后载入时模拟控制台删掉它,没作用。但是控制台删掉它,就有作用,不稳定

不看modal的源码不行了

为了能调试进源码中,换Chrome跟进bootstrap源码,再到IE9看效果

先把modal函数中代码全删了,果然问题没了,然后逐个功能还原,寻找复现问题的临界点

发现enforceFocus这样的方法,是为了强制让对话框获得焦点,感觉就是这个了

把这个方法注掉,没作用,看看实现,就是先解绑一个自定义聚焦事件再绑定这个自定义聚焦事件

在事件中写log,果然点击textarea,就触发这个自定义事件

把事件中把强制获得焦点的代码删掉,好了,这应该就是问题所在了

考虑解决方案,enforceFocus只是进行解绑和绑定事件,而事件是点击textarea时触发的,那就让它只解绑不绑定

分析源码,enforceFocus引用是Modal.prototype中的方法,而Modal是$.fn.modal.constructor,因此是在源码外改的

尽量不动源码,在源码之外加补丁

chrome和firefox在实验室环境中,textarea是不能获得焦点的,但是网站中可以,原因未知

通过覆盖自动聚焦事件,解决了问题


困难

IE9的调试工具太差,Chrome调试工具虽好,但是Chrome没有问题

bootstrap大量的样式名污染的全局空间,每一个元素有大量冗余的层叠样式

很多事件可能是跟样式名相关联的,删了样式名会影响事件

前两天本机环境没有搭建好,只能通过浏览器调试

第三方库用了什么黑魔法,不知道

页面太杂乱,script片段遍布各处,到处是动态加载但不清理的内容

setTimeout乱用,至少二十处setTimeout,js执行过程紊乱

两层弹框,第一级弹框中还能进行内容tab切换,影响因素比较多

项目代码的问题写的太差,互相依赖,很难对功能进行隔离,不能以功能模块为单位进行测试

二级弹框并不是一级弹框的子元素,而是body的子元素,与一级弹框的位置相距很远,从直觉上很难发现有关联


优势

电脑配置不错,两个显示器,16G内存装了虚拟机可以模拟IE8-11,Edge

没有时间压力,没人催我,没有别的项目或会议打断我

服务器端同事配合,没有怀疑我的能力

bootstrap和jqgrid源码不是太烂

这不是一个偶现的bug,没次都能出现,难度降低了不少


误区

其实IE的问题并不是那么多,更多的是可见代码的问题

黑盒试错,不如静下心来跟进源码看看原理

不能过度依赖调试工具的结论

可以通过改动来试错的代码越多,排除假设的机会就越大