从谷歌的一个Bug说起,谈谈键盘事件的兼容性

上面是谷歌首页,当输入某个词时,下面会弹出自动补全提示。功能并不复杂,但考虑到要兼容各个浏览器,谷歌为此可能花费了不少功夫。然而完美实在是很难得,谷歌首页上一直有一个处理得不妥的Bug:

除了Ctrl+X/C/V,Ctrl+Z/Y也是经常使用的快捷键。在Firefox/Safari/Opera中访问谷歌,一切都很正常。但当我们打开IE浏览谷歌时,Ctrl+Z/Y不起作用了。在当今特别是中国,IE是份量最重的浏览器,谷歌首页有此问题,完全可以归为一个Bug.

这个Bug究竟是怎么引起的呢?为了进一步讨论,我们先来看看各个浏览器下,当输入法开启和未开启时,对键盘等事件的响应情况。

猛击查看 JavaScript键盘事件测试小结

通过上面这篇测试小结,我们可以看出,要实现谷歌的自动补全功能并不是一件很简单的事。目前可以找到的解决方案有:

方案一:通过监听keydown, keypress, keyup事件来实现。这是大部分JavaScript教科书里的做法,对于拉丁语系国家,是没有问题的。但输入法一开启后,一切就都不美妙了:

  1. 无论有没有输入法,通过鼠标右键粘贴复制时,key事件都触发不了,真糟糕。
  2. 输入法开启时,各个浏览器表现不同。不同输入法之间还有差异,太让人沮丧了。
  3. 输入法开启时,Opera压根不触发键盘事件。亲爱的Opera,叫我怎么爱上你?

考虑到中文用户,特别是第一条(不少中文用户习惯使用右键菜单来粘贴复制),第一个方案基本可以枪毙掉。

方案二:不考虑这些烦人的键盘事件,直接采用定时器来实现。在输入框获取焦点时,触发定时器,失去焦点时,关闭定时器。定时器每隔200ms检查输入框的值,根据值的变化来进行下一步响应。这个trick很简单,基本上能解决大部分问题(谷歌的自动完成就是这么做的^o^)。但有以下不妥:

  1. 性能问题。(因为仅在获取焦点时触发定时器,性能问题倒是可以不考虑的)
  2. ie下,此方法会导致Ctrl+Z/Y快捷键失效。
  3. firefox下,用定时器实现表单输入时的即时校验,当输入法开启时,如果校验函数在输入未完成时改变输入框的值,会导致输入框的值变成空。(这个属于不可忽视的Bug,很恼人)

方案二自动解决了右键菜单粘贴的问题,对于自动补全功能来说,一般应用场景下也足够用,但对谷歌来说,感觉有此Bug是不妥的。如果用方案二来实现表单输入时的即时校验,上面的第3点会导致firefox的中文用户很不爽。

苦思冥想许久,在键盘事件中折腾来折腾去,感觉怎么做都无法同时解决上面的所有不妥。昨天静下心来对所有A级浏览器的键盘事件在输入法开启和未开启时做了个仔细的测试后,下面这个方案就很清晰的浮了出来:

方案三:在上面的浏览器事件测试中,有一个很让人高兴的发现:所有浏览器中,都会触发input(ie下可以用propertychange)事件。而 且input事件仅在输入框的值有变化时才会触发。在输入法开启时,input也能正常触发(虽然会触发一些冗余的input,但比起定时器来好很多)。 在右键菜单粘贴等操作时,也能正确触发input. 采用input/propertychange, 几近完美。但需要注意以下几点:

  1. ie下,如果监听的事件函数中,有页面输出操作,如YAHOO.log(…), 会导致Ctrl+Z/Y失效。(深层次原因还需仔细探索,感觉页面输出操作只是表象)
  2. 对于表单输入时的即时校验来说,比如只能输入数字的输入框,当输入字母时,监听input事件的实现会在字母显示出来后,立刻又删除掉(和 keyup的实现效果一样),没有监听keypress的效果好(不会先显示出来)。因此对于即时校验来说,可以结合input和keypress,在输 入法未开启时,给用户更友好的体验。

最后,看一个根据方案三来实现的简单例子:表单输入时的即时校验

参考资料

转载于:https://www.cnblogs.com/a-jian/archive/2011/03/14/1983332.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值