2008-05-09
西方人通常发现不了的一个IE的bug
关键字: ie focus bug
这个问题我大概在一年多以前在某个用到VML的页面中(当时倒是记录了VML的一个严重问题)首次发现了这个Bug。经过一番狗狗之后,也未发现有同样的报告。后来我又逐渐在几种其他非VML的情形下重现了这个奇异的Bug。经过一番探究,我大致推断出了这个bug的原因。不过我一直没有公开发布过这个有趣的问题,只是跟少数同事提到过它。这个bug有个有趣的特点,就是西方人通常不会碰到这个bug。
最近,真懒同学(realazy)在《认识延迟时间为 0 的 setTimeout》一文中举例说明setTimeout的用途。代码大意如下:
在IE中,新创建的input没有如预期的获得焦点。
如果把input.focus()放在一个setTimeout中延时执行,则就可以获得焦点。
这个例子本身其实并不能证明realazy想要说明的观点,因为他不小心碰到了一个IE的微妙bug。在留言中,Lunatic Sun倒是敏锐的判断出这是IE的bug,只是这个bug的本质不是那么容易认识到,它其实并不是onmousedown本身的bug。
实际上,这是IE的focus机制的bug。
IE中的所有元素其实并不是被凭空绘制出来的,而是统统基于已有的Windows控件之上。除了典型的按钮、下拉菜单等,普通的div其实也是一个textbox控件。
所以IE的HTML focus等实际是被转换为windows控件的focus,于是在IE中存在两种不同层次的focus机制。理想上,HTML的focus应该被同步转换为windows控件的focus,然而IE可怜的代码导致这种转换存在许多bug。我们经常遇到的焦点虚线框丢失的问题其实就是一个例子。
实际上,在上面的例子中,表面上input没有得到焦点,但是其实调用focus()之后,HTML focus确实已经到了新生成的input中,这一点你可以通过document.activeElement来验证,你也可以按tab和shift-tab观察焦点的切换来证明这一点。然而,由于mousedown事件默认会获得控件焦点,所以windows控件focus就跑回了你的按钮上面了。这里出现了windows focus机制和html focus机制的脱节。显然IE在focus上的同步代码实在是太脆弱了。
事实上,IE对焦点的控制似乎本来就不和逻辑。所有的hasLayout元素都能获得焦点!结果一个页面上大部分区域在mousedown之后焦点就不知跑到哪个元素上了——这显然不是我们想要的行为——合乎HTML规范逻辑的行为应该是只有交互控件,如表单控件和A元素等,才能获得焦点。这导致一个典型的用户体验问题:在一个限制高度的可卷动区域中(例如一个长表单),拖动scrollbar,控件焦点就丢失——实际焦点跑到scrollbar所在的元素(例如form元素)上了。最严重的是,body元素一般总会有scrollbar!为了缓解这个问题,微软为body元素打了补丁,使得body上的scrollbar不会抢走焦点。然而IE这个patch打得实在是太烂了,在标准模式下,canvas从body变成了html元素,所以页面scrollbar就到了html元素上,结果bug又回来了!
撇开抢焦点问题,我们回到前面的话题。
既然html focus还是在input元素上,那么当时windows控件焦点到底跑哪里去了?实际上这个焦点跑到了mousedown所发生的对象上。比如如果是一个input按钮,焦点就会在该input按钮实际对应的windows的Button控件上。不过button元素的实现和一般的input不同,所以button元素上的mousedown之后,windows控件焦点实际上会跑到button元素外层的那个元素所对应的windows控件(通常是TextBox控件)中。
如何证明这一点?我过去用过一个调试工具可以显示出每个html控件实际的windows控件,也能查看实际的windows系统焦点。不过现在想不起来那个工具的名称了。搞笑的是,此处还会出现一个非常orz的症状——也就是本文标题所称的“西方人通常发现不了的一个IE的bug”——可以证明这一点。
focus问题 + 西方人通常发现不了。各位是否已经猜到了呢?大家不妨用realazy的那个页面中的第一个按钮来直接实验一把。
我会在下篇blog中继续聊这个话题。
最近,真懒同学(realazy)在《认识延迟时间为 0 的 setTimeout》一文中举例说明setTimeout的用途。代码大意如下:
$('myButton').onmousedown = function () {
var input = document.createElement('input');
input.type = 'text';
$('myDiv').appendChild(input);
input.focus();
}
在IE中,新创建的input没有如预期的获得焦点。
如果把input.focus()放在一个setTimeout中延时执行,则就可以获得焦点。
这个例子本身其实并不能证明realazy想要说明的观点,因为他不小心碰到了一个IE的微妙bug。在留言中,Lunatic Sun倒是敏锐的判断出这是IE的bug,只是这个bug的本质不是那么容易认识到,它其实并不是onmousedown本身的bug。
实际上,这是IE的focus机制的bug。
IE中的所有元素其实并不是被凭空绘制出来的,而是统统基于已有的Windows控件之上。除了典型的按钮、下拉菜单等,普通的div其实也是一个textbox控件。
所以IE的HTML focus等实际是被转换为windows控件的focus,于是在IE中存在两种不同层次的focus机制。理想上,HTML的focus应该被同步转换为windows控件的focus,然而IE可怜的代码导致这种转换存在许多bug。我们经常遇到的焦点虚线框丢失的问题其实就是一个例子。
实际上,在上面的例子中,表面上input没有得到焦点,但是其实调用focus()之后,HTML focus确实已经到了新生成的input中,这一点你可以通过document.activeElement来验证,你也可以按tab和shift-tab观察焦点的切换来证明这一点。然而,由于mousedown事件默认会获得控件焦点,所以windows控件focus就跑回了你的按钮上面了。这里出现了windows focus机制和html focus机制的脱节。显然IE在focus上的同步代码实在是太脆弱了。
事实上,IE对焦点的控制似乎本来就不和逻辑。所有的hasLayout元素都能获得焦点!结果一个页面上大部分区域在mousedown之后焦点就不知跑到哪个元素上了——这显然不是我们想要的行为——合乎HTML规范逻辑的行为应该是只有交互控件,如表单控件和A元素等,才能获得焦点。这导致一个典型的用户体验问题:在一个限制高度的可卷动区域中(例如一个长表单),拖动scrollbar,控件焦点就丢失——实际焦点跑到scrollbar所在的元素(例如form元素)上了。最严重的是,body元素一般总会有scrollbar!为了缓解这个问题,微软为body元素打了补丁,使得body上的scrollbar不会抢走焦点。然而IE这个patch打得实在是太烂了,在标准模式下,canvas从body变成了html元素,所以页面scrollbar就到了html元素上,结果bug又回来了!
撇开抢焦点问题,我们回到前面的话题。
既然html focus还是在input元素上,那么当时windows控件焦点到底跑哪里去了?实际上这个焦点跑到了mousedown所发生的对象上。比如如果是一个input按钮,焦点就会在该input按钮实际对应的windows的Button控件上。不过button元素的实现和一般的input不同,所以button元素上的mousedown之后,windows控件焦点实际上会跑到button元素外层的那个元素所对应的windows控件(通常是TextBox控件)中。
如何证明这一点?我过去用过一个调试工具可以显示出每个html控件实际的windows控件,也能查看实际的windows系统焦点。不过现在想不起来那个工具的名称了。搞笑的是,此处还会出现一个非常orz的症状——也就是本文标题所称的“西方人通常发现不了的一个IE的bug”——可以证明这一点。
focus问题 + 西方人通常发现不了。各位是否已经猜到了呢?大家不妨用realazy的那个页面中的第一个按钮来直接实验一把。
我会在下篇blog中继续聊这个话题。
评论
hax
前天
fins 写道
按到底 是 down
抬起的一瞬间是 click
完全抬起时是 up
谁来告诉我一下 哪个系统是这么设计的了
swt ? j2me ? ...
你是不是跟dblclick混淆了?dblclick的行为是有不一致的。
fins
前天
你是怎么测试的??
================
我测试了一下 确实是我的错 呵呵
谢谢
我之前忘记了是被什么误导了 我一直以为
按到底 是 down
抬起的一瞬间是 click
完全抬起时是 up
谁来告诉我一下 哪个系统是这么设计的了
swt ? j2me ? ...
================
我测试了一下 确实是我的错 呵呵
我之前忘记了是被什么误导了 我一直以为
按到底 是 down
抬起的一瞬间是 click
完全抬起时是 up
谁来告诉我一下 哪个系统是这么设计的了
swt ? j2me ? ...
netix1999
前天
fins 写道
netix1999 写道
fins 写道
down click up 这是事件处理的顺序
在down里做一些事情确实危险
例如 alert一个东西 那么click事件 就不能被正确的触发了
在down里做一些事情确实危险
例如 alert一个东西 那么click事件 就不能被正确的触发了
事件顺序应该是 down up click 吧
你试验一下就知道了
对key 来说 keypress, keytype, keyrelease
对mouse来说 mousedown, mouseup, mouseclick
sutra
前天
楼主描述的问题好像不是bug吧,在keyup的时候聚焦或者取得文字就会如你所愿了:
--- settimeout_original.html 2008-05-11 23:41:23.000000000 +0900
+++ settimeout.html 2008-05-11 23:32:48.000000000 +0900
@@ -13,7 +13,7 @@
}
window.onload = function(){
- get('makeinput').onmousedown = function(){
+ get('makeinput').onmouseup = function(){
var input = document.createElement('input');
input.setAttribute('type', 'text');
input.setAttribute('value', 'test1');
@@ -31,7 +31,7 @@
input.select();
}, 0);
}
- get('input').onkeypress = function(){
+ get('input').onkeyup = function(){
get('preview').innerHTML = this.value;
}
}
--- settimeout_original.html 2008-05-11 23:41:23.000000000 +0900
+++ settimeout.html 2008-05-11 23:47:48.000000000 +0900
@@ -12,14 +12,18 @@
return document.getElementById(id);
}
+ var lastInput;
window.onload = function(){
get('makeinput').onmousedown = function(){
var input = document.createElement('input');
input.setAttribute('type', 'text');
input.setAttribute('value', 'test1');
get('inpwrapper').appendChild(input);
- input.focus();
- input.select();
+ lastInput = input;
+ }
+ get('makeinput').onmouseup = function() {
+ lastInput.focus();
+ lastInput.select();
}
get('makeinput2').onmousedown = function(){
var input = document.createElement('input');
@@ -31,7 +35,7 @@
input.select();
}, 0);
}
- get('input').onkeypress = function(){
+ get('input').onkeyup = function(){
get('preview').innerHTML = this.value;
}
}
fins
前天
netix1999 写道
fins 写道
down click up 这是事件处理的顺序
在down里做一些事情确实危险
例如 alert一个东西 那么click事件 就不能被正确的触发了
在down里做一些事情确实危险
例如 alert一个东西 那么click事件 就不能被正确的触发了
事件顺序应该是 down up click 吧
你试验一下就知道了
hax
前天
wacaoren 写道
为什么会焦点会移动到最上面的Settimeout上呢?而不是移动到靠近的那个settimeout上?
oh,我又看了一下,我原来对button元素的描述有误。点击它之后,焦点并不是跑到直接的父层元素,而是到canvas上去了。
实际上大多数元素你都会看到是插入到被点击的元素内部。更确切的说,插入到点击的那个点,就好像它成了一个编辑框,光标跑到了你点击的地方一样。比方说如果是<div>abcd</div>,你点击b和c之间,则插入的字符就到了b和c之间。
但是<button>元素和一般div之类的元素不同(包括与<input type=button>也不同)。测试结果表明<button>上的mousedown之后,焦点会跑到canvas(body或html元素)上,更确切的说是canvas上第一个插入点。至于说为什么会这样,看来只有问IE team了。。。
afcn0
前天
不是一般nb,非常nb,输入法和ie...电脑真奇妙
csf177
前天
太强了 这个应该报告给Ms啦 hoho
wacaoren
前天
为什么会焦点会移动到最上面的Settimeout上呢?而不是移动到靠近的那个settimeout上?
netix1999
前天
刚才用微软拼音,全拼,双拼,google拼音都试过了
是ie bug, 不是输入法的
是ie bug, 不是输入法的
achun
前天
我晕呀,
什么BUG呀,我说我怎么发现不了。
你用什么输入法呀!
我用google/sogou拼音都没有发现这个问题。
输入法的BUG吧!
什么BUG呀,我说我怎么发现不了。
你用什么输入法呀!
我用google/sogou拼音都没有发现这个问题。
输入法的BUG吧!
netix1999
2008-05-11
就当是个圣诞节彩蛋吧
hax
2008-05-11
呵呵。其实这个有趣的bug按说应该很容易被国人(还有日本人韩国人等需要输入法的)发现,不过不知道为什么一直未见有记载。
netix1999
2008-05-11
试了一下第一个例子
打开输入法点击"生成input”
页面的输入焦点就挪到setTimeout的label上了
再敲键就能在原先不可能接收输入的label上增加字符
牛逼,老外确实发现不了这个bug
打开输入法点击"生成input”
页面的输入焦点就挪到setTimeout的label上了
再敲键就能在原先不可能接收输入的label上增加字符
牛逼,老外确实发现不了这个bug
hax
2008-05-11
netix1999 写道
realazy的例子中
"另一个例子",如果没有打开输入法
onkeypress事件能正常激活
打开输入法后,输入的汉字就不能激活事件了
我很好奇 google 的搜索框中
打开输入法,当输入拼音,还没形成汉字进入输入框时
它的可选搜索结果就出现在下拉框中了
这是怎么实现的?
"另一个例子",如果没有打开输入法
onkeypress事件能正常激活
打开输入法后,输入的汉字就不能激活事件了
我很好奇 google 的搜索框中
打开输入法,当输入拼音,还没形成汉字进入输入框时
它的可选搜索结果就出现在下拉框中了
这是怎么实现的?
试试我说的那个(也就是第一个例子)吧。
关于onkeypress,实际上并没有标准可循。一般浏览器都会将所输入的完整字符作为keypress事件。将来也许会标准化为textinput事件。使用输入法时,输入的字母并不会最后形成完整字符,自然不会触发keypress。
google可能用的keydown事件。Windows输入法上有个特点,keydown事件还是会出现的,但是keyup和keypress事件则不会出现。实际上IE中的这些事件貌似是直接对应某几种windows消息(又,我忘记具体消息名称了),而且我记得是会出现keyup事件,但是keycode与keydown的keycode值不一样,是一个固定的表示输入法消息的值。
netix1999
2008-05-11
fins 写道
down click up 这是事件处理的顺序
在down里做一些事情确实危险
例如 alert一个东西 那么click事件 就不能被正确的触发了
在down里做一些事情确实危险
例如 alert一个东西 那么click事件 就不能被正确的触发了
事件顺序应该是 down up click 吧
netix1999
2008-05-11
realazy的例子中
"另一个例子",如果没有打开输入法
onkeypress事件能正常激活
打开输入法后,输入的汉字就不能激活事件了
我很好奇 google 的搜索框中
打开输入法,当输入拼音,还没形成汉字进入输入框时
它的可选搜索结果就出现在下拉框中了
这是怎么实现的?
"另一个例子",如果没有打开输入法
onkeypress事件能正常激活
打开输入法后,输入的汉字就不能激活事件了
我很好奇 google 的搜索框中
打开输入法,当输入拼音,还没形成汉字进入输入框时
它的可选搜索结果就出现在下拉框中了
这是怎么实现的?
hax
2008-05-11
afcn0 写道
西方人发现不了,是因为输入法,焦点在输入法和ie之间大概会有问题的意思吧
bingo. 请try一下我ding楼给的realazy的原有例子罢。
BTW,JE的编辑器说我这篇有“我ding”之类的嫌疑。。。难道是因为ding楼这个词??这也太敏感了罢。
laurince
2008-05-11
咖啡舞者 写道
hax 写道
achun 写道
hax 写道
fins 写道
不知道为什么 西方人发现不了
开动脑筋啊。一样使用IE,我们跟西方人有什么区别呢?
还没有明显发现,不过发现如果点鼠标的中建(波轮),selected生效.
还有就是如果出滚动条的话,focus生效(FF也是这样).这个不算BUG吧!也就是特性吧.
大家加油喔。什么东西偶们使用,但是西方人不用的呢?
西方人一般不用IE?
还是说西方人页面根本不那么花哨?简简单单~?
大概是说输入法了? 还是请老大别卖关子了
yesterday
2008-05-10
跟语言有关系?
发表评论
提醒: 该博客已发表在公共论坛,博客所有留言会成为论坛回贴,留言请注意遵守论坛发贴规则
- 浏览: 124397 次
- 性别:

- 来自: 上海

- 详细资料
搜索本博客
最近加入圈子
最新评论
-
两篇预测2008年川滇强震的 ...
貌似,马后炮啊
-- by laitaogood -
两篇预测2008年川滇强震的 ...
追寻唐山大地震漏报真相( 2006-10-30 16:39:02 ) 唐山大地 ...
-- by hax -
两篇预测2008年川滇强震的 ...
-- by lordhong -
测试一下你属于哪种人
一个有意思的问题!不过好像有点标题党的嫌疑哦!:)
-- by zqrain -
地震了,我咋没感觉
晕,我昨天头晕的厉害,所有人都以为自己病了。我在望京这边一栋大厦的六楼。
-- by s79






评论排行榜